@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
@@ -5,31 +5,30 @@ import deepEqual from 'fast-deep-equal';
5
5
  import * as React from 'react';
6
6
  import { isValidElementType } from 'react-is';
7
7
  import useLatestCallback from 'use-latest-callback';
8
+ import { ConsumedParamsContext } from "./ConsumedParamsContext.js";
8
9
  import { deepFreeze } from "./deepFreeze.js";
9
10
  import { Group } from "./Group.js";
10
11
  import { isArrayEqual } from "./isArrayEqual.js";
11
- import { isRecordEqual } from "./isRecordEqual.js";
12
- import { NavigationBuilderContext } from "./NavigationBuilderContext.js";
12
+ import { useNavigationBuilderContext } from "./NavigationBuilderContext.js";
13
13
  import { NavigationHelpersContext } from "./NavigationHelpersContext.js";
14
- import { NavigationMetaContext } from "./NavigationMetaContext.js";
15
- import { NavigationRouteContext } from "./NavigationProvider.js";
14
+ import { IsScreenContext, NavigationRouteContext } from "./NavigationProvider.js";
16
15
  import { NavigationStateContext } from "./NavigationStateContext.js";
17
16
  import { PreventRemoveProvider } from "./PreventRemoveProvider.js";
18
17
  import { Screen } from "./Screen.js";
19
18
  import { PrivateValueStore } from "./types.js";
20
19
  import { UnhandledActionContext } from "./UnhandledActionContext.js";
21
20
  import { useChildListeners } from "./useChildListeners.js";
22
- import { useComponent } from "./useComponent.js";
23
- import { useCurrentRender } from "./useCurrentRender.js";
24
21
  import { useDescriptors } from "./useDescriptors.js";
25
22
  import { useEventEmitter } from "./useEventEmitter.js";
26
23
  import { useFocusedListenersChildrenAdapter } from "./useFocusedListenersChildrenAdapter.js";
27
24
  import { useFocusEvents } from "./useFocusEvents.js";
25
+ import { FocusedRouteKeyContext } from "./useIsFocused.js";
28
26
  import { useKeyedChildListeners } from "./useKeyedChildListeners.js";
29
27
  import { useLazyValue } from "./useLazyValue.js";
30
28
  import { useNavigationHelpers } from "./useNavigationHelpers.js";
31
29
  import { NavigationStateListenerProvider } from "./useNavigationState.js";
32
30
  import { useOnAction } from "./useOnAction.js";
31
+ import { useOnGetNavigation } from "./useOnGetNavigation.js";
33
32
  import { useOnGetState } from "./useOnGetState.js";
34
33
  import { useOnRouteFocus } from "./useOnRouteFocus.js";
35
34
  import { useRegisterNavigator } from "./useRegisterNavigator.js";
@@ -39,6 +38,7 @@ import { useScheduleUpdate } from "./useScheduleUpdate.js";
39
38
  // eslint-disable-next-line @typescript-eslint/no-unused-expressions
40
39
  import { jsx as _jsx } from "react/jsx-runtime";
41
40
  PrivateValueStore;
41
+ const isNavigationState = state => state != null && typeof state === 'object' && 'routes' in state && Array.isArray(state.routes);
42
42
  const isScreen = child => {
43
43
  return child.type === Screen;
44
44
  };
@@ -52,7 +52,7 @@ const isValidKey = key => key === undefined || typeof key === 'string' && key !=
52
52
  *
53
53
  * @param children React Elements to extract the config from.
54
54
  */
55
- const getRouteConfigsFromChildren = (children, groupKey, groupOptions, groupLayout) => {
55
+ const getRouteConfigsFromChildren = (children, groupKeys = [], groupOptions, groupLayout) => {
56
56
  const configs = React.Children.toArray(children).reduce((acc, child) => {
57
57
  if (/*#__PURE__*/React.isValidElement(child)) {
58
58
  if (isScreen(child)) {
@@ -69,7 +69,7 @@ const getRouteConfigsFromChildren = (children, groupKey, groupOptions, groupLayo
69
69
  throw new Error(`Got an invalid 'navigationKey' prop (${JSON.stringify(child.props.navigationKey)}) for the screen '${child.props.name}'. It must be a non-empty string or 'undefined'.`);
70
70
  }
71
71
  acc.push({
72
- keys: [groupKey, child.props.navigationKey],
72
+ keys: [...groupKeys, child.props.navigationKey],
73
73
  options: groupOptions,
74
74
  layout: groupLayout,
75
75
  props: child.props
@@ -83,14 +83,14 @@ const getRouteConfigsFromChildren = (children, groupKey, groupOptions, groupLayo
83
83
 
84
84
  // When we encounter a fragment or group, we need to dive into its children to extract the configs
85
85
  // This is handy to conditionally define a group of screens
86
- acc.push(...getRouteConfigsFromChildren(child.props.children, child.props.navigationKey,
86
+ acc.push(...getRouteConfigsFromChildren(child.props.children, child.props.navigationKey != null ? [...groupKeys, child.props.navigationKey] : groupKeys,
87
87
  // FIXME
88
88
  // @ts-expect-error: add validation
89
89
  child.type !== Group ? groupOptions : groupOptions != null ? [...groupOptions, child.props.screenOptions] : [child.props.screenOptions], typeof child.props.screenLayout === 'function' ? child.props.screenLayout : groupLayout));
90
90
  return acc;
91
91
  }
92
92
  }
93
- throw new Error(`A navigator can only contain 'Screen', 'Group' or 'React.Fragment' as its direct children (found ${/*#__PURE__*/React.isValidElement(child) ? `'${typeof child.type === 'string' ? child.type : child.type?.name}'${child.props != null && typeof child.props === 'object' && 'name' in child.props && child.props?.name ? ` for the screen '${child.props.name}'` : ''}` : typeof child === 'object' ? JSON.stringify(child) : `'${String(child)}'`}). To render this component in the navigator, pass it in the 'component' prop to 'Screen'.`);
93
+ throw new Error(`A navigator can only contain 'Screen', 'Group' or 'React.Fragment' as its direct children (found ${ /*#__PURE__*/React.isValidElement(child) ? `'${typeof child.type === 'string' ? child.type : child.type?.name}'${child.props != null && typeof child.props === 'object' && 'name' in child.props && child.props?.name ? ` for the screen '${child.props.name}'` : ''}` : typeof child === 'object' ? JSON.stringify(child) : `'${String(child)}'`}). To render this component in the navigator, pass it in the 'component' prop to 'Screen'.`);
94
94
  }, []);
95
95
  if (process.env.NODE_ENV !== 'production') {
96
96
  configs.forEach(config => {
@@ -136,9 +136,16 @@ const getRouteConfigsFromChildren = (children, groupKey, groupOptions, groupLayo
136
136
  }
137
137
  return configs;
138
138
  };
139
- const getStateFromParams = params => {
140
- if (params?.state != null) {
141
- return params.state;
139
+ const getStateFromParams = (params, type) => {
140
+ const state = params?.state;
141
+ if (isNavigationState(state)) {
142
+ if (state.type != null && state.type !== type) {
143
+ if (process.env.NODE_ENV !== 'production') {
144
+ console.error(`The state passed in the params is for a navigator of type '${state.type}', but it was passed to a navigator of type '${type}'. This can happen if the state was meant for a different navigator. The state will be discarded.`);
145
+ }
146
+ return undefined;
147
+ }
148
+ return state;
142
149
  } else if (typeof params?.screen === 'string' && params?.initial !== false) {
143
150
  return {
144
151
  routes: [{
@@ -160,7 +167,9 @@ const getStateFromParams = params => {
160
167
  */
161
168
  export function useNavigationBuilder(createRouter, options) {
162
169
  const navigatorKey = useRegisterNavigator();
163
- const route = React.useContext(NavigationRouteContext);
170
+ const route = React.use(NavigationRouteContext);
171
+ const consumedParams = React.use(ConsumedParamsContext);
172
+ const isNestedParamsConsumed = typeof route?.params === 'object' && route.params != null ? consumedParams?.has(route.params) : false;
164
173
  const {
165
174
  children,
166
175
  layout,
@@ -185,31 +194,26 @@ export function useNavigationBuilder(createRouter, options) {
185
194
  }
186
195
  return original;
187
196
  });
188
- const screens = routeConfigs.reduce((acc, config) => {
189
- if (config.props.name in acc) {
190
- throw new Error(`A navigator cannot contain multiple 'Screen' components with the same name (found duplicate screen named '${config.props.name}')`);
191
- }
192
- acc[config.props.name] = config;
193
- return acc;
194
- }, {});
195
197
  const routeNames = routeConfigs.map(config => config.props.name);
196
- const routeKeyList = routeNames.reduce((acc, curr) => {
197
- acc[curr] = screens[curr].keys.map(key => key ?? '').join(':');
198
- return acc;
199
- }, {});
200
- const routeParamList = routeNames.reduce((acc, curr) => {
201
- const {
202
- initialParams
203
- } = screens[curr].props;
204
- acc[curr] = initialParams;
205
- return acc;
206
- }, {});
207
- const routeGetIdList = routeNames.reduce((acc, curr) => Object.assign(acc, {
208
- [curr]: screens[curr].props.getId
209
- }), {});
210
198
  if (!routeNames.length) {
211
199
  throw new Error("Couldn't find any screens for the navigator. Have you defined any screens as its children?");
212
200
  }
201
+ const screens = {};
202
+ const routeKeyList = {};
203
+ const routeParamList = {};
204
+ const routeGetIdList = {};
205
+ for (const config of routeConfigs) {
206
+ const name = config.props.name;
207
+ if (name in screens) {
208
+ throw new Error(`A navigator cannot contain multiple 'Screen' components with the same name (found duplicate screen named '${name}')`);
209
+ }
210
+ screens[name] = config;
211
+ routeKeyList[name] = config.keys;
212
+ routeParamList[name] = config.props.initialParams;
213
+ Object.assign(routeGetIdList, {
214
+ [name]: config.props.getId
215
+ });
216
+ }
213
217
  const isStateValid = React.useCallback(state => state.type === undefined || state.type === router.type, [router.type]);
214
218
  const isStateInitialized = React.useCallback(state => state !== undefined && state.stale === false && isStateValid(state), [isStateValid]);
215
219
  const doesStateHaveOnlyInvalidRoutes = React.useCallback(state => state.routes.every(r => !routeNames.includes(r.name)), [routeNames]);
@@ -217,25 +221,52 @@ export function useNavigationBuilder(createRouter, options) {
217
221
  state: currentState,
218
222
  getState: getCurrentState,
219
223
  setState: setCurrentState,
224
+ subscribe,
220
225
  setKey,
221
226
  getKey,
222
227
  getIsInitial
223
- } = React.useContext(NavigationStateContext);
224
- const stateCleanedUp = React.useRef(false);
228
+ } = React.use(NavigationStateContext);
229
+ const {
230
+ onEmitEvent,
231
+ getIsStateEmitted,
232
+ canGoBack: canGoBackParent
233
+ } = useNavigationBuilderContext();
234
+ const mountStateRef = React.useRef('initial');
235
+ const previousStateRef = React.useRef(currentState);
236
+ const savedStateRef = React.useRef(undefined);
225
237
  const setState = useLatestCallback(state => {
226
- if (stateCleanedUp.current) {
238
+ if (mountStateRef.current === 'unmounted') {
239
+ // Store the state locally in case the current navigator is in `Activity`
240
+ savedStateRef.current = state;
241
+
227
242
  // State might have been already cleaned up due to unmount
228
- // We do not want to expose API allowing to override this
229
- // This would lead to old data preservation on main navigator unmount
243
+ // We don't want to update `route.state` in parent
244
+ // Otherwise it will be reused if a new navigator gets mounted
230
245
  return;
231
246
  }
232
247
  setCurrentState(state);
233
248
  });
234
- const [stateBeforeInitialization, initializedState, isFirstStateInitialization] = React.useMemo(() => {
249
+ const lastState = (mountStateRef.current !== 'mounted' || !isStateInitialized(currentState)) && (
250
+ // If the state object differs from previously committed state, we have new state
251
+ // e.g. because of a reset
252
+ // So we need to use it before checking if we should reuse the saved state.
253
+ currentState === previousStateRef.current || mountStateRef.current === 'unmounted' && currentState === undefined) ?
254
+ // If the navigator is hidden with `Activity`, its state gets cleaned up due to effect cleanup.
255
+ // So we reuse the saved state to avoid remounting screens when the navigator is shown again.
256
+ savedStateRef.current : undefined;
257
+ const [stateBeforeInitialization, initializedState, isFirstStateInitialization, paramsUsedForInitialization] = React.useMemo(() => {
258
+ if (lastState && isStateValid(lastState)) {
259
+ const state = isStateInitialized(lastState) ? lastState : router.getRehydratedState(lastState, {
260
+ routeNames,
261
+ routeParamList,
262
+ routeGetIdList
263
+ });
264
+ return [undefined, state, false, undefined];
265
+ }
235
266
  const initialRouteParamList = routeNames.reduce((acc, curr) => {
236
267
  const {
237
268
  initialParams
238
- } = screens[curr].props;
269
+ } = screens[curr]?.props ?? {};
239
270
  const initialParamsFromParams = route?.params?.state == null && route?.params?.initial !== false && route?.params?.screen === curr ? route.params.params : undefined;
240
271
  acc[curr] = initialParams !== undefined || initialParamsFromParams !== undefined ? {
241
272
  ...initialParams,
@@ -248,24 +279,32 @@ export function useNavigationBuilder(createRouter, options) {
248
279
  // We also need to re-initialize it if the state passed from parent was changed (maybe due to reset)
249
280
  // Otherwise assume that the state was provided as initial state
250
281
  // So we need to rehydrate it to make it usable
251
- if ((currentState === undefined || !isStateValid(currentState)) && route?.params?.state == null && !(typeof route?.params?.screen === 'string' && route?.params?.initial !== false)) {
282
+ if ((currentState === undefined || !isStateValid(currentState)) && route?.params?.state == null && !(typeof route?.params?.screen === 'string' && route?.params?.initial !== false) && !isNestedParamsConsumed) {
252
283
  return [undefined, router.getInitialState({
253
284
  routeNames,
254
285
  routeParamList: initialRouteParamList,
255
286
  routeGetIdList
256
- }), true];
287
+ }), true, undefined];
257
288
  } else {
258
- const stateFromParams = getStateFromParams(route?.params);
289
+ const paramsForState = isNestedParamsConsumed ? undefined : route?.params;
290
+ const stateFromParams = paramsForState ? getStateFromParams(paramsForState, router.type) : undefined;
259
291
  const stateBeforeInitialization = stateFromParams ?? currentState;
260
- const hydratedState = router.getRehydratedState(stateBeforeInitialization, {
292
+ const hydratedState = stateBeforeInitialization == null ? router.getInitialState({
293
+ routeNames,
294
+ routeParamList: initialRouteParamList,
295
+ routeGetIdList
296
+ }) : router.getRehydratedState(stateBeforeInitialization, {
261
297
  routeNames,
262
298
  routeParamList: initialRouteParamList,
263
299
  routeGetIdList
264
300
  });
265
- if (options.routeNamesChangeBehavior === 'lastUnhandled' && doesStateHaveOnlyInvalidRoutes(stateBeforeInitialization)) {
266
- return [stateBeforeInitialization, hydratedState, true];
301
+ if (stateBeforeInitialization != null && isStateValid(stateBeforeInitialization) && options.routeNamesChangeBehavior === 'lastUnhandled' && doesStateHaveOnlyInvalidRoutes(stateBeforeInitialization)) {
302
+ return [stateBeforeInitialization, hydratedState, true, paramsForState];
267
303
  }
268
- return [undefined, hydratedState, false];
304
+ return [undefined, hydratedState, false,
305
+ // Current state is already initialized
306
+ // So params weren't used, and need to be handled later
307
+ isStateInitialized(currentState) ? undefined : paramsForState];
269
308
  }
270
309
  // We explicitly don't include routeNames, route.params etc. in the dep list
271
310
  // below. We want to avoid forcing a new state to be calculated in those cases
@@ -273,12 +312,19 @@ export function useNavigationBuilder(createRouter, options) {
273
312
  // that some changes to routeConfigs are explicitly ignored, such as changes
274
313
  // to initialParams
275
314
  // eslint-disable-next-line react-hooks/exhaustive-deps
276
- }, [currentState, router, isStateValid]);
315
+ }, [currentState, lastState, router, isStateValid]);
277
316
  const previousRouteKeyListRef = React.useRef(routeKeyList);
278
- React.useEffect(() => {
317
+ React.useInsertionEffect(() => {
279
318
  previousRouteKeyListRef.current = routeKeyList;
280
319
  });
281
320
  const previousRouteKeyList = previousRouteKeyListRef.current;
321
+
322
+ // Names of the screens whose navigation key changed since the last render
323
+ const routeKeyChanges = Object.keys(routeKeyList).filter(name => {
324
+ const current = routeKeyList[name];
325
+ const previous = previousRouteKeyList[name];
326
+ return current != null && previous != null && !isArrayEqual(current, previous);
327
+ });
282
328
  const [unhandledState, setUnhandledState] = React.useState(stateBeforeInitialization);
283
329
 
284
330
  // An unhandled state is state that didn't have any valid routes
@@ -292,60 +338,68 @@ export function useNavigationBuilder(createRouter, options) {
292
338
  // If the state isn't initialized, or stale, use the state we initialized instead
293
339
  // The state won't update until there's a change needed in the state we have initialized locally
294
340
  // So it'll be `undefined` or stale until the first navigation event happens
295
- isStateInitialized(currentState) ? currentState : initializedState;
341
+ lastState === undefined && isStateInitialized(currentState) ? currentState : initializedState;
296
342
  let nextState = state;
297
343
  let shouldClearUnhandledState = false;
298
-
344
+ if (unhandledState != null && !isStateValid(unhandledState)) {
345
+ // The stored unhandled state is for a different type of navigator
346
+ // It can't be used with this navigator, so we discard it
347
+ setUnhandledState(undefined);
348
+ } else if (
299
349
  // Previously unhandled state is now valid again
300
350
  // And current state no longer has any valid routes
301
351
  // We should reuse the unhandled state instead of re-calculating the state
302
- if (unhandledState?.routes.every(r => routeNames.includes(r.name)) && state?.routes.every(r => !routeNames.includes(r.name))) {
352
+ unhandledState?.routes.every(r => routeNames.includes(r.name)) && state?.routes.every(r => !routeNames.includes(r.name))) {
303
353
  shouldClearUnhandledState = true;
304
354
  nextState = router.getRehydratedState(unhandledState, {
305
355
  routeNames,
306
356
  routeParamList,
307
357
  routeGetIdList
308
358
  });
309
- } else if (!isArrayEqual(state.routeNames, routeNames) || !isRecordEqual(routeKeyList, previousRouteKeyList)) {
359
+ } else if (!isArrayEqual(state.routeNames, routeNames) || routeKeyChanges.length !== 0) {
310
360
  // When the list of route names change, the router should handle it to remove invalid routes
311
361
  nextState = router.getStateForRouteNamesChange(state, {
312
362
  routeNames,
313
363
  routeParamList,
314
364
  routeGetIdList,
315
- routeKeyChanges: Object.keys(routeKeyList).filter(name => name in previousRouteKeyList && routeKeyList[name] !== previousRouteKeyList[name])
365
+ routeKeyChanges
316
366
  });
317
367
  }
318
- const previousNestedParamsRef = React.useRef(route?.params);
319
- React.useEffect(() => {
320
- previousNestedParamsRef.current = route?.params;
321
- }, [route?.params]);
322
- if (route?.params) {
323
- const previousParams = previousNestedParamsRef.current;
368
+ let didConsumeNestedParams = route?.params === paramsUsedForInitialization;
369
+ if (route?.params && !didConsumeNestedParams) {
324
370
  let action;
325
- if (typeof route.params.state === 'object' && route.params.state != null && route.params !== previousParams) {
326
- if (options.routeNamesChangeBehavior === 'lastUnhandled' && doesStateHaveOnlyInvalidRoutes(route.params.state)) {
327
- if (route.params.state !== unhandledState) {
328
- setUnhandledState(route.params.state);
371
+ if (isNavigationState(route.params.state) && !isNestedParamsConsumed) {
372
+ didConsumeNestedParams = true;
373
+ const stateFromParams = getStateFromParams(route.params, router.type);
374
+ if (stateFromParams != null) {
375
+ if (options.routeNamesChangeBehavior === 'lastUnhandled' && doesStateHaveOnlyInvalidRoutes(stateFromParams)) {
376
+ if (stateFromParams !== unhandledState) {
377
+ setUnhandledState(stateFromParams);
378
+ }
379
+ } else {
380
+ // If the route was updated with new state, we should reset to it
381
+ action = CommonActions.reset(stateFromParams);
329
382
  }
330
- } else {
331
- // If the route was updated with new state, we should reset to it
332
- action = CommonActions.reset(route.params.state);
333
383
  }
334
- } else if (typeof route.params.screen === 'string' && (route.params.initial === false && isFirstStateInitialization || route.params !== previousParams)) {
384
+ } else if (typeof route.params.screen === 'string' && (route.params.initial === false && isFirstStateInitialization || !isNestedParamsConsumed)) {
385
+ didConsumeNestedParams = true;
335
386
  if (options.routeNamesChangeBehavior === 'lastUnhandled' && !routeNames.includes(route.params.screen)) {
336
- const state = getStateFromParams(route.params);
387
+ const state = getStateFromParams(route.params, router.type);
337
388
  if (state != null && !deepEqual(state, unhandledState)) {
338
389
  setUnhandledState(state);
339
390
  }
340
391
  } else {
341
392
  // If the route was updated with new screen name and/or params, we should navigate there
342
- action = CommonActions.navigate({
343
- name: route.params.screen,
344
- params: route.params.params,
345
- path: route.params.path,
346
- merge: route.params.merge,
347
- pop: route.params.pop
348
- });
393
+ action = {
394
+ type: 'NAVIGATE',
395
+ payload: {
396
+ name: route.params.screen,
397
+ params: route.params.params,
398
+ path: route.params.path,
399
+ merge: route.params.merge,
400
+ pop: route.params.pop
401
+ }
402
+ };
349
403
  }
350
404
  }
351
405
 
@@ -355,16 +409,25 @@ export function useNavigationBuilder(createRouter, options) {
355
409
  routeParamList,
356
410
  routeGetIdList
357
411
  }) : null;
412
+ if (process.env.NODE_ENV !== 'production' && action != null && updatedState === null) {
413
+ const names = routeNames.map(name => `'${name}'`).join(', ');
414
+ console.error(`The 'state' or 'screen' passed in the params couldn't be applied to the navigator with the screens: ${names}. This can happen if the params contain names of screens that don't exist in the navigator. The navigation specified in the params will be ignored.`);
415
+ }
358
416
  nextState = updatedState !== null ? router.getRehydratedState(updatedState, {
359
417
  routeNames,
360
418
  routeParamList,
361
419
  routeGetIdList
362
420
  }) : nextState;
363
421
  }
364
- const shouldUpdate = state !== nextState || typeof route?.params?.state === 'object' || typeof route?.params?.screen === 'string';
422
+ React.useInsertionEffect(() => {
423
+ if (consumedParams && didConsumeNestedParams && typeof route?.params === 'object' && route.params != null) {
424
+ consumedParams.set(route.params, true);
425
+ }
426
+ }, [consumedParams, didConsumeNestedParams, route?.params]);
427
+ const shouldUpdate = state !== nextState;
365
428
  useScheduleUpdate(() => {
366
429
  if (shouldUpdate) {
367
- // If the state needs to be updated, we'll schedule an update
430
+ // Schedule an update if the state needs to be updated
368
431
  setState(nextState);
369
432
  if (shouldClearUnhandledState) {
370
433
  setUnhandledState(undefined);
@@ -376,44 +439,52 @@ export function useNavigationBuilder(createRouter, options) {
376
439
  // We can't use the outdated state since the screens have changed, which will cause error due to mismatched config
377
440
  // So we override the state object we return to use the latest state as soon as possible
378
441
  state = nextState;
442
+ React.useInsertionEffect(() => {
443
+ savedStateRef.current = state;
444
+ previousStateRef.current = currentState;
445
+ });
446
+ React.useInsertionEffect(() => {
447
+ return () => {
448
+ // An initially hidden Activity doesn't run passive effects or their cleanup.
449
+ // We mark actual unmount here so queued updates can't write state into a replacement navigator.
450
+ mountStateRef.current = 'unmounted';
451
+ };
452
+ }, []);
379
453
  React.useEffect(() => {
454
+ const savedState = savedStateRef.current ?? state;
455
+
380
456
  // In strict mode, React will double-invoke effects.
381
- // So we need to reset the flag if component was not unmounted
382
- stateCleanedUp.current = false;
457
+ // So we need to reset the status if component was not unmounted
458
+ mountStateRef.current = 'mounted';
383
459
  setKey(navigatorKey);
384
- if (!getIsInitial()) {
385
- // If it's not initial render, we need to update the state
386
- // This will make sure that our container gets notifier of state changes due to new mounts
460
+ if (!getIsInitial() || getIsStateEmitted()) {
461
+ // We need to notify the state update in these scenarios:
462
+ // 1. If it's not the initial render of the component containing the navigator
463
+ // 2. If the container has already emitted state before the navigator mounted
464
+ //
465
+ // This will make sure that the container gets notified of state changes due to new mounts
387
466
  // This is necessary for proper screen tracking, URL updates etc.
388
- setState(nextState);
467
+ //
468
+ // During hydration, a nested navigator may mount after the container's initial state event.
469
+ // Or mount could be delayed due to conditional rendering, suspense etc.
470
+ // So only checking for the initial render is not enough.
471
+ // We also need to propagate the navigator's initial state when it mounts later,
472
+ // so the container is notified that the nested state is now available.
473
+ setState(savedState);
389
474
  }
390
475
  return () => {
391
476
  // We need to clean up state for this navigator on unmount
392
477
  if (getCurrentState() !== undefined && getKey() === navigatorKey) {
393
478
  setCurrentState(undefined);
394
- stateCleanedUp.current = true;
395
479
  }
480
+ mountStateRef.current = 'unmounted';
396
481
  };
397
482
  // eslint-disable-next-line react-hooks/exhaustive-deps
398
483
  }, []);
399
-
400
- // In some cases (e.g. route names change), internal state might have changed
401
- // But it hasn't been committed yet, so hasn't propagated to the sync external store
402
- // During this time, we need to return the internal state in `getState`
403
- // Otherwise it can result in inconsistent state during render in children
404
- // To avoid this, we use a ref for render phase, and immediately clear it on commit
405
- const stateRef = React.useRef(state);
406
- stateRef.current = state;
407
- React.useLayoutEffect(() => {
408
- stateRef.current = null;
409
- });
410
484
  const getState = useLatestCallback(() => {
411
- const currentState = getCurrentState();
485
+ const currentState = mountStateRef.current === 'unmounted' ? savedStateRef.current : getCurrentState();
412
486
  return deepFreeze(isStateInitialized(currentState) ? currentState : initializedState);
413
487
  });
414
- const {
415
- onEmitEvent
416
- } = React.useContext(NavigationBuilderContext);
417
488
  const emitter = useEventEmitter(e => {
418
489
  const routeNames = [];
419
490
  let route;
@@ -429,32 +500,33 @@ export function useNavigationBuilder(createRouter, options) {
429
500
  if (route == null) {
430
501
  return;
431
502
  }
432
- const navigation = descriptors[route.key].navigation;
433
- const listeners = [].concat(
434
- // Get an array of listeners for all screens + common listeners on navigator
435
- ...[screenListeners, ...routeNames.map(name => {
436
- const {
437
- listeners
438
- } = screens[name].props;
439
- return listeners;
440
- })].map(listeners => {
441
- const map = typeof listeners === 'function' ? listeners({
442
- route: route,
443
- navigation
444
- }) : listeners;
445
- return map ? Object.keys(map).filter(type => type === e.type).map(type => map?.[type]) : undefined;
446
- }))
447
- // We don't want same listener to be called multiple times for same event
448
- // So we remove any duplicate functions from the array
449
- .filter((cb, i, self) => cb && self.lastIndexOf(cb) === i);
450
- listeners.forEach(listener => listener?.(e));
451
- onEmitEvent({
452
- type: e.type,
453
- data: e.data,
454
- target: e.target,
455
- defaultPrevented: e.defaultPrevented
456
- });
457
- });
503
+ const hasPerScreenListeners = routeNames.some(name => screens[name]?.props.listeners != null);
504
+ if (screenListeners != null || hasPerScreenListeners) {
505
+ const descriptor = descriptors[route.key];
506
+ if (descriptor == null) {
507
+ throw new Error(`Couldn't find a descriptor for route '${route.key}'.`);
508
+ }
509
+ const navigation = descriptor.navigation;
510
+ const listeners = [].concat(
511
+ // Get an array of listeners for all screens + common listeners on navigator
512
+ ...[screenListeners, ...routeNames.map(name => {
513
+ const {
514
+ listeners
515
+ } = screens[name]?.props ?? {};
516
+ return listeners;
517
+ })].map(listeners => {
518
+ const map = typeof listeners === 'function' ? listeners({
519
+ route: route,
520
+ navigation
521
+ }) : listeners;
522
+ return map ? Object.keys(map).filter(type => type === e.type).map(type => map?.[type]) : undefined;
523
+ }))
524
+ // We don't want same listener to be called multiple times for same event
525
+ // So we remove any duplicate functions from the array
526
+ .filter((cb, i, self) => cb && self.lastIndexOf(cb) === i);
527
+ listeners.forEach(listener => listener?.(e));
528
+ }
529
+ }, onEmitEvent);
458
530
  useFocusEvents({
459
531
  state,
460
532
  emitter
@@ -495,7 +567,7 @@ export function useNavigationBuilder(createRouter, options) {
495
567
  getState,
496
568
  setState
497
569
  });
498
- const onUnhandledActionParent = React.useContext(UnhandledActionContext);
570
+ const onUnhandledActionParent = React.use(UnhandledActionContext);
499
571
  const onUnhandledAction = useLatestCallback(action => {
500
572
  if (options.routeNamesChangeBehavior === 'lastUnhandled' && action.type === 'NAVIGATE' && action.payload != null && 'name' in action.payload && typeof action.payload.name === 'string' && !routeNames.includes(action.payload.name)) {
501
573
  const state = {
@@ -509,13 +581,28 @@ export function useNavigationBuilder(createRouter, options) {
509
581
  }
510
582
  onUnhandledActionParent?.(action);
511
583
  });
584
+ const canGoBack = useLatestCallback(source => {
585
+ const state = getState();
586
+ return router.getStateForAction(state, {
587
+ ...CommonActions.goBack(),
588
+ source
589
+ }, {
590
+ routeNames: state.routeNames,
591
+ routeParamList: {},
592
+ routeGetIdList: {}
593
+ }) !== null || canGoBackParent?.(
594
+ // If the `source` belonged to the current navigator,
595
+ // rewrite the `source` to the parent screen's key when checking
596
+ // This mirrors the way actions bubble up to the parent
597
+ source !== undefined && state.routes.some(r => r.key === source) ? route?.key : source) || false;
598
+ });
512
599
  const navigation = useNavigationHelpers({
513
600
  onAction,
514
601
  onUnhandledAction,
602
+ canGoBack,
515
603
  getState,
516
604
  emitter,
517
- router,
518
- stateRef
605
+ router
519
606
  });
520
607
  useFocusedListenersChildrenAdapter({
521
608
  navigation,
@@ -525,15 +612,20 @@ export function useNavigationBuilder(createRouter, options) {
525
612
  getState,
526
613
  getStateListeners: keyedListeners.getState
527
614
  });
615
+ useOnGetNavigation({
616
+ navigation
617
+ });
528
618
  const descriptors = useDescriptors({
529
- routes: router.getRoutesFromState ? router.getRoutesFromState(state) : state.routes,
530
619
  screens,
620
+ state,
531
621
  navigation,
532
622
  screenOptions,
533
623
  screenLayout,
534
624
  onAction,
625
+ canGoBack,
535
626
  getState,
536
627
  setState,
628
+ subscribe,
537
629
  onRouteFocus,
538
630
  addListener,
539
631
  addKeyedListener,
@@ -541,36 +633,41 @@ export function useNavigationBuilder(createRouter, options) {
541
633
  // @ts-expect-error: this should have both core and custom events, but too much work right now
542
634
  emitter
543
635
  });
544
- useCurrentRender({
545
- state,
546
- navigation,
547
- descriptors
548
- });
549
- const NavigationContent = useComponent(children => {
636
+ const render = children => {
637
+ const focusedRoute = state.routes[state.index];
638
+ if (focusedRoute == null) {
639
+ throw new Error(`Couldn't find a route at index ${state.index}.`);
640
+ }
550
641
  const element = layout != null ? layout({
551
642
  state,
552
643
  descriptors,
553
644
  navigation,
554
645
  children
555
646
  }) : children;
556
- return /*#__PURE__*/_jsx(NavigationMetaContext.Provider, {
557
- value: undefined,
558
- children: /*#__PURE__*/_jsx(NavigationHelpersContext.Provider, {
559
- value: navigation,
560
- children: /*#__PURE__*/_jsx(NavigationStateListenerProvider, {
561
- state: state,
647
+ return /*#__PURE__*/_jsx(NavigationHelpersContext.Provider, {
648
+ value: navigation,
649
+ children: /*#__PURE__*/_jsx(NavigationStateListenerProvider, {
650
+ isSynced: !shouldUpdate,
651
+ state: state,
652
+ getState: getState,
653
+ subscribe: subscribe,
654
+ children: /*#__PURE__*/_jsx(FocusedRouteKeyContext.Provider, {
655
+ value: focusedRoute.key,
562
656
  children: /*#__PURE__*/_jsx(PreventRemoveProvider, {
563
- children: element
657
+ children: /*#__PURE__*/_jsx(IsScreenContext.Provider, {
658
+ value: false,
659
+ children: element
660
+ })
564
661
  })
565
662
  })
566
663
  })
567
664
  });
568
- });
665
+ };
569
666
  return {
570
667
  state,
571
668
  navigation,
572
669
  descriptors,
573
- NavigationContent
670
+ render
574
671
  };
575
672
  }
576
673
  //# sourceMappingURL=useNavigationBuilder.js.map