@react-navigation/core 8.0.0-alpha.3 → 8.0.0-alpha.30

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 (283) hide show
  1. package/lib/module/BaseNavigationContainer.js +34 -17
  2. package/lib/module/BaseNavigationContainer.js.map +1 -1
  3. package/lib/module/ConsumedParamsContext.js +5 -0
  4. package/lib/module/ConsumedParamsContext.js.map +1 -0
  5. package/lib/module/DataLoading.js +127 -0
  6. package/lib/module/DataLoading.js.map +1 -0
  7. package/lib/module/NavigationBuilderContext.js +1 -0
  8. package/lib/module/NavigationBuilderContext.js.map +1 -1
  9. package/lib/module/NavigationIndependentTree.js +17 -8
  10. package/lib/module/NavigationIndependentTree.js.map +1 -1
  11. package/lib/module/NavigationProvider.js +22 -11
  12. package/lib/module/NavigationProvider.js.map +1 -1
  13. package/lib/module/NavigationStateContext.js.map +1 -1
  14. package/lib/module/PreventRemoveContext.js.map +1 -1
  15. package/lib/module/PreventRemoveProvider.js +37 -27
  16. package/lib/module/PreventRemoveProvider.js.map +1 -1
  17. package/lib/module/SceneView.js +7 -40
  18. package/lib/module/SceneView.js.map +1 -1
  19. package/lib/module/StaticNavigation.js +179 -50
  20. package/lib/module/StaticNavigation.js.map +1 -1
  21. package/lib/module/StaticTreeContext.js +5 -0
  22. package/lib/module/StaticTreeContext.js.map +1 -0
  23. package/lib/module/checkSerializable.js +18 -13
  24. package/lib/module/checkSerializable.js.map +1 -1
  25. package/lib/module/createNavigationContainerRef.js +6 -8
  26. package/lib/module/createNavigationContainerRef.js.map +1 -1
  27. package/lib/module/createNavigatorFactory.js +27 -5
  28. package/lib/module/createNavigatorFactory.js.map +1 -1
  29. package/lib/module/findFocusedRoute.js +7 -4
  30. package/lib/module/findFocusedRoute.js.map +1 -1
  31. package/lib/module/getActionFromState.js +45 -20
  32. package/lib/module/getActionFromState.js.map +1 -1
  33. package/lib/module/getPathFromState.js +171 -90
  34. package/lib/module/getPathFromState.js.map +1 -1
  35. package/lib/module/getPatternParts.js +20 -4
  36. package/lib/module/getPatternParts.js.map +1 -1
  37. package/lib/module/getStateFromPath.js +485 -214
  38. package/lib/module/getStateFromPath.js.map +1 -1
  39. package/lib/module/getStateFromRouteParams.js +24 -0
  40. package/lib/module/getStateFromRouteParams.js.map +1 -0
  41. package/lib/module/index.js +5 -4
  42. package/lib/module/index.js.map +1 -1
  43. package/lib/module/theming/useTheme.js +1 -1
  44. package/lib/module/theming/useTheme.js.map +1 -1
  45. package/lib/module/types.js +35 -0
  46. package/lib/module/types.js.map +1 -1
  47. package/lib/module/useDescriptors.js +19 -11
  48. package/lib/module/useDescriptors.js.map +1 -1
  49. package/lib/module/useEventEmitter.js +48 -33
  50. package/lib/module/useEventEmitter.js.map +1 -1
  51. package/lib/module/useFocusEvents.js +12 -4
  52. package/lib/module/useFocusEvents.js.map +1 -1
  53. package/lib/module/useFocusedListenersChildrenAdapter.js +2 -2
  54. package/lib/module/useFocusedListenersChildrenAdapter.js.map +1 -1
  55. package/lib/module/useIsFocused.js +7 -12
  56. package/lib/module/useIsFocused.js.map +1 -1
  57. package/lib/module/useKeyedChildListeners.js +4 -2
  58. package/lib/module/useKeyedChildListeners.js.map +1 -1
  59. package/lib/module/useLazyValue.js.map +1 -1
  60. package/lib/module/useNavigation.js +2 -15
  61. package/lib/module/useNavigation.js.map +1 -1
  62. package/lib/module/useNavigationBuilder.js +201 -131
  63. package/lib/module/useNavigationBuilder.js.map +1 -1
  64. package/lib/module/useNavigationCache.js +22 -17
  65. package/lib/module/useNavigationCache.js.map +1 -1
  66. package/lib/module/useNavigationHelpers.js +28 -10
  67. package/lib/module/useNavigationHelpers.js.map +1 -1
  68. package/lib/module/useNavigationIndependentTree.js +1 -1
  69. package/lib/module/useNavigationIndependentTree.js.map +1 -1
  70. package/lib/module/useNavigationState.js +70 -35
  71. package/lib/module/useNavigationState.js.map +1 -1
  72. package/lib/module/useOnAction.js +37 -7
  73. package/lib/module/useOnAction.js.map +1 -1
  74. package/lib/module/useOnGetState.js +6 -3
  75. package/lib/module/useOnGetState.js.map +1 -1
  76. package/lib/module/useOnPreventRemove.js +39 -30
  77. package/lib/module/useOnPreventRemove.js.map +1 -1
  78. package/lib/module/useOnRouteFocus.js +1 -1
  79. package/lib/module/useOnRouteFocus.js.map +1 -1
  80. package/lib/module/useOptionsGetters.js +10 -5
  81. package/lib/module/useOptionsGetters.js.map +1 -1
  82. package/lib/module/usePreventRemove.js +10 -3
  83. package/lib/module/usePreventRemove.js.map +1 -1
  84. package/lib/module/usePreventRemoveContext.js +1 -1
  85. package/lib/module/usePreventRemoveContext.js.map +1 -1
  86. package/lib/module/useRegisterNavigator.js +2 -2
  87. package/lib/module/useRegisterNavigator.js.map +1 -1
  88. package/lib/module/useRoute.js +2 -0
  89. package/lib/module/useRoute.js.map +1 -1
  90. package/lib/module/useRouteCache.js +17 -11
  91. package/lib/module/useRouteCache.js.map +1 -1
  92. package/lib/module/useScheduleUpdate.js +9 -9
  93. package/lib/module/useScheduleUpdate.js.map +1 -1
  94. package/lib/module/useStateForPath.js +1 -1
  95. package/lib/module/useStateForPath.js.map +1 -1
  96. package/lib/module/useSyncState.js +7 -3
  97. package/lib/module/useSyncState.js.map +1 -1
  98. package/lib/module/validatePathConfig.js +50 -36
  99. package/lib/module/validatePathConfig.js.map +1 -1
  100. package/lib/typescript/src/BaseNavigationContainer.d.ts +6 -3
  101. package/lib/typescript/src/BaseNavigationContainer.d.ts.map +1 -1
  102. package/lib/typescript/src/ConsumedParamsContext.d.ts +3 -0
  103. package/lib/typescript/src/ConsumedParamsContext.d.ts.map +1 -0
  104. package/lib/typescript/src/DataLoading.d.ts +21 -0
  105. package/lib/typescript/src/DataLoading.d.ts.map +1 -0
  106. package/lib/typescript/src/EnsureSingleNavigator.d.ts +1 -1
  107. package/lib/typescript/src/EnsureSingleNavigator.d.ts.map +1 -1
  108. package/lib/typescript/src/Group.d.ts +1 -1
  109. package/lib/typescript/src/Group.d.ts.map +1 -1
  110. package/lib/typescript/src/NavigationBuilderContext.d.ts +9 -8
  111. package/lib/typescript/src/NavigationBuilderContext.d.ts.map +1 -1
  112. package/lib/typescript/src/NavigationContainerRefContext.d.ts +1 -1
  113. package/lib/typescript/src/NavigationContainerRefContext.d.ts.map +1 -1
  114. package/lib/typescript/src/NavigationFocusedRouteStateContext.d.ts +4 -4
  115. package/lib/typescript/src/NavigationFocusedRouteStateContext.d.ts.map +1 -1
  116. package/lib/typescript/src/NavigationHelpersContext.d.ts +1 -1
  117. package/lib/typescript/src/NavigationHelpersContext.d.ts.map +1 -1
  118. package/lib/typescript/src/NavigationIndependentTree.d.ts +1 -1
  119. package/lib/typescript/src/NavigationIndependentTree.d.ts.map +1 -1
  120. package/lib/typescript/src/NavigationProvider.d.ts +12 -13
  121. package/lib/typescript/src/NavigationProvider.d.ts.map +1 -1
  122. package/lib/typescript/src/NavigationStateContext.d.ts +3 -3
  123. package/lib/typescript/src/NavigationStateContext.d.ts.map +1 -1
  124. package/lib/typescript/src/PreventRemoveContext.d.ts +1 -0
  125. package/lib/typescript/src/PreventRemoveContext.d.ts.map +1 -1
  126. package/lib/typescript/src/PreventRemoveProvider.d.ts +1 -1
  127. package/lib/typescript/src/PreventRemoveProvider.d.ts.map +1 -1
  128. package/lib/typescript/src/SceneView.d.ts +3 -2
  129. package/lib/typescript/src/SceneView.d.ts.map +1 -1
  130. package/lib/typescript/src/Screen.d.ts +1 -1
  131. package/lib/typescript/src/Screen.d.ts.map +1 -1
  132. package/lib/typescript/src/StaticContainer.d.ts +1 -1
  133. package/lib/typescript/src/StaticContainer.d.ts.map +1 -1
  134. package/lib/typescript/src/StaticNavigation.d.ts +189 -109
  135. package/lib/typescript/src/StaticNavigation.d.ts.map +1 -1
  136. package/lib/typescript/src/StaticTreeContext.d.ts +4 -0
  137. package/lib/typescript/src/StaticTreeContext.d.ts.map +1 -0
  138. package/lib/typescript/src/checkSerializable.d.ts +8 -4
  139. package/lib/typescript/src/checkSerializable.d.ts.map +1 -1
  140. package/lib/typescript/src/createNavigationContainerRef.d.ts +1 -1
  141. package/lib/typescript/src/createNavigationContainerRef.d.ts.map +1 -1
  142. package/lib/typescript/src/createNavigatorFactory.d.ts +23 -5
  143. package/lib/typescript/src/createNavigatorFactory.d.ts.map +1 -1
  144. package/lib/typescript/src/findFocusedRoute.d.ts +3 -3
  145. package/lib/typescript/src/findFocusedRoute.d.ts.map +1 -1
  146. package/lib/typescript/src/getActionFromState.d.ts +4 -4
  147. package/lib/typescript/src/getActionFromState.d.ts.map +1 -1
  148. package/lib/typescript/src/getPathFromState.d.ts +3 -3
  149. package/lib/typescript/src/getPathFromState.d.ts.map +1 -1
  150. package/lib/typescript/src/getPatternParts.d.ts +1 -0
  151. package/lib/typescript/src/getPatternParts.d.ts.map +1 -1
  152. package/lib/typescript/src/getStateFromPath.d.ts +5 -5
  153. package/lib/typescript/src/getStateFromPath.d.ts.map +1 -1
  154. package/lib/typescript/src/getStateFromRouteParams.d.ts +3 -0
  155. package/lib/typescript/src/getStateFromRouteParams.d.ts.map +1 -0
  156. package/lib/typescript/src/index.d.ts +36 -33
  157. package/lib/typescript/src/index.d.ts.map +1 -1
  158. package/lib/typescript/src/theming/ThemeContext.d.ts +1 -1
  159. package/lib/typescript/src/theming/ThemeContext.d.ts.map +1 -1
  160. package/lib/typescript/src/theming/ThemeProvider.d.ts +2 -2
  161. package/lib/typescript/src/theming/ThemeProvider.d.ts.map +1 -1
  162. package/lib/typescript/src/theming/useTheme.d.ts +1 -1
  163. package/lib/typescript/src/theming/useTheme.d.ts.map +1 -1
  164. package/lib/typescript/src/types.d.ts +260 -159
  165. package/lib/typescript/src/types.d.ts.map +1 -1
  166. package/lib/typescript/src/useChildListeners.d.ts +3 -3
  167. package/lib/typescript/src/useChildListeners.d.ts.map +1 -1
  168. package/lib/typescript/src/useComponent.d.ts +1 -1
  169. package/lib/typescript/src/useComponent.d.ts.map +1 -1
  170. package/lib/typescript/src/useDescriptors.d.ts +8 -8
  171. package/lib/typescript/src/useDescriptors.d.ts.map +1 -1
  172. package/lib/typescript/src/useEventEmitter.d.ts +2 -2
  173. package/lib/typescript/src/useEventEmitter.d.ts.map +1 -1
  174. package/lib/typescript/src/useFocusEvents.d.ts +2 -2
  175. package/lib/typescript/src/useFocusEvents.d.ts.map +1 -1
  176. package/lib/typescript/src/useFocusedListenersChildrenAdapter.d.ts +2 -2
  177. package/lib/typescript/src/useFocusedListenersChildrenAdapter.d.ts.map +1 -1
  178. package/lib/typescript/src/useIsFocused.d.ts +3 -0
  179. package/lib/typescript/src/useIsFocused.d.ts.map +1 -1
  180. package/lib/typescript/src/useKeyedChildListeners.d.ts +3 -3
  181. package/lib/typescript/src/useKeyedChildListeners.d.ts.map +1 -1
  182. package/lib/typescript/src/useLazyValue.d.ts.map +1 -1
  183. package/lib/typescript/src/useNavigation.d.ts +4 -2
  184. package/lib/typescript/src/useNavigation.d.ts.map +1 -1
  185. package/lib/typescript/src/useNavigationBuilder.d.ts +23 -30
  186. package/lib/typescript/src/useNavigationBuilder.d.ts.map +1 -1
  187. package/lib/typescript/src/useNavigationCache.d.ts +3 -3
  188. package/lib/typescript/src/useNavigationCache.d.ts.map +1 -1
  189. package/lib/typescript/src/useNavigationContainerRef.d.ts +1 -1
  190. package/lib/typescript/src/useNavigationContainerRef.d.ts.map +1 -1
  191. package/lib/typescript/src/useNavigationHelpers.d.ts +19 -27
  192. package/lib/typescript/src/useNavigationHelpers.d.ts.map +1 -1
  193. package/lib/typescript/src/useNavigationState.d.ts +13 -3
  194. package/lib/typescript/src/useNavigationState.d.ts.map +1 -1
  195. package/lib/typescript/src/useOnAction.d.ts +9 -9
  196. package/lib/typescript/src/useOnAction.d.ts.map +1 -1
  197. package/lib/typescript/src/useOnGetState.d.ts +1 -1
  198. package/lib/typescript/src/useOnGetState.d.ts.map +1 -1
  199. package/lib/typescript/src/useOnPreventRemove.d.ts +5 -9
  200. package/lib/typescript/src/useOnPreventRemove.d.ts.map +1 -1
  201. package/lib/typescript/src/useOnRouteFocus.d.ts +6 -6
  202. package/lib/typescript/src/useOnRouteFocus.d.ts.map +1 -1
  203. package/lib/typescript/src/useOptionsGetters.d.ts +1 -1
  204. package/lib/typescript/src/useOptionsGetters.d.ts.map +1 -1
  205. package/lib/typescript/src/usePreventRemove.d.ts.map +1 -1
  206. package/lib/typescript/src/usePreventRemoveContext.d.ts +2 -1
  207. package/lib/typescript/src/usePreventRemoveContext.d.ts.map +1 -1
  208. package/lib/typescript/src/useRoute.d.ts +7 -3
  209. package/lib/typescript/src/useRoute.d.ts.map +1 -1
  210. package/lib/typescript/src/useRouteCache.d.ts +5 -5
  211. package/lib/typescript/src/useRouteCache.d.ts.map +1 -1
  212. package/lib/typescript/src/useScheduleUpdate.d.ts +5 -4
  213. package/lib/typescript/src/useScheduleUpdate.d.ts.map +1 -1
  214. package/lib/typescript/src/useStateForPath.d.ts +1 -1
  215. package/lib/typescript/src/useStateForPath.d.ts.map +1 -1
  216. package/lib/typescript/src/useSyncState.d.ts.map +1 -1
  217. package/lib/typescript/src/utilities.d.ts +74 -37
  218. package/lib/typescript/src/utilities.d.ts.map +1 -1
  219. package/lib/typescript/src/validatePathConfig.d.ts.map +1 -1
  220. package/package.json +23 -22
  221. package/src/BaseNavigationContainer.tsx +351 -333
  222. package/src/ConsumedParamsContext.tsx +5 -0
  223. package/src/DataLoading.tsx +203 -0
  224. package/src/NavigationBuilderContext.tsx +14 -9
  225. package/src/NavigationFocusedRouteStateContext.tsx +4 -4
  226. package/src/NavigationIndependentTree.tsx +18 -12
  227. package/src/NavigationProvider.tsx +26 -15
  228. package/src/NavigationStateContext.tsx +5 -6
  229. package/src/PreventRemoveContext.tsx +1 -0
  230. package/src/PreventRemoveProvider.tsx +51 -46
  231. package/src/SceneView.tsx +7 -39
  232. package/src/StaticNavigation.tsx +659 -307
  233. package/src/StaticTreeContext.tsx +7 -0
  234. package/src/checkSerializable.tsx +35 -19
  235. package/src/createNavigationContainerRef.tsx +12 -9
  236. package/src/createNavigatorFactory.tsx +92 -8
  237. package/src/findFocusedRoute.tsx +13 -8
  238. package/src/getActionFromState.tsx +86 -51
  239. package/src/getPathFromState.tsx +254 -128
  240. package/src/getPatternParts.tsx +25 -4
  241. package/src/getStateFromPath.tsx +811 -309
  242. package/src/getStateFromRouteParams.tsx +60 -0
  243. package/src/index.tsx +55 -5
  244. package/src/theming/useTheme.tsx +1 -1
  245. package/src/types.tsx +798 -373
  246. package/src/useDescriptors.tsx +28 -14
  247. package/src/useEventEmitter.tsx +52 -38
  248. package/src/useFocusEvents.tsx +15 -7
  249. package/src/useFocusedListenersChildrenAdapter.tsx +2 -2
  250. package/src/useIsFocused.tsx +14 -21
  251. package/src/useKeyedChildListeners.tsx +4 -2
  252. package/src/useLazyValue.tsx +2 -2
  253. package/src/useNavigation.tsx +7 -24
  254. package/src/useNavigationBuilder.tsx +311 -186
  255. package/src/useNavigationCache.tsx +32 -25
  256. package/src/useNavigationHelpers.tsx +27 -10
  257. package/src/useNavigationIndependentTree.tsx +1 -1
  258. package/src/useNavigationState.tsx +93 -59
  259. package/src/useOnAction.tsx +61 -13
  260. package/src/useOnGetState.tsx +5 -3
  261. package/src/useOnPreventRemove.tsx +75 -42
  262. package/src/useOnRouteFocus.tsx +10 -12
  263. package/src/useOptionsGetters.tsx +11 -5
  264. package/src/usePreventRemove.tsx +12 -3
  265. package/src/usePreventRemoveContext.tsx +1 -1
  266. package/src/useRegisterNavigator.tsx +2 -2
  267. package/src/useRoute.tsx +20 -6
  268. package/src/useRouteCache.tsx +22 -16
  269. package/src/useScheduleUpdate.tsx +9 -10
  270. package/src/useStateForPath.tsx +1 -1
  271. package/src/useSyncState.tsx +8 -3
  272. package/src/utilities.tsx +144 -31
  273. package/src/validatePathConfig.tsx +86 -57
  274. package/lib/module/CurrentRenderContext.js +0 -10
  275. package/lib/module/CurrentRenderContext.js.map +0 -1
  276. package/lib/module/useCurrentRender.js +0 -19
  277. package/lib/module/useCurrentRender.js.map +0 -1
  278. package/lib/typescript/src/CurrentRenderContext.d.ts +0 -9
  279. package/lib/typescript/src/CurrentRenderContext.d.ts.map +0 -1
  280. package/lib/typescript/src/useCurrentRender.d.ts +0 -14
  281. package/lib/typescript/src/useCurrentRender.d.ts.map +0 -1
  282. package/src/CurrentRenderContext.tsx +0 -9
  283. package/src/useCurrentRender.tsx +0 -31
@@ -0,0 +1,7 @@
1
+ import * as React from 'react';
2
+
3
+ import type { TreeForPathConfig } from './StaticNavigation';
4
+
5
+ export const StaticTreeContext = React.createContext<
6
+ TreeForPathConfig | undefined
7
+ >(undefined);
@@ -1,14 +1,18 @@
1
+ type Success = { serializable: true };
2
+
3
+ type Failure = {
4
+ serializable: false;
5
+ location: (string | number)[];
6
+ reason: string;
7
+ };
8
+
9
+ type Result = Success | Failure;
10
+
1
11
  const checkSerializableWithoutCircularReference = (
2
12
  o: { [key: string]: any },
3
13
  seen: Set<any>,
4
14
  location: (string | number)[]
5
- ):
6
- | { serializable: true }
7
- | {
8
- serializable: false;
9
- location: (string | number)[];
10
- reason: string;
11
- } => {
15
+ ): Failure | undefined => {
12
16
  if (
13
17
  o === undefined ||
14
18
  o === null ||
@@ -16,7 +20,7 @@ const checkSerializableWithoutCircularReference = (
16
20
  typeof o === 'number' ||
17
21
  typeof o === 'string'
18
22
  ) {
19
- return { serializable: true };
23
+ return undefined;
20
24
  }
21
25
 
22
26
  if (
@@ -25,7 +29,7 @@ const checkSerializableWithoutCircularReference = (
25
29
  ) {
26
30
  return {
27
31
  serializable: false,
28
- location,
32
+ location: location.slice(),
29
33
  reason: typeof o === 'function' ? 'Function' : String(o),
30
34
  };
31
35
  }
@@ -34,7 +38,7 @@ const checkSerializableWithoutCircularReference = (
34
38
  return {
35
39
  serializable: false,
36
40
  reason: 'Circular reference',
37
- location,
41
+ location: location.slice(),
38
42
  };
39
43
  }
40
44
 
@@ -42,33 +46,45 @@ const checkSerializableWithoutCircularReference = (
42
46
 
43
47
  if (Array.isArray(o)) {
44
48
  for (let i = 0; i < o.length; i++) {
49
+ location.push(i);
45
50
  const childResult = checkSerializableWithoutCircularReference(
46
51
  o[i],
47
- new Set<any>(seen),
48
- [...location, i]
52
+ seen,
53
+ location
49
54
  );
55
+ location.pop();
50
56
 
51
- if (!childResult.serializable) {
57
+ if (childResult) {
58
+ seen.delete(o);
52
59
  return childResult;
53
60
  }
54
61
  }
55
62
  } else {
56
63
  for (const key in o) {
64
+ location.push(key);
57
65
  const childResult = checkSerializableWithoutCircularReference(
58
66
  o[key],
59
- new Set<any>(seen),
60
- [...location, key]
67
+ seen,
68
+ location
61
69
  );
70
+ location.pop();
62
71
 
63
- if (!childResult.serializable) {
72
+ if (childResult) {
73
+ seen.delete(o);
64
74
  return childResult;
65
75
  }
66
76
  }
67
77
  }
68
78
 
69
- return { serializable: true };
79
+ seen.delete(o);
80
+
81
+ return undefined;
70
82
  };
71
83
 
72
- export function checkSerializable(o: { [key: string]: any }) {
73
- return checkSerializableWithoutCircularReference(o, new Set<any>(), []);
84
+ export function checkSerializable(o: { [key: string]: any }): Result {
85
+ return (
86
+ checkSerializableWithoutCircularReference(o, new Set<any>(), []) ?? {
87
+ serializable: true,
88
+ }
89
+ );
74
90
  }
@@ -30,6 +30,8 @@ export function createNavigationContainerRef<
30
30
 
31
31
  const listeners: Record<string, ((...args: any[]) => void)[]> = {};
32
32
 
33
+ let current: NavigationContainerRef<ParamList> | null = null;
34
+
33
35
  const removeListener = (
34
36
  event: string,
35
37
  callback: (...args: any[]) => void
@@ -37,9 +39,12 @@ export function createNavigationContainerRef<
37
39
  if (listeners[event]) {
38
40
  listeners[event] = listeners[event].filter((cb) => cb !== callback);
39
41
  }
40
- };
41
42
 
42
- let current: NavigationContainerRef<ParamList> | null = null;
43
+ current?.removeListener(
44
+ event as keyof NavigationContainerEventMap,
45
+ callback
46
+ );
47
+ };
43
48
 
44
49
  const ref: NavigationContainerRefWithCurrent<ParamList> = {
45
50
  get current() {
@@ -68,7 +73,11 @@ export function createNavigationContainerRef<
68
73
  },
69
74
  ...methods.reduce<any>((acc, name) => {
70
75
  acc[name] = (...args: any[]) => {
71
- if (current == null) {
76
+ if (name === 'removeListener') {
77
+ const [event, callback] = args;
78
+
79
+ removeListener(event, callback);
80
+ } else if (current == null) {
72
81
  switch (name) {
73
82
  case 'addListener': {
74
83
  const [event, callback] = args;
@@ -78,12 +87,6 @@ export function createNavigationContainerRef<
78
87
 
79
88
  return () => removeListener(event, callback);
80
89
  }
81
- case 'removeListener': {
82
- const [event, callback] = args;
83
-
84
- removeListener(event, callback);
85
- break;
86
- }
87
90
  default:
88
91
  console.error(NOT_INITIALIZED_ERROR);
89
92
  }
@@ -1,23 +1,107 @@
1
- import type * as React from 'react';
1
+ import type { ParamListBase } from '@react-navigation/routers';
2
+ import * as React from 'react';
2
3
 
3
4
  import { Group } from './Group';
4
5
  import { Screen } from './Screen';
6
+ import {
7
+ createComponentForStaticConfig,
8
+ type NoExcessStaticConfig,
9
+ type StaticConfig,
10
+ type StaticParamList,
11
+ } from './StaticNavigation';
12
+ import type {
13
+ NavigatorTypeBagBase,
14
+ NavigatorTypeBagFor,
15
+ NestedNavigatorsForParamList,
16
+ TypedNavigator,
17
+ } from './types';
18
+ import type { KeysOf, NoExcessObject } from './utilities';
19
+
20
+ type NavigatorNesting<ParamList extends ParamListBase, Nesting> = {
21
+ [RouteName in keyof ParamList]?: unknown;
22
+ } & Record<Exclude<KeysOf<Nesting>, keyof ParamList>, never>;
23
+
24
+ type ValidNavigatorNesting<ParamList extends ParamListBase, Nesting> =
25
+ Nesting extends NavigatorNesting<ParamList, Nesting> ? Nesting : never;
26
+
27
+ type AnyStaticConfig<TypeBag extends NavigatorTypeBagBase> = StaticConfig<
28
+ NavigatorTypeBagFor<TypeBag, ParamListBase>
29
+ >;
30
+
31
+ export type TypedNavigatorFactory<in out TypeBag extends NavigatorTypeBagBase> =
32
+ {
33
+ <
34
+ const ParamList extends ParamListBase,
35
+ const Nesting extends NavigatorNesting<ParamList, Nesting> =
36
+ ValidNavigatorNesting<
37
+ ParamList,
38
+ NestedNavigatorsForParamList<ParamList>
39
+ >,
40
+ >(): TypedNavigator<
41
+ NavigatorTypeBagFor<TypeBag, ParamList>,
42
+ undefined,
43
+ Nesting
44
+ >;
45
+ <
46
+ const Config extends AnyStaticConfig<TypeBag> &
47
+ NoExcessObject<Config, AnyStaticConfig<TypeBag>>,
48
+ >(
49
+ config: Config & NoExcessStaticConfig<NoInfer<Config>, TypeBag>
50
+ ): TypedNavigator<
51
+ NavigatorTypeBagFor<TypeBag, StaticParamList<{ config: Config }>>,
52
+ Config
53
+ >;
54
+ };
5
55
 
6
56
  /**
7
- * Higher order component to create a `Navigator` and `Screen` pair.
8
- * Custom navigators should wrap the navigator component in `createNavigator` before exporting.
57
+ * Higher order function to create a navigator factory
58
+ * A navigator factory creates a navigator:
59
+ * - `Navigator` and `Screen` pairs for dynamic configuration
60
+ * - Static navigator object for static configuration
9
61
  *
10
62
  * @param Navigator The navigator component to wrap.
11
- * @returns Factory method to create a `Navigator` and `Screen` pair.
63
+ * @returns Factory method to create a navigator
12
64
  */
13
- export function createNavigatorFactory(Navigator: React.ComponentType<any>) {
65
+ export function createNavigatorFactory<TypeBag extends NavigatorTypeBagBase>(
66
+ Navigator: React.ComponentType<any>
67
+ ): TypedNavigatorFactory<TypeBag> {
68
+ const displayName = Navigator.displayName ?? Navigator.name ?? 'Navigator';
69
+
14
70
  function createNavigator(config?: any): any {
15
71
  if (config != null) {
72
+ const NavigatorComponent = createComponentForStaticConfig(
73
+ {
74
+ Navigator,
75
+ Screen,
76
+ Group,
77
+ config,
78
+ },
79
+ displayName
80
+ );
81
+
16
82
  return {
17
- Navigator,
18
- Screen,
19
- Group,
20
83
  config,
84
+ with(
85
+ DecoratorComponent: React.ComponentType<{
86
+ Navigator: React.ComponentType<any>;
87
+ }>
88
+ ) {
89
+ const WithComponent = () => {
90
+ return React.createElement(DecoratorComponent, {
91
+ Navigator: NavigatorComponent,
92
+ });
93
+ };
94
+
95
+ WithComponent.displayName = `${displayName}With`;
96
+
97
+ return {
98
+ config,
99
+ getComponent: () => WithComponent,
100
+ };
101
+ },
102
+ getComponent() {
103
+ return NavigatorComponent;
104
+ },
21
105
  };
22
106
  }
23
107
 
@@ -2,21 +2,26 @@ import type { InitialState } from '@react-navigation/routers';
2
2
 
3
3
  type Result =
4
4
  | {
5
- key?: string;
5
+ key?: string | undefined;
6
6
  name: string;
7
- params?: object;
8
- path?: string;
7
+ params?: object | undefined;
8
+ path?: string | undefined;
9
9
  }
10
10
  | undefined;
11
11
 
12
12
  export function findFocusedRoute(state: InitialState): Result {
13
13
  let current: InitialState | undefined = state;
14
14
 
15
- while (current?.routes[current.index ?? 0].state != null) {
16
- current = current.routes[current.index ?? 0].state;
17
- }
15
+ while (current != null) {
16
+ const route: InitialState['routes'][number] | undefined =
17
+ current.routes[current.index ?? current.routes.length - 1];
18
+
19
+ if (route?.state == null) {
20
+ return route;
21
+ }
18
22
 
19
- const route = current?.routes[current?.index ?? 0];
23
+ current = route.state;
24
+ }
20
25
 
21
- return route;
26
+ return undefined;
22
27
  }
@@ -2,20 +2,18 @@ import type {
2
2
  CommonActions,
3
3
  NavigationState,
4
4
  ParamListBase,
5
- PartialRoute,
6
5
  PartialState,
7
- Route,
8
6
  } from '@react-navigation/routers';
9
7
 
10
8
  import type { NavigatorScreenParams, PathConfig, PathConfigMap } from './types';
11
9
 
12
10
  type ConfigItem = {
13
- initialRouteName?: string;
14
- screens?: Record<string, ConfigItem>;
11
+ initialRouteName?: string | undefined;
12
+ screens?: Record<string, ConfigItem> | undefined;
15
13
  };
16
14
 
17
15
  type Options = {
18
- initialRouteName?: string;
16
+ initialRouteName?: string | undefined;
19
17
  screens: PathConfigMap<object>;
20
18
  };
21
19
 
@@ -23,34 +21,60 @@ type NavigateAction<State extends NavigationState> = {
23
21
  type: 'NAVIGATE';
24
22
  payload: {
25
23
  name: string;
26
- params?: NavigatorScreenParams<State>;
27
- path?: string;
24
+ params?: NavigatorScreenParams<State> | undefined;
25
+ path?: string | undefined;
28
26
  };
29
27
  };
30
28
 
29
+ // Cache the normalized config across calls for the same `options` reference,
30
+ // so we don't re-walk the config tree on every action conversion.
31
+ const cachedNormalizedConfig = new WeakMap<Options, ConfigItem>();
32
+
31
33
  export function getActionFromState(
32
34
  state: PartialState<NavigationState>,
33
35
  options?: Options
34
36
  ): NavigateAction<NavigationState> | CommonActions.Action | undefined {
35
- // Create a normalized configs object which will be easier to use
36
- const normalizedConfig = options
37
- ? createNormalizedConfigItem(options as PathConfig<object> | string)
38
- : {};
37
+ let normalizedConfig;
38
+
39
+ if (options) {
40
+ const cached = cachedNormalizedConfig.get(options);
41
+
42
+ if (cached) {
43
+ normalizedConfig = cached;
44
+ } else {
45
+ normalizedConfig = createNormalizedConfigItem(
46
+ options as PathConfig<object> | string
47
+ );
48
+ cachedNormalizedConfig.set(options, normalizedConfig as ConfigItem);
49
+ }
50
+ } else {
51
+ normalizedConfig = {};
52
+ }
39
53
 
40
- const routes =
41
- state.index != null ? state.routes.slice(0, state.index + 1) : state.routes;
54
+ const routesLength =
55
+ state.index == null || state.index >= state.routes.length
56
+ ? state.routes.length
57
+ : state.index + 1;
42
58
 
43
- if (routes.length === 0) {
59
+ if (routesLength === 0) {
44
60
  return undefined;
45
61
  }
46
62
 
63
+ const firstRoute = state.routes[0];
64
+
65
+ if (firstRoute == null) {
66
+ return undefined;
67
+ }
68
+
69
+ const secondRoute = state.routes[1];
70
+
47
71
  if (
48
72
  !(
49
- (routes.length === 1 && routes[0].key === undefined) ||
50
- (routes.length === 2 &&
51
- routes[0].key === undefined &&
52
- routes[0].name === normalizedConfig?.initialRouteName &&
53
- routes[1].key === undefined)
73
+ (routesLength === 1 && firstRoute.key == null) ||
74
+ (routesLength === 2 &&
75
+ firstRoute.key == null &&
76
+ firstRoute.name === normalizedConfig?.initialRouteName &&
77
+ secondRoute?.key == null)
54
78
  )
55
79
  ) {
56
80
  return {
@@ -61,20 +85,20 @@ export function getActionFromState(
61
85
 
62
86
  const route = state.routes[state.index ?? state.routes.length - 1];
63
87
 
64
- let current: PartialState<NavigationState> | undefined = route?.state;
65
- let config: ConfigItem | undefined = normalizedConfig?.screens?.[route?.name];
88
+ if (route == null) {
89
+ return undefined;
90
+ }
91
+
92
+ let current: PartialState<NavigationState> | undefined = route.state;
93
+ let config: ConfigItem | undefined = normalizedConfig?.screens?.[route.name];
66
94
  let params = { ...route.params } as NavigatorScreenParams<ParamListBase>;
67
95
 
68
- const payload:
69
- | {
70
- name: string;
71
- params: NavigatorScreenParams<ParamListBase>;
72
- path?: string;
73
- pop?: boolean;
74
- }
75
- | undefined = route
76
- ? { name: route.name, path: route.path, params }
77
- : undefined;
96
+ const payload: {
97
+ name: string;
98
+ params: NavigatorScreenParams<ParamListBase>;
99
+ path?: string | undefined;
100
+ pop?: boolean | undefined;
101
+ } = { name: route.name, path: route.path, params };
78
102
 
79
103
  // If the screen contains a navigator, pop other screens to navigate to it
80
104
  // This avoid pushing multiple instances of navigators onto a stack
@@ -90,7 +114,7 @@ export function getActionFromState(
90
114
  // There are 2 ways we can detect if a screen contains a navigator:
91
115
  // - The route contains nested state in `route.state`
92
116
  // - Nested screens are defined in the config
93
- if (payload && config?.screens && Object.keys(config.screens).length) {
117
+ if (config?.screens && Object.keys(config.screens).length) {
94
118
  payload.pop = true;
95
119
  }
96
120
 
@@ -99,13 +123,24 @@ export function getActionFromState(
99
123
  return undefined;
100
124
  }
101
125
 
102
- const routes =
103
- current.index != null
104
- ? current.routes.slice(0, current.index + 1)
105
- : current.routes;
126
+ const routesLength =
127
+ current.index == null || current.index >= current.routes.length
128
+ ? current.routes.length
129
+ : current.index + 1;
130
+
131
+ const route = current.routes[routesLength - 1];
132
+
133
+ if (route == null) {
134
+ return undefined;
135
+ }
136
+
137
+ const firstRoute = current.routes[0];
138
+
139
+ if (firstRoute == null) {
140
+ return undefined;
141
+ }
106
142
 
107
- const route: Route<string> | PartialRoute<Route<string>> =
108
- routes[routes.length - 1];
143
+ const secondRoute = current.routes[1];
109
144
 
110
145
  // Explicitly set to override existing value when merging params
111
146
  Object.assign(params, {
@@ -115,14 +150,14 @@ export function getActionFromState(
115
150
  state: undefined,
116
151
  });
117
152
 
118
- if (routes.length === 1 && routes[0].key === undefined) {
153
+ if (routesLength === 1 && firstRoute.key == null) {
119
154
  params.initial = true;
120
155
  params.screen = route.name;
121
156
  } else if (
122
- routes.length === 2 &&
123
- routes[0].key === undefined &&
124
- routes[0].name === config?.initialRouteName &&
125
- routes[1].key === undefined
157
+ routesLength === 2 &&
158
+ firstRoute.key == null &&
159
+ firstRoute.name === config?.initialRouteName &&
160
+ secondRoute?.key == null
126
161
  ) {
127
162
  params.initial = false;
128
163
  params.screen = route.name;
@@ -148,14 +183,10 @@ export function getActionFromState(
148
183
  }
149
184
  }
150
185
 
151
- if (payload?.params.screen || payload?.params.state) {
186
+ if (payload.params.screen || payload.params.state) {
152
187
  payload.pop = true;
153
188
  }
154
189
 
155
- if (!payload) {
156
- return;
157
- }
158
-
159
190
  // Try to construct payload for a `NAVIGATE` action from the state
160
191
  // This lets us preserve the navigation state and not lose it
161
192
  return {
@@ -164,11 +195,16 @@ export function getActionFromState(
164
195
  };
165
196
  }
166
197
 
167
- const createNormalizedConfigItem = (config: PathConfig<object> | string) =>
198
+ const createNormalizedConfigItem = (
199
+ config: PathConfig<object> | string
200
+ ): ConfigItem =>
168
201
  typeof config === 'object' && config != null
169
202
  ? {
170
203
  initialRouteName:
171
- 'initialRouteName' in config ? config.initialRouteName : undefined,
204
+ 'initialRouteName' in config &&
205
+ typeof config.initialRouteName === 'string'
206
+ ? config.initialRouteName
207
+ : undefined,
172
208
  screens:
173
209
  'screens' in config && config.screens != null
174
210
  ? createNormalizedConfigs(config.screens)
@@ -178,7 +214,6 @@ const createNormalizedConfigItem = (config: PathConfig<object> | string) =>
178
214
 
179
215
  const createNormalizedConfigs = (options: PathConfigMap<object>) =>
180
216
  Object.entries(options).reduce<Record<string, ConfigItem>>((acc, [k, v]) => {
181
- // @ts-expect-error -we can't properly type this
182
217
  acc[k] = createNormalizedConfigItem(v);
183
218
  return acc;
184
219
  }, {});