@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
@@ -1,9 +1,6 @@
1
1
  "use strict";
2
2
 
3
3
  import * as React from 'react';
4
- import useLatestCallback from 'use-latest-callback';
5
- import { useSyncExternalStoreWithSelector } from 'use-sync-external-store/with-selector';
6
- import { useNavigation } from "./useNavigation.js";
7
4
 
8
5
  /**
9
6
  * Hook to get a value from the current navigation state using a selector.
@@ -15,66 +12,181 @@ import { useNavigation } from "./useNavigation.js";
15
12
  */
16
13
  import { jsx as _jsx } from "react/jsx-runtime";
17
14
  export function useNavigationState(...args) {
18
- let navigation, stateListener, selector;
15
+ const selector = typeof args[0] === 'string' ? args[1] : args[0];
16
+ if (typeof selector !== 'function') {
17
+ throw new Error(`A selector function must be provided (got ${typeof selector}).`);
18
+ }
19
+
20
+ // @ts-expect-error: the public overloads guarantee the selector's type, but
21
+ // the `unknown[]` implementation signature can't express it
22
+ const select = selector;
23
+ let listener;
19
24
  if (typeof args[0] === 'string') {
20
- // `useNavigation` uses `use` internally, so it's fine to call it conditionally
21
- // @ts-expect-error we can't specify the type here
22
- // eslint-disable-next-line react-hooks/rules-of-hooks
23
- navigation = useNavigation(args[0]);
24
- selector = args[1];
25
+ const name = args[0];
26
+ const listeners = React.use(NamedNavigationStateListenerListContext);
27
+ listener = listeners?.[name];
28
+ if (listener == null) {
29
+ throw new Error(`Couldn't find a navigator for the route '${name}' in any of the parent screens. Is your component inside the correct screen?`);
30
+ }
25
31
  } else {
26
- selector = args[0];
27
- }
28
- if (navigation == null) {
29
- stateListener = React.use(NavigationStateListenerContext);
30
- if (stateListener == null) {
32
+ listener = React.use(NavigationStateListenerContext);
33
+ if (listener == null) {
31
34
  throw new Error("Couldn't get the navigation state. Is your component inside a navigator?");
32
35
  }
33
36
  }
34
- const subscribe = React.useCallback(callback => {
35
- if (navigation) {
36
- return navigation.addListener('state', callback);
37
- } else if (stateListener) {
38
- return stateListener.subscribe(callback);
39
- } else {
40
- throw new Error("Couldn't subscribe to navigation state changes. This is not expected.");
37
+ const {
38
+ getState,
39
+ getSnapshot,
40
+ subscribe
41
+ } = listener;
42
+ const initialRef = React.useRef(true);
43
+
44
+ // We read the initial state from context on mount instead of using getState
45
+ // This ensures that we get proper state for the current render,
46
+ // even if the external store has been updated.
47
+ // We conditionally use `use` to avoid more unnecessary re-renders after first mount.
48
+ // The context subscription is removed on the next render, which can cause one extra render.
49
+ const initialState = initialRef.current ? React.use(listener.initialStateContext) : undefined;
50
+
51
+ // We track the last committed reducer entry, navigation state, and selector,
52
+ // so we can check if an update changes the value the component last committed.
53
+ const committedRef = React.useRef({
54
+ entry: null,
55
+ state: initialState ?? getSnapshot(),
56
+ select
57
+ });
58
+
59
+ // The store can contain state from a transition that hasn't committed yet.
60
+ // Reading it during render can show state that doesn't match the navigator in that render.
61
+ // The reducer lets React process state in the same render lane as the navigator.
62
+ const [entry, dispatch] = React.useReducer((previous, event) => {
63
+ // Navigation state can change between the dispatch and the reducer running.
64
+ // Reading here ensures the processed event uses the state for that render.
65
+ const state = event === 'update' ? getState() : getSnapshot();
66
+
67
+ // If we're processing the same reducer entry as the last commit,
68
+ // we compare against the state last committed by the component.
69
+ // We keep the reducer entry to avoid re-renders for unchanged selections.
70
+ // This means the reducer entry can still hold older navigation state.
71
+ // If a parent causes another render,
72
+ // we use the latest snapshot so the selector doesn't read stale state.
73
+ // We leave the reducer entry unchanged to avoid an extra render.
74
+ // We save that snapshot in committedRef when the render commits,
75
+ // so later updates compare against the state we actually rendered,
76
+ // including when the selector changed.
77
+ // If the reducer entry is different, we use its own navigation state,
78
+ // so comparisons include updates already processed in the pending render.
79
+ const previousState = previous === committedRef.current.entry ? committedRef.current.state : previous.state;
80
+ if (previous.listener === listener && (previousState === state || event === 'update' && Object.is(select(previousState), select(state)))) {
81
+ return previous;
41
82
  }
42
- }, [navigation, stateListener]);
43
- const getSnapshot = navigation ? navigation.getState : stateListener?.getState;
44
- if (getSnapshot == null) {
45
- throw new Error("Couldn't get the navigation state. This is not expected.");
46
- }
47
- if (typeof selector !== 'function') {
48
- throw new Error(`A selector function must be provided (got ${typeof selector}).`);
49
- }
50
- const value = useSyncExternalStoreWithSelector(subscribe, getSnapshot, getSnapshot,
51
- // @ts-expect-error we can't infer the type here
52
- selector);
53
- return value;
83
+ return {
84
+ listener,
85
+ state
86
+ };
87
+ }, undefined, () => ({
88
+ listener,
89
+ state: initialState ?? getSnapshot()
90
+ }));
91
+ const state =
92
+ // A different listener means the state belongs to another navigator.
93
+ // This can happen when the passed route name changes.
94
+ entry.listener !== listener ||
95
+ // An entry that advanced past the last commit is at least as new as the snapshot.
96
+ // An entry that didn't advance while the committed state changed is older.
97
+ entry === committedRef.current.entry ? getSnapshot() : entry.state;
98
+ React.useInsertionEffect(() => {
99
+ initialRef.current = false;
100
+ committedRef.current = {
101
+ entry,
102
+ state,
103
+ select
104
+ };
105
+ });
106
+ React.useLayoutEffect(() => {
107
+ const check = event => {
108
+ const {
109
+ state,
110
+ select
111
+ } = committedRef.current;
112
+
113
+ // An 'update' event follows the latest state in the lane the update was made in.
114
+ // A 'commit' event syncs the reducer to the state committed by the navigator.
115
+ const target = event === 'update' ? getState() : getSnapshot();
116
+ if (state !== target && !Object.is(select(state), select(target))) {
117
+ dispatch(event);
118
+ }
119
+ };
120
+ const unsubscribe = subscribe(check);
121
+
122
+ // The reducer may not match the committed state when the subscription starts.
123
+ // This happens on mount during a transition or an update before subscribing.
124
+ check('commit');
125
+ return unsubscribe;
126
+ }, [getState, getSnapshot, subscribe]);
127
+ return select(state);
54
128
  }
55
129
  export function NavigationStateListenerProvider({
130
+ isSynced,
56
131
  state,
132
+ getState,
133
+ subscribe,
57
134
  children
58
135
  }) {
59
- const listeners = React.useRef([]);
60
- const getState = useLatestCallback(() => state);
61
- const subscribe = useLatestCallback(callback => {
62
- listeners.current.push(callback);
63
- return () => {
64
- listeners.current = listeners.current.filter(cb => cb !== callback);
65
- };
66
- });
67
- React.useEffect(() => {
68
- listeners.current.forEach(callback => callback());
136
+ const [InitialStateContext] = React.useState(() => /*#__PURE__*/React.createContext(state));
137
+ const [listeners] = React.useState(() => new Set());
138
+ React.useLayoutEffect(() => {
139
+ listeners.forEach(listener => listener('commit'));
140
+ }, [listeners, state]);
141
+ const snapshotRef = React.useRef(state);
142
+ React.useInsertionEffect(() => {
143
+ snapshotRef.current = state;
69
144
  }, [state]);
145
+
146
+ // Route config or nested params can produce new state during render.
147
+ // If the scheduled update hasn't synced that state to the store yet,
148
+ // We need to expose the rendered state so consumers match the navigator.
149
+ // We keep this `undefined` for other scenarios, so the context isn't recreated.
150
+ const nextState = isSynced ? undefined : state;
70
151
  const context = React.useMemo(() => ({
152
+ initialStateContext: InitialStateContext,
71
153
  getState,
72
- subscribe
73
- }), [getState, subscribe]);
154
+ getSnapshot: () => nextState ?? snapshotRef.current,
155
+ subscribe: callback => {
156
+ const unsubscribe = subscribe(() => callback('update'));
157
+ listeners.add(callback);
158
+ return () => {
159
+ listeners.delete(callback);
160
+ unsubscribe();
161
+ };
162
+ }
163
+ }), [InitialStateContext, getState, listeners, nextState, subscribe]);
74
164
  return /*#__PURE__*/_jsx(NavigationStateListenerContext.Provider, {
75
165
  value: context,
166
+ children: /*#__PURE__*/_jsx(InitialStateContext.Provider, {
167
+ value: state,
168
+ children: children
169
+ })
170
+ });
171
+ }
172
+ export function NamedNavigationStateListenerProvider({
173
+ name,
174
+ children
175
+ }) {
176
+ const listener = React.use(NavigationStateListenerContext);
177
+ if (listener == null) {
178
+ throw new Error("Couldn't find a navigation state listener. This is likely a bug in the navigator.\n\nIf you're using a custom navigator, make sure that the navigator content is wrapped by the 'render' function returned by 'useNavigationBuilder'.");
179
+ }
180
+ const parents = React.use(NamedNavigationStateListenerListContext);
181
+ const listeners = React.useMemo(() => ({
182
+ ...parents,
183
+ [name]: listener
184
+ }), [listener, name, parents]);
185
+ return /*#__PURE__*/_jsx(NamedNavigationStateListenerListContext.Provider, {
186
+ value: listeners,
76
187
  children: children
77
188
  });
78
189
  }
79
- const NavigationStateListenerContext = /*#__PURE__*/React.createContext(undefined);
190
+ export const NavigationStateListenerContext = /*#__PURE__*/React.createContext(undefined);
191
+ export const NamedNavigationStateListenerListContext = /*#__PURE__*/React.createContext(undefined);
80
192
  //# sourceMappingURL=useNavigationState.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["React","useLatestCallback","useSyncExternalStoreWithSelector","useNavigation","jsx","_jsx","useNavigationState","args","navigation","stateListener","selector","use","NavigationStateListenerContext","Error","subscribe","useCallback","callback","addListener","getSnapshot","getState","value","NavigationStateListenerProvider","state","children","listeners","useRef","current","push","filter","cb","useEffect","forEach","context","useMemo","Provider","createContext","undefined"],"sourceRoot":"../../src","sources":["useNavigationState.tsx"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["React","jsx","_jsx","useNavigationState","args","selector","Error","select","listener","name","listeners","use","NamedNavigationStateListenerListContext","NavigationStateListenerContext","getState","getSnapshot","subscribe","initialRef","useRef","initialState","current","initialStateContext","undefined","committedRef","entry","state","dispatch","useReducer","previous","event","previousState","Object","is","useInsertionEffect","useLayoutEffect","check","target","unsubscribe","NavigationStateListenerProvider","isSynced","children","InitialStateContext","useState","createContext","Set","forEach","snapshotRef","nextState","context","useMemo","callback","add","delete","Provider","value","NamedNavigationStateListenerProvider","parents"],"sourceRoot":"../../src","sources":["useNavigationState.tsx"],"mappings":"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","ignoreList":[]}
@@ -1,7 +1,10 @@
1
1
  "use strict";
2
2
 
3
3
  import * as React from 'react';
4
- import { NavigationBuilderContext } from "./NavigationBuilderContext.js";
4
+ import { ConsumedParamsContext } from "./ConsumedParamsContext.js";
5
+ import { getLoaderForStateChange } from "./DataLoading.js";
6
+ import { useNavigationBuilderContext } from "./NavigationBuilderContext.js";
7
+ import { StaticTreeContext } from "./StaticTreeContext.js";
5
8
  import { shouldPreventRemove, useOnPreventRemove } from "./useOnPreventRemove.js";
6
9
  /**
7
10
  * Hook to handle actions for a navigator, including state updates and bubbling.
@@ -26,13 +29,20 @@ export function useOnAction({
26
29
  onAction: onActionParent,
27
30
  onRouteFocus: onRouteFocusParent,
28
31
  addListener: addListenerParent,
29
- onDispatchAction
30
- } = React.useContext(NavigationBuilderContext);
32
+ onDispatchAction,
33
+ flushUpdates
34
+ } = useNavigationBuilderContext();
35
+ const tree = React.use(StaticTreeContext);
36
+ const consumedParams = React.use(ConsumedParamsContext);
31
37
  const routerConfigOptionsRef = React.useRef(routerConfigOptions);
32
- React.useEffect(() => {
38
+ React.useInsertionEffect(() => {
33
39
  routerConfigOptionsRef.current = routerConfigOptions;
34
40
  });
35
41
  const onAction = React.useCallback((action, visitedNavigators = new Set()) => {
42
+ // Apply any pending state updates scheduled during render before handling the action
43
+ // Otherwise the action will be handled with an outdated state,
44
+ // and the pending updates will overwrite the changes from the action
45
+ flushUpdates();
36
46
  const state = getState();
37
47
 
38
48
  // Since actions can bubble both up and down, they could come to the same navigator again
@@ -45,16 +55,38 @@ export function useOnAction({
45
55
  let result = router.getStateForAction(state, action, routerConfigOptionsRef.current);
46
56
 
47
57
  // If a target is specified and set to current navigator, the action shouldn't bubble
48
- // So instead of `null`, we use the state object for such cases to signal that action was handled
49
- result = result === null && action.target === state.key ? state : result;
58
+ // So we immediately return `false` to mark it as unhandled
59
+ if (result === null && action.target === state.key) {
60
+ return false;
61
+ }
62
+ if (result !== null && result.stale !== false) {
63
+ // Some actions (e.g. `RESET`) may return a stale state from the router
64
+ // We rehydrate it before storing so the stored state is always usable
65
+ // Otherwise anything reading the state before the next render
66
+ // (e.g. another dispatch immediately after) would get an outdated state
67
+ result = router.getRehydratedState(result, routerConfigOptionsRef.current);
68
+ }
50
69
  if (result !== null) {
51
- onDispatchAction(action, state === result);
52
70
  if (state !== result) {
53
71
  const isPrevented = shouldPreventRemove(emitter, beforeRemoveListeners, state.routes, result.routes, action);
54
72
  if (isPrevented) {
73
+ onDispatchAction(action, true);
55
74
  return true;
56
75
  }
76
+ if (getState() !== state) {
77
+ // Listeners for 'beforeRemove' may dispatch actions that change the state
78
+ // Then the result we have is outdated and would overwrite those changes
79
+ // So we handle the action again to calculate the result with the latest state
80
+ return onAction(action, new Set());
81
+ }
82
+ onDispatchAction(action, false);
83
+ if (tree) {
84
+ const loader = getLoaderForStateChange(tree, result, state, consumedParams);
85
+ loader?.();
86
+ }
57
87
  setState(result);
88
+ } else {
89
+ onDispatchAction(action, true);
58
90
  }
59
91
  if (onRouteFocusParent !== undefined) {
60
92
  // Some actions such as `NAVIGATE` also want to bring the navigated route to focus in the whole tree
@@ -67,29 +99,44 @@ export function useOnAction({
67
99
  return true;
68
100
  }
69
101
  }
102
+ const isSourceInCurrentNavigator = action.source !== undefined && state.routes.some(r => r.key === action.source);
70
103
  if (onActionParent !== undefined) {
71
104
  // Bubble action to the parent if the current navigator didn't handle it
72
- if (onActionParent(action, visitedNavigators)) {
105
+ const parentAction = isSourceInCurrentNavigator && key !== undefined ? {
106
+ ...action,
107
+ // If the `source` belonged to the current navigator,
108
+ // rewrite the `source` to the parent screen's key when bubbling
109
+ // This will let parent handle it relative to the child that dispatched the action
110
+ source: key
111
+ } : action;
112
+ if (onActionParent(parentAction, visitedNavigators)) {
73
113
  return true;
74
114
  }
75
115
  }
76
116
  if (typeof action.target === 'string') {
77
117
  // If the action wasn't handled by current navigator or a parent navigator, let children handle it
118
+ const childAction = isSourceInCurrentNavigator ? {
119
+ ...action,
120
+ // If the `source` belonged to the current navigator,
121
+ // remove it when targeting a child navigator
122
+ // So child navigators can handle it based on the focused screen
123
+ source: undefined
124
+ } : action;
78
125
  for (let i = actionListeners.length - 1; i >= 0; i--) {
79
126
  const listener = actionListeners[i];
80
- if (listener(action, visitedNavigators)) {
127
+ if (listener?.(childAction, visitedNavigators)) {
81
128
  return true;
82
129
  }
83
130
  }
84
131
  }
85
132
  return false;
86
- }, [actionListeners, beforeRemoveListeners, emitter, getState, key, onActionParent, onDispatchAction, onRouteFocusParent, router, setState]);
133
+ }, [actionListeners, beforeRemoveListeners, consumedParams, emitter, flushUpdates, getState, key, onActionParent, onDispatchAction, onRouteFocusParent, router, setState, tree]);
87
134
  useOnPreventRemove({
88
135
  getState,
89
136
  emitter,
90
137
  beforeRemoveListeners
91
138
  });
92
- React.useEffect(() => addListenerParent?.('action', onAction), [addListenerParent, onAction]);
139
+ React.useInsertionEffect(() => addListenerParent?.('action', onAction), [addListenerParent, onAction]);
93
140
  return onAction;
94
141
  }
95
142
  //# sourceMappingURL=useOnAction.js.map
@@ -1 +1 @@
1
- {"version":3,"names":["React","NavigationBuilderContext","shouldPreventRemove","useOnPreventRemove","useOnAction","router","getState","setState","key","actionListeners","beforeRemoveListeners","routerConfigOptions","emitter","onAction","onActionParent","onRouteFocus","onRouteFocusParent","addListener","addListenerParent","onDispatchAction","useContext","routerConfigOptionsRef","useRef","useEffect","current","useCallback","action","visitedNavigators","Set","state","has","add","target","result","getStateForAction","isPrevented","routes","undefined","shouldFocus","shouldActionChangeFocus","i","length","listener"],"sourceRoot":"../../src","sources":["useOnAction.tsx"],"mappings":"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","ignoreList":[]}
1
+ {"version":3,"names":["React","ConsumedParamsContext","getLoaderForStateChange","useNavigationBuilderContext","StaticTreeContext","shouldPreventRemove","useOnPreventRemove","useOnAction","router","getState","setState","key","actionListeners","beforeRemoveListeners","routerConfigOptions","emitter","onAction","onActionParent","onRouteFocus","onRouteFocusParent","addListener","addListenerParent","onDispatchAction","flushUpdates","tree","use","consumedParams","routerConfigOptionsRef","useRef","useInsertionEffect","current","useCallback","action","visitedNavigators","Set","state","has","add","target","result","getStateForAction","stale","getRehydratedState","isPrevented","routes","loader","undefined","shouldFocus","shouldActionChangeFocus","isSourceInCurrentNavigator","source","some","r","parentAction","childAction","i","length","listener"],"sourceRoot":"../../src","sources":["useOnAction.tsx"],"mappings":"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","ignoreList":[]}
@@ -0,0 +1,26 @@
1
+ "use strict";
2
+
3
+ import * as React from 'react';
4
+ import { useNavigationBuilderContext } from "./NavigationBuilderContext.js";
5
+ import { NavigationRouteContext } from "./NavigationProvider.js";
6
+ /**
7
+ * Hook which lets the container access the navigation object of the root navigator.
8
+ * It's used for the navigation object returned by `useNavigation` outside a screen.
9
+ */
10
+ export function useOnGetNavigation({
11
+ navigation
12
+ }) {
13
+ const {
14
+ addKeyedListener
15
+ } = useNavigationBuilderContext();
16
+ const route = React.use(NavigationRouteContext);
17
+ React.useInsertionEffect(() => {
18
+ // We only register if this is the root navigator
19
+ // i.e. there is no parent route
20
+ if (route != null) {
21
+ return;
22
+ }
23
+ return addKeyedListener?.('getNavigation', 'root', () => navigation);
24
+ }, [addKeyedListener, navigation, route]);
25
+ }
26
+ //# sourceMappingURL=useOnGetNavigation.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"names":["React","useNavigationBuilderContext","NavigationRouteContext","useOnGetNavigation","navigation","addKeyedListener","route","use","useInsertionEffect"],"sourceRoot":"../../src","sources":["useOnGetNavigation.tsx"],"mappings":";;AACA,OAAO,KAAKA,KAAK,MAAM,OAAO;AAE9B,SAASC,2BAA2B,QAAQ,+BAA4B;AACxE,SAASC,sBAAsB,QAAQ,yBAAsB;AAO7D;AACA;AACA;AACA;AACA,OAAO,SAASC,kBAAkBA,CAAC;EAAEC;AAAoB,CAAC,EAAE;EAC1D,MAAM;IAAEC;EAAiB,CAAC,GAAGJ,2BAA2B,CAAC,CAAC;EAE1D,MAAMK,KAAK,GAAGN,KAAK,CAACO,GAAG,CAACL,sBAAsB,CAAC;EAE/CF,KAAK,CAACQ,kBAAkB,CAAC,MAAM;IAC7B;IACA;IACA,IAAIF,KAAK,IAAI,IAAI,EAAE;MACjB;IACF;IAEA,OAAOD,gBAAgB,GAAG,eAAe,EAAE,MAAM,EAAE,MAAMD,UAAU,CAAC;EACtE,CAAC,EAAE,CAACC,gBAAgB,EAAED,UAAU,EAAEE,KAAK,CAAC,CAAC;AAC3C","ignoreList":[]}
@@ -2,7 +2,7 @@
2
2
 
3
3
  import * as React from 'react';
4
4
  import { isArrayEqual } from "./isArrayEqual.js";
5
- import { NavigationBuilderContext } from "./NavigationBuilderContext.js";
5
+ import { useNavigationBuilderContext } from "./NavigationBuilderContext.js";
6
6
  import { NavigationRouteContext } from "./NavigationProvider.js";
7
7
  export function useOnGetState({
8
8
  getState,
@@ -10,8 +10,8 @@ export function useOnGetState({
10
10
  }) {
11
11
  const {
12
12
  addKeyedListener
13
- } = React.useContext(NavigationBuilderContext);
14
- const route = React.useContext(NavigationRouteContext);
13
+ } = useNavigationBuilderContext();
14
+ const route = React.use(NavigationRouteContext);
15
15
  const key = route ? route.key : 'root';
16
16
  const getRehydratedState = React.useCallback(() => {
17
17
  const state = getState();
@@ -35,7 +35,10 @@ export function useOnGetState({
35
35
  routes
36
36
  };
37
37
  }, [getState, getStateListeners]);
38
- React.useEffect(() => {
38
+
39
+ // Use insertion effect to preserve the listener under `<Activity mode="hidden">`
40
+ // So `getRootState` will still return state of nested navigators
41
+ React.useInsertionEffect(() => {
39
42
  return addKeyedListener?.('getState', key, getRehydratedState);
40
43
  }, [addKeyedListener, getRehydratedState, key]);
41
44
  }
@@ -1 +1 @@
1
- {"version":3,"names":["React","isArrayEqual","NavigationBuilderContext","NavigationRouteContext","useOnGetState","getState","getStateListeners","addKeyedListener","useContext","route","key","getRehydratedState","useCallback","state","routes","map","childState","useEffect"],"sourceRoot":"../../src","sources":["useOnGetState.tsx"],"mappings":";;AACA,OAAO,KAAKA,KAAK,MAAM,OAAO;AAE9B,SAASC,YAAY,QAAQ,mBAAgB;AAC7C,SAEEC,wBAAwB,QACnB,+BAA4B;AACnC,SAASC,sBAAsB,QAAQ,yBAAsB;AAO7D,OAAO,SAASC,aAAaA,CAAC;EAAEC,QAAQ;EAAEC;AAA2B,CAAC,EAAE;EACtE,MAAM;IAAEC;EAAiB,CAAC,GAAGP,KAAK,CAACQ,UAAU,CAACN,wBAAwB,CAAC;EACvE,MAAMO,KAAK,GAAGT,KAAK,CAACQ,UAAU,CAACL,sBAAsB,CAAC;EACtD,MAAMO,GAAG,GAAGD,KAAK,GAAGA,KAAK,CAACC,GAAG,GAAG,MAAM;EAEtC,MAAMC,kBAAkB,GAAGX,KAAK,CAACY,WAAW,CAAC,MAAM;IACjD,MAAMC,KAAK,GAAGR,QAAQ,CAAC,CAAC;;IAExB;IACA,MAAMS,MAAM,GAAGD,KAAK,CAACC,MAAM,CAACC,GAAG,CAAEN,KAAK,IAAK;MACzC,MAAMO,UAAU,GAAGV,iBAAiB,CAACG,KAAK,CAACC,GAAG,CAAC,GAAG,CAAC;MAEnD,IAAID,KAAK,CAACI,KAAK,KAAKG,UAAU,EAAE;QAC9B,OAAOP,KAAK;MACd;MAEA,OAAO;QAAE,GAAGA,KAAK;QAAEI,KAAK,EAAEG;MAAW,CAAC;IACxC,CAAC,CAAC;IAEF,IAAIf,YAAY,CAACY,KAAK,CAACC,MAAM,EAAEA,MAAM,CAAC,EAAE;MACtC,OAAOD,KAAK;IACd;IAEA,OAAO;MAAE,GAAGA,KAAK;MAAEC;IAAO,CAAC;EAC7B,CAAC,EAAE,CAACT,QAAQ,EAAEC,iBAAiB,CAAC,CAAC;EAEjCN,KAAK,CAACiB,SAAS,CAAC,MAAM;IACpB,OAAOV,gBAAgB,GAAG,UAAU,EAAEG,GAAG,EAAEC,kBAAkB,CAAC;EAChE,CAAC,EAAE,CAACJ,gBAAgB,EAAEI,kBAAkB,EAAED,GAAG,CAAC,CAAC;AACjD","ignoreList":[]}
1
+ {"version":3,"names":["React","isArrayEqual","useNavigationBuilderContext","NavigationRouteContext","useOnGetState","getState","getStateListeners","addKeyedListener","route","use","key","getRehydratedState","useCallback","state","routes","map","childState","useInsertionEffect"],"sourceRoot":"../../src","sources":["useOnGetState.tsx"],"mappings":";;AACA,OAAO,KAAKA,KAAK,MAAM,OAAO;AAE9B,SAASC,YAAY,QAAQ,mBAAgB;AAC7C,SAEEC,2BAA2B,QACtB,+BAA4B;AACnC,SAASC,sBAAsB,QAAQ,yBAAsB;AAO7D,OAAO,SAASC,aAAaA,CAAC;EAAEC,QAAQ;EAAEC;AAA2B,CAAC,EAAE;EACtE,MAAM;IAAEC;EAAiB,CAAC,GAAGL,2BAA2B,CAAC,CAAC;EAE1D,MAAMM,KAAK,GAAGR,KAAK,CAACS,GAAG,CAACN,sBAAsB,CAAC;EAE/C,MAAMO,GAAG,GAAGF,KAAK,GAAGA,KAAK,CAACE,GAAG,GAAG,MAAM;EAEtC,MAAMC,kBAAkB,GAAGX,KAAK,CAACY,WAAW,CAAC,MAAM;IACjD,MAAMC,KAAK,GAAGR,QAAQ,CAAC,CAAC;;IAExB;IACA,MAAMS,MAAM,GAAGD,KAAK,CAACC,MAAM,CAACC,GAAG,CAAEP,KAAK,IAAK;MACzC,MAAMQ,UAAU,GAAGV,iBAAiB,CAACE,KAAK,CAACE,GAAG,CAAC,GAAG,CAAC;MAEnD,IAAIF,KAAK,CAACK,KAAK,KAAKG,UAAU,EAAE;QAC9B,OAAOR,KAAK;MACd;MAEA,OAAO;QAAE,GAAGA,KAAK;QAAEK,KAAK,EAAEG;MAAW,CAAC;IACxC,CAAC,CAAC;IAEF,IAAIf,YAAY,CAACY,KAAK,CAACC,MAAM,EAAEA,MAAM,CAAC,EAAE;MACtC,OAAOD,KAAK;IACd;IAEA,OAAO;MAAE,GAAGA,KAAK;MAAEC;IAAO,CAAC;EAC7B,CAAC,EAAE,CAACT,QAAQ,EAAEC,iBAAiB,CAAC,CAAC;;EAEjC;EACA;EACAN,KAAK,CAACiB,kBAAkB,CAAC,MAAM;IAC7B,OAAOV,gBAAgB,GAAG,UAAU,EAAEG,GAAG,EAAEC,kBAAkB,CAAC;EAChE,CAAC,EAAE,CAACJ,gBAAgB,EAAEI,kBAAkB,EAAED,GAAG,CAAC,CAAC;AACjD","ignoreList":[]}
@@ -1,43 +1,52 @@
1
1
  "use strict";
2
2
 
3
3
  import * as React from 'react';
4
- import { NavigationBuilderContext } from "./NavigationBuilderContext.js";
4
+ import { useNavigationBuilderContext } from "./NavigationBuilderContext.js";
5
5
  import { NavigationRouteContext } from "./NavigationProvider.js";
6
6
  const VISITED_ROUTE_KEYS = Symbol('VISITED_ROUTE_KEYS');
7
7
  export const shouldPreventRemove = (emitter, beforeRemoveListeners, currentRoutes, nextRoutes, action) => {
8
- const nextRouteKeys = nextRoutes.map(route => route.key);
9
-
10
- // Call these in reverse order so last screens handle the event first
11
- const removedRoutes = currentRoutes.filter(route => !nextRouteKeys.includes(route.key)).reverse();
12
- const visitedRouteKeys =
13
- // @ts-expect-error: add this property to mark that we've already emitted this action
14
- action[VISITED_ROUTE_KEYS] ?? new Set();
8
+ const nextRoutesByKey = new Map(nextRoutes.map(route => [route.key, route]).filter(([, route]) => route.key != null));
9
+ const visitedRouteKeys = VISITED_ROUTE_KEYS in action && action[VISITED_ROUTE_KEYS] instanceof Set ? action[VISITED_ROUTE_KEYS] : new Set();
15
10
  const beforeRemoveAction = {
16
11
  ...action,
17
12
  [VISITED_ROUTE_KEYS]: visitedRouteKeys
18
13
  };
19
- for (const route of removedRoutes) {
14
+
15
+ // Call these in reverse order so last screens handle the event first
16
+ const reversedCurrentRoutes = [...currentRoutes].reverse();
17
+ for (const route of reversedCurrentRoutes) {
20
18
  if (visitedRouteKeys.has(route.key)) {
21
19
  // Skip if we've already emitted this action for this screen
22
20
  continue;
23
21
  }
24
-
25
- // First, we need to check if any child screens want to prevent it
26
- const isPrevented = beforeRemoveListeners[route.key]?.(beforeRemoveAction);
27
- if (isPrevented) {
28
- return true;
29
- }
30
- visitedRouteKeys.add(route.key);
31
- const event = emitter.emit({
32
- type: 'beforeRemove',
33
- target: route.key,
34
- data: {
35
- action: beforeRemoveAction
36
- },
37
- canPreventDefault: true
38
- });
39
- if (event.defaultPrevented) {
40
- return true;
22
+ if (!nextRoutesByKey.has(route.key)) {
23
+ // The route is not in next state, so it's being removed
24
+ // First, we need to check if any child screens want to prevent it
25
+ const isPrevented = beforeRemoveListeners[route.key]?.(beforeRemoveAction, undefined);
26
+ if (isPrevented) {
27
+ return true;
28
+ }
29
+ visitedRouteKeys.add(route.key);
30
+ const event = emitter.emit({
31
+ type: 'beforeRemove',
32
+ target: route.key,
33
+ data: {
34
+ action: beforeRemoveAction
35
+ },
36
+ canPreventDefault: true
37
+ });
38
+ if (event.defaultPrevented) {
39
+ return true;
40
+ }
41
+ } else {
42
+ // The route is kept but its nested state changed, so propagate the check into the nested navigator
43
+ const nextRoute = nextRoutesByKey.get(route.key);
44
+ if (route.state != null && route.state !== nextRoute?.state) {
45
+ const isPrevented = beforeRemoveListeners[route.key]?.(beforeRemoveAction, nextRoute?.state);
46
+ if (isPrevented) {
47
+ return true;
48
+ }
49
+ }
41
50
  }
42
51
  }
43
52
  return false;
@@ -49,14 +58,14 @@ export function useOnPreventRemove({
49
58
  }) {
50
59
  const {
51
60
  addKeyedListener
52
- } = React.useContext(NavigationBuilderContext);
53
- const route = React.useContext(NavigationRouteContext);
61
+ } = useNavigationBuilderContext();
62
+ const route = React.use(NavigationRouteContext);
54
63
  const routeKey = route?.key;
55
- React.useEffect(() => {
64
+ React.useInsertionEffect(() => {
56
65
  if (routeKey) {
57
- return addKeyedListener?.('beforeRemove', routeKey, action => {
66
+ return addKeyedListener?.('beforeRemove', routeKey, (action, nextState) => {
58
67
  const state = getState();
59
- return shouldPreventRemove(emitter, beforeRemoveListeners, state.routes, [], action);
68
+ return shouldPreventRemove(emitter, beforeRemoveListeners, state.routes, nextState?.routes ?? [], action);
60
69
  });
61
70
  }
62
71
  }, [addKeyedListener, beforeRemoveListeners, emitter, getState, routeKey]);
@@ -1 +1 @@
1
- {"version":3,"names":["React","NavigationBuilderContext","NavigationRouteContext","VISITED_ROUTE_KEYS","Symbol","shouldPreventRemove","emitter","beforeRemoveListeners","currentRoutes","nextRoutes","action","nextRouteKeys","map","route","key","removedRoutes","filter","includes","reverse","visitedRouteKeys","Set","beforeRemoveAction","has","isPrevented","add","event","emit","type","target","data","canPreventDefault","defaultPrevented","useOnPreventRemove","getState","addKeyedListener","useContext","routeKey","useEffect","state","routes"],"sourceRoot":"../../src","sources":["useOnPreventRemove.tsx"],"mappings":";;AAIA,OAAO,KAAKA,KAAK,MAAM,OAAO;AAE9B,SAEEC,wBAAwB,QACnB,+BAA4B;AACnC,SAASC,sBAAsB,QAAQ,yBAAsB;AAU7D,MAAMC,kBAAkB,GAAGC,MAAM,CAAC,oBAAoB,CAAC;AAEvD,OAAO,MAAMC,mBAAmB,GAAGA,CACjCC,OAAkD,EAClDC,qBAA4E,EAC5EC,aAAgC,EAChCC,UAA0C,EAC1CC,MAAwB,KACrB;EACH,MAAMC,aAAa,GAAGF,UAAU,CAACG,GAAG,CAAEC,KAAK,IAAKA,KAAK,CAACC,GAAG,CAAC;;EAE1D;EACA,MAAMC,aAAa,GAAGP,aAAa,CAChCQ,MAAM,CAAEH,KAAK,IAAK,CAACF,aAAa,CAACM,QAAQ,CAACJ,KAAK,CAACC,GAAG,CAAC,CAAC,CACrDI,OAAO,CAAC,CAAC;EAEZ,MAAMC,gBAA6B;EACjC;EACAT,MAAM,CAACP,kBAAkB,CAAC,IAAI,IAAIiB,GAAG,CAAS,CAAC;EAEjD,MAAMC,kBAAkB,GAAG;IACzB,GAAGX,MAAM;IACT,CAACP,kBAAkB,GAAGgB;EACxB,CAAC;EAED,KAAK,MAAMN,KAAK,IAAIE,aAAa,EAAE;IACjC,IAAII,gBAAgB,CAACG,GAAG,CAACT,KAAK,CAACC,GAAG,CAAC,EAAE;MACnC;MACA;IACF;;IAEA;IACA,MAAMS,WAAW,GAAGhB,qBAAqB,CAACM,KAAK,CAACC,GAAG,CAAC,GAAGO,kBAAkB,CAAC;IAE1E,IAAIE,WAAW,EAAE;MACf,OAAO,IAAI;IACb;IAEAJ,gBAAgB,CAACK,GAAG,CAACX,KAAK,CAACC,GAAG,CAAC;IAE/B,MAAMW,KAAK,GAAGnB,OAAO,CAACoB,IAAI,CAAC;MACzBC,IAAI,EAAE,cAAc;MACpBC,MAAM,EAAEf,KAAK,CAACC,GAAG;MACjBe,IAAI,EAAE;QAAEnB,MAAM,EAAEW;MAAmB,CAAC;MACpCS,iBAAiB,EAAE;IACrB,CAAC,CAAC;IAEF,IAAIL,KAAK,CAACM,gBAAgB,EAAE;MAC1B,OAAO,IAAI;IACb;EACF;EAEA,OAAO,KAAK;AACd,CAAC;AAED,OAAO,SAASC,kBAAkBA,CAAC;EACjCC,QAAQ;EACR3B,OAAO;EACPC;AACO,CAAC,EAAE;EACV,MAAM;IAAE2B;EAAiB,CAAC,GAAGlC,KAAK,CAACmC,UAAU,CAAClC,wBAAwB,CAAC;EACvE,MAAMY,KAAK,GAAGb,KAAK,CAACmC,UAAU,CAACjC,sBAAsB,CAAC;EACtD,MAAMkC,QAAQ,GAAGvB,KAAK,EAAEC,GAAG;EAE3Bd,KAAK,CAACqC,SAAS,CAAC,MAAM;IACpB,IAAID,QAAQ,EAAE;MACZ,OAAOF,gBAAgB,GAAG,cAAc,EAAEE,QAAQ,EAAG1B,MAAM,IAAK;QAC9D,MAAM4B,KAAK,GAAGL,QAAQ,CAAC,CAAC;QAExB,OAAO5B,mBAAmB,CACxBC,OAAO,EACPC,qBAAqB,EACrB+B,KAAK,CAACC,MAAM,EACZ,EAAE,EACF7B,MACF,CAAC;MACH,CAAC,CAAC;IACJ;EACF,CAAC,EAAE,CAACwB,gBAAgB,EAAE3B,qBAAqB,EAAED,OAAO,EAAE2B,QAAQ,EAAEG,QAAQ,CAAC,CAAC;AAC5E","ignoreList":[]}
1
+ {"version":3,"names":["React","useNavigationBuilderContext","NavigationRouteContext","VISITED_ROUTE_KEYS","Symbol","shouldPreventRemove","emitter","beforeRemoveListeners","currentRoutes","nextRoutes","action","nextRoutesByKey","Map","map","route","key","filter","visitedRouteKeys","Set","beforeRemoveAction","reversedCurrentRoutes","reverse","has","isPrevented","undefined","add","event","emit","type","target","data","canPreventDefault","defaultPrevented","nextRoute","get","state","useOnPreventRemove","getState","addKeyedListener","use","routeKey","useInsertionEffect","nextState","routes"],"sourceRoot":"../../src","sources":["useOnPreventRemove.tsx"],"mappings":"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","ignoreList":[]}