one 1.1.390 → 1.1.391

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 (241) hide show
  1. package/dist/cjs/Root.cjs +6 -17
  2. package/dist/cjs/Root.js +9 -13
  3. package/dist/cjs/Root.js.map +1 -1
  4. package/dist/cjs/Root.native.js +4 -12
  5. package/dist/cjs/Root.native.js.map +1 -1
  6. package/dist/cjs/fork/NavigationContainer.cjs +49 -31
  7. package/dist/cjs/fork/NavigationContainer.js +40 -21
  8. package/dist/cjs/fork/NavigationContainer.js.map +2 -2
  9. package/dist/cjs/fork/NavigationContainer.native.js +51 -29
  10. package/dist/cjs/fork/NavigationContainer.native.js.map +2 -2
  11. package/dist/cjs/fork/createMemoryHistory.cjs +4 -3
  12. package/dist/cjs/fork/createMemoryHistory.js +3 -2
  13. package/dist/cjs/fork/createMemoryHistory.js.map +1 -1
  14. package/dist/cjs/fork/createMemoryHistory.native.js +8 -4
  15. package/dist/cjs/fork/createMemoryHistory.native.js.map +2 -2
  16. package/dist/cjs/fork/extractPathFromURL.cjs +48 -28
  17. package/dist/cjs/fork/extractPathFromURL.js +44 -21
  18. package/dist/cjs/fork/extractPathFromURL.js.map +2 -2
  19. package/dist/cjs/fork/extractPathFromURL.native.js +58 -26
  20. package/dist/cjs/fork/extractPathFromURL.native.js.map +2 -2
  21. package/dist/cjs/fork/findFocusedRoute.js.map +1 -1
  22. package/dist/cjs/fork/findFocusedRoute.native.js.map +1 -1
  23. package/dist/cjs/fork/getPathFromState-mods.cjs +65 -0
  24. package/dist/cjs/fork/getPathFromState-mods.js +56 -0
  25. package/dist/cjs/fork/getPathFromState-mods.js.map +6 -0
  26. package/dist/cjs/fork/getPathFromState-mods.native.js +70 -0
  27. package/dist/cjs/fork/getPathFromState-mods.native.js.map +6 -0
  28. package/dist/cjs/fork/getPathFromState.cjs +75 -224
  29. package/dist/cjs/fork/getPathFromState.js +68 -223
  30. package/dist/cjs/fork/getPathFromState.js.map +2 -2
  31. package/dist/cjs/fork/getPathFromState.native.js +79 -261
  32. package/dist/cjs/fork/getPathFromState.native.js.map +2 -2
  33. package/dist/cjs/fork/getStateFromPath-mods.cjs +187 -0
  34. package/dist/cjs/fork/getStateFromPath-mods.js +199 -0
  35. package/dist/cjs/fork/getStateFromPath-mods.js.map +6 -0
  36. package/dist/cjs/fork/getStateFromPath-mods.native.js +284 -0
  37. package/dist/cjs/fork/getStateFromPath-mods.native.js.map +6 -0
  38. package/dist/cjs/fork/getStateFromPath.cjs +181 -263
  39. package/dist/cjs/fork/getStateFromPath.js +148 -264
  40. package/dist/cjs/fork/getStateFromPath.js.map +2 -2
  41. package/dist/cjs/fork/getStateFromPath.native.js +164 -304
  42. package/dist/cjs/fork/getStateFromPath.native.js.map +2 -2
  43. package/dist/cjs/fork/useBackButton.js.map +1 -1
  44. package/dist/cjs/fork/useBackButton.native.js.map +1 -1
  45. package/dist/cjs/fork/useDocumentTitle.js +4 -1
  46. package/dist/cjs/fork/useDocumentTitle.js.map +1 -1
  47. package/dist/cjs/fork/useDocumentTitle.native.js +1 -1
  48. package/dist/cjs/fork/useDocumentTitle.native.js.map +2 -2
  49. package/dist/cjs/fork/useLinking.cjs +21 -24
  50. package/dist/cjs/fork/useLinking.js +21 -25
  51. package/dist/cjs/fork/useLinking.js.map +2 -2
  52. package/dist/cjs/fork/useLinking.native.js +68 -66
  53. package/dist/cjs/fork/useLinking.native.js.map +2 -2
  54. package/dist/cjs/fork/useThenable.js.map +1 -1
  55. package/dist/cjs/fork/useThenable.native.js.map +1 -1
  56. package/dist/cjs/fork/validatePathConfig.cjs +32 -11
  57. package/dist/cjs/fork/validatePathConfig.js +41 -11
  58. package/dist/cjs/fork/validatePathConfig.js.map +1 -1
  59. package/dist/cjs/fork/validatePathConfig.native.js +47 -18
  60. package/dist/cjs/fork/validatePathConfig.native.js.map +2 -2
  61. package/dist/cjs/layouts/withLayoutContext.cjs +1 -1
  62. package/dist/cjs/layouts/withLayoutContext.js +1 -1
  63. package/dist/cjs/layouts/withLayoutContext.js.map +1 -1
  64. package/dist/cjs/layouts/withLayoutContext.native.js +1 -1
  65. package/dist/cjs/layouts/withLayoutContext.native.js.map +1 -1
  66. package/dist/cjs/link/linking.cjs +4 -4
  67. package/dist/cjs/link/linking.js +3 -3
  68. package/dist/cjs/link/linking.js.map +2 -2
  69. package/dist/cjs/link/linking.native.js +3 -3
  70. package/dist/cjs/link/linking.native.js.map +1 -1
  71. package/dist/cjs/link/useLinkTo.cjs +2 -2
  72. package/dist/cjs/link/useLinkTo.js +2 -2
  73. package/dist/cjs/link/useLinkTo.js.map +1 -1
  74. package/dist/cjs/link/useLinkTo.native.js +2 -2
  75. package/dist/cjs/link/useLinkTo.native.js.map +1 -1
  76. package/dist/cjs/router/getNormalizedStatePath.cjs +2 -2
  77. package/dist/cjs/router/getNormalizedStatePath.js +2 -2
  78. package/dist/cjs/router/getNormalizedStatePath.js.map +1 -1
  79. package/dist/cjs/router/getNormalizedStatePath.native.js +2 -2
  80. package/dist/cjs/router/getNormalizedStatePath.native.js.map +1 -1
  81. package/dist/cjs/router/router.cjs +19 -3
  82. package/dist/cjs/router/router.js +25 -3
  83. package/dist/cjs/router/router.js.map +1 -1
  84. package/dist/cjs/router/router.native.js +39 -3
  85. package/dist/cjs/router/router.native.js.map +2 -2
  86. package/dist/esm/Root.js +6 -2
  87. package/dist/esm/Root.js.map +1 -1
  88. package/dist/esm/Root.mjs +1 -1
  89. package/dist/esm/Root.mjs.map +1 -1
  90. package/dist/esm/Root.native.js +1 -1
  91. package/dist/esm/Root.native.js.map +2 -2
  92. package/dist/esm/fork/NavigationContainer.js +43 -20
  93. package/dist/esm/fork/NavigationContainer.js.map +1 -1
  94. package/dist/esm/fork/NavigationContainer.mjs +42 -24
  95. package/dist/esm/fork/NavigationContainer.mjs.map +1 -1
  96. package/dist/esm/fork/NavigationContainer.native.js +44 -24
  97. package/dist/esm/fork/NavigationContainer.native.js.map +2 -2
  98. package/dist/esm/fork/createMemoryHistory.js +3 -2
  99. package/dist/esm/fork/createMemoryHistory.js.map +1 -1
  100. package/dist/esm/fork/createMemoryHistory.mjs +4 -3
  101. package/dist/esm/fork/createMemoryHistory.mjs.map +1 -1
  102. package/dist/esm/fork/createMemoryHistory.native.js +4 -4
  103. package/dist/esm/fork/createMemoryHistory.native.js.map +2 -2
  104. package/dist/esm/fork/extractPathFromURL.js +42 -11
  105. package/dist/esm/fork/extractPathFromURL.js.map +1 -1
  106. package/dist/esm/fork/extractPathFromURL.mjs +39 -11
  107. package/dist/esm/fork/extractPathFromURL.mjs.map +1 -1
  108. package/dist/esm/fork/extractPathFromURL.native.js +52 -15
  109. package/dist/esm/fork/extractPathFromURL.native.js.map +2 -2
  110. package/dist/esm/fork/findFocusedRoute.js.map +1 -1
  111. package/dist/esm/fork/findFocusedRoute.mjs.map +1 -1
  112. package/dist/esm/fork/findFocusedRoute.native.js.map +1 -1
  113. package/dist/esm/fork/getPathFromState-mods.js +40 -0
  114. package/dist/esm/fork/getPathFromState-mods.js.map +6 -0
  115. package/dist/esm/fork/getPathFromState-mods.mjs +40 -0
  116. package/dist/esm/fork/getPathFromState-mods.mjs.map +1 -0
  117. package/dist/esm/fork/getPathFromState-mods.native.js +47 -0
  118. package/dist/esm/fork/getPathFromState-mods.native.js.map +6 -0
  119. package/dist/esm/fork/getPathFromState.js +71 -228
  120. package/dist/esm/fork/getPathFromState.js.map +2 -2
  121. package/dist/esm/fork/getPathFromState.mjs +73 -221
  122. package/dist/esm/fork/getPathFromState.mjs.map +1 -1
  123. package/dist/esm/fork/getPathFromState.native.js +79 -260
  124. package/dist/esm/fork/getPathFromState.native.js.map +2 -2
  125. package/dist/esm/fork/getStateFromPath-mods.js +176 -0
  126. package/dist/esm/fork/getStateFromPath-mods.js.map +6 -0
  127. package/dist/esm/fork/getStateFromPath-mods.mjs +143 -0
  128. package/dist/esm/fork/getStateFromPath-mods.mjs.map +1 -0
  129. package/dist/esm/fork/getStateFromPath-mods.native.js +246 -0
  130. package/dist/esm/fork/getStateFromPath-mods.native.js.map +6 -0
  131. package/dist/esm/fork/getStateFromPath.js +160 -265
  132. package/dist/esm/fork/getStateFromPath.js.map +2 -2
  133. package/dist/esm/fork/getStateFromPath.mjs +181 -260
  134. package/dist/esm/fork/getStateFromPath.mjs.map +1 -1
  135. package/dist/esm/fork/getStateFromPath.native.js +164 -302
  136. package/dist/esm/fork/getStateFromPath.native.js.map +2 -2
  137. package/dist/esm/fork/useBackButton.js.map +1 -1
  138. package/dist/esm/fork/useBackButton.mjs.map +1 -1
  139. package/dist/esm/fork/useBackButton.native.js.map +1 -1
  140. package/dist/esm/fork/useDocumentTitle.js +4 -1
  141. package/dist/esm/fork/useDocumentTitle.js.map +1 -1
  142. package/dist/esm/fork/useDocumentTitle.mjs.map +1 -1
  143. package/dist/esm/fork/useDocumentTitle.native.js +1 -1
  144. package/dist/esm/fork/useDocumentTitle.native.js.map +2 -2
  145. package/dist/esm/fork/useLinking.js +22 -26
  146. package/dist/esm/fork/useLinking.js.map +1 -1
  147. package/dist/esm/fork/useLinking.mjs +20 -23
  148. package/dist/esm/fork/useLinking.mjs.map +1 -1
  149. package/dist/esm/fork/useLinking.native.js +65 -67
  150. package/dist/esm/fork/useLinking.native.js.map +2 -2
  151. package/dist/esm/fork/useThenable.js.map +1 -1
  152. package/dist/esm/fork/useThenable.mjs.map +1 -1
  153. package/dist/esm/fork/useThenable.native.js.map +1 -1
  154. package/dist/esm/fork/validatePathConfig.js +41 -11
  155. package/dist/esm/fork/validatePathConfig.js.map +1 -1
  156. package/dist/esm/fork/validatePathConfig.mjs +32 -11
  157. package/dist/esm/fork/validatePathConfig.mjs.map +1 -1
  158. package/dist/esm/fork/validatePathConfig.native.js +43 -18
  159. package/dist/esm/fork/validatePathConfig.native.js.map +2 -2
  160. package/dist/esm/layouts/withLayoutContext.js +1 -1
  161. package/dist/esm/layouts/withLayoutContext.js.map +1 -1
  162. package/dist/esm/layouts/withLayoutContext.mjs +1 -1
  163. package/dist/esm/layouts/withLayoutContext.mjs.map +1 -1
  164. package/dist/esm/layouts/withLayoutContext.native.js +1 -1
  165. package/dist/esm/layouts/withLayoutContext.native.js.map +1 -1
  166. package/dist/esm/link/linking.js +2 -2
  167. package/dist/esm/link/linking.js.map +1 -1
  168. package/dist/esm/link/linking.mjs +2 -2
  169. package/dist/esm/link/linking.mjs.map +1 -1
  170. package/dist/esm/link/linking.native.js +2 -2
  171. package/dist/esm/link/linking.native.js.map +1 -1
  172. package/dist/esm/link/useLinkTo.js +1 -1
  173. package/dist/esm/link/useLinkTo.mjs +1 -1
  174. package/dist/esm/link/useLinkTo.native.js +1 -1
  175. package/dist/esm/router/getNormalizedStatePath.js +1 -1
  176. package/dist/esm/router/getNormalizedStatePath.mjs +1 -1
  177. package/dist/esm/router/getNormalizedStatePath.native.js +1 -1
  178. package/dist/esm/router/router.js +24 -2
  179. package/dist/esm/router/router.js.map +1 -1
  180. package/dist/esm/router/router.mjs +18 -2
  181. package/dist/esm/router/router.mjs.map +1 -1
  182. package/dist/esm/router/router.native.js +38 -2
  183. package/dist/esm/router/router.native.js.map +2 -2
  184. package/package.json +8 -9
  185. package/src/Root.tsx +6 -2
  186. package/src/fork/NavigationContainer.tsx +101 -39
  187. package/src/fork/createMemoryHistory.tsx +15 -13
  188. package/src/fork/extractPathFromURL.ts +85 -40
  189. package/src/fork/findFocusedRoute.tsx +9 -1
  190. package/src/fork/getPathFromState-mods.ts +142 -0
  191. package/src/fork/getPathFromState.ts +244 -501
  192. package/src/fork/getStateFromPath-mods.ts +400 -0
  193. package/src/fork/getStateFromPath.ts +447 -538
  194. package/src/fork/useBackButton.native.tsx +16 -2
  195. package/src/fork/useBackButton.tsx +11 -2
  196. package/src/fork/useDocumentTitle.native.tsx +9 -4
  197. package/src/fork/useDocumentTitle.tsx +12 -7
  198. package/src/fork/useLinking.native.ts +71 -63
  199. package/src/fork/useLinking.ts +75 -40
  200. package/src/fork/useThenable.tsx +7 -1
  201. package/src/fork/validatePathConfig.ts +64 -12
  202. package/src/layouts/withLayoutContext.tsx +1 -1
  203. package/src/link/linking.ts +2 -2
  204. package/src/link/useLinkTo.tsx +1 -1
  205. package/src/router/getNormalizedStatePath.tsx +1 -1
  206. package/src/router/router.ts +41 -2
  207. package/types/Root.d.ts.map +1 -1
  208. package/types/fork/NavigationContainer.d.ts +19 -8
  209. package/types/fork/NavigationContainer.d.ts.map +1 -1
  210. package/types/fork/createMemoryHistory.d.ts +10 -1
  211. package/types/fork/createMemoryHistory.d.ts.map +1 -1
  212. package/types/fork/extractPathFromURL.d.ts +7 -1
  213. package/types/fork/extractPathFromURL.d.ts.map +1 -1
  214. package/types/fork/findFocusedRoute.d.ts +9 -0
  215. package/types/fork/findFocusedRoute.d.ts.map +1 -1
  216. package/types/fork/getPathFromState-mods.d.ts +23 -0
  217. package/types/fork/getPathFromState-mods.d.ts.map +1 -0
  218. package/types/fork/getPathFromState.d.ts +15 -14
  219. package/types/fork/getPathFromState.d.ts.map +1 -1
  220. package/types/fork/getStateFromPath-mods.d.ts +58 -0
  221. package/types/fork/getStateFromPath-mods.d.ts.map +1 -0
  222. package/types/fork/getStateFromPath.d.ts +28 -29
  223. package/types/fork/getStateFromPath.d.ts.map +1 -1
  224. package/types/fork/useBackButton.d.ts +6 -0
  225. package/types/fork/useBackButton.d.ts.map +1 -1
  226. package/types/fork/useBackButton.native.d.ts +9 -1
  227. package/types/fork/useBackButton.native.d.ts.map +1 -1
  228. package/types/fork/useDocumentTitle.d.ts +8 -6
  229. package/types/fork/useDocumentTitle.d.ts.map +1 -1
  230. package/types/fork/useDocumentTitle.native.d.ts +5 -2
  231. package/types/fork/useDocumentTitle.native.d.ts.map +1 -1
  232. package/types/fork/useLinking.d.ts +8 -1
  233. package/types/fork/useLinking.d.ts.map +1 -1
  234. package/types/fork/useLinking.native.d.ts +9 -2
  235. package/types/fork/useLinking.native.d.ts.map +1 -1
  236. package/types/fork/useThenable.d.ts +6 -0
  237. package/types/fork/useThenable.d.ts.map +1 -1
  238. package/types/fork/validatePathConfig.d.ts +8 -1
  239. package/types/fork/validatePathConfig.d.ts.map +1 -1
  240. package/types/link/linking.d.ts +2 -2
  241. package/types/link/linking.d.ts.map +1 -1
@@ -1,40 +1,63 @@
1
- // Forked from React Navigation
1
+ /**
2
+ * This file is copied from the react-navigation repo:
3
+ * https://github.com/react-navigation/react-navigation/blob/%40react-navigation/core%407.1.2/packages/core/src/getPathFromState.tsx
4
+ *
5
+ * Please refrain from making changes to this file, as it will make merging updates from the upstream harder.
6
+ * All modifications except formatting should be marked with `// @modified` comment.
7
+ */
2
8
 
3
9
  import {
4
10
  BaseNavigationContainer,
5
- DefaultTheme,
6
- type DocumentTitleOptions,
7
- LinkingContext,
8
- type LinkingOptions,
9
- LocaleDirContext,
10
- type LocaleDirection,
11
+ getActionFromState,
12
+ getPathFromState,
13
+ getStateFromPath,
11
14
  type NavigationContainerProps,
12
15
  type NavigationContainerRef,
16
+ type NavigationState,
13
17
  type ParamListBase,
14
- type Theme,
15
18
  ThemeProvider,
16
- getActionFromState,
17
- getPathFromState,
18
- getStateFromPath,
19
19
  validatePathConfig,
20
- } from '@react-navigation/native'
20
+ } from '@react-navigation/core'
21
21
  import * as React from 'react'
22
-
23
- import useLinking from './useLinking'
24
22
  import { I18nManager } from 'react-native'
23
+ import useLatestCallback from 'use-latest-callback'
24
+
25
+ // @modified - start
26
+ // import { LinkingContext } from './LinkingContext'
27
+ // import { LocaleDirContext } from './LocaleDirContext'
28
+ // import { DefaultTheme } from './theming/DefaultTheme'
29
+ // import type { DocumentTitleOptions, LinkingOptions, LocaleDirection } from './types'
30
+ // import { UnhandledLinkingContext } from './UnhandledLinkingContext'
31
+ import {
32
+ LinkingContext,
33
+ LocaleDirContext,
34
+ DefaultTheme,
35
+ type DocumentTitleOptions,
36
+ type LinkingOptions,
37
+ type LocaleDirection,
38
+ UNSTABLE_UnhandledLinkingContext as UnhandledLinkingContext,
39
+ } from '@react-navigation/native'
40
+ // @modified - end
25
41
  import { useBackButton } from './useBackButton'
26
42
  import { useDocumentTitle } from './useDocumentTitle'
43
+ import { useLinking } from './useLinking'
27
44
  import { useThenable } from './useThenable'
28
45
 
46
+ declare global {
47
+ // eslint-disable-next-line no-var
48
+ var REACT_NAVIGATION_DEVTOOLS: WeakMap<
49
+ NavigationContainerRef<any>,
50
+ { readonly linking: LinkingOptions<any> }
51
+ >
52
+ }
53
+
29
54
  globalThis.REACT_NAVIGATION_DEVTOOLS = new WeakMap()
30
55
 
31
- type Props<ParamList extends object> = NavigationContainerProps & {
56
+ type Props<ParamList extends {}> = NavigationContainerProps & {
32
57
  direction?: LocaleDirection
33
- documentTitle?: DocumentTitleOptions
34
- fallback?: React.ReactNode
35
58
  linking?: LinkingOptions<ParamList>
36
- onReady?: () => void
37
- theme?: Theme
59
+ fallback?: React.ReactNode
60
+ documentTitle?: DocumentTitleOptions
38
61
  }
39
62
 
40
63
  /**
@@ -44,7 +67,9 @@ type Props<ParamList extends object> = NavigationContainerProps & {
44
67
  * @param props.initialState Initial state object for the navigation tree. When deep link handling is enabled, this will override deep links when specified. Make sure that you don't specify an `initialState` when there's a deep link (`Linking.getInitialURL()`).
45
68
  * @param props.onReady Callback which is called after the navigation tree mounts.
46
69
  * @param props.onStateChange Callback which is called with the latest navigation state when it changes.
47
- * @param props.theme Theme object for the navigators.
70
+ * @param props.onUnhandledAction Callback which is called when an action is not handled.
71
+ * @param props.direction Text direction of the components. Defaults to `'ltr'`.
72
+ * @param props.theme Theme object for the UI elements.
48
73
  * @param props.linking Options for deep linking. Deep link handling is enabled when this prop is provided, unless `linking.enabled` is `false`.
49
74
  * @param props.fallback Fallback component to render until we have finished getting initial state when linking is enabled. Defaults to `null`.
50
75
  * @param props.documentTitle Options to configure the document title on Web. Updating document title is handled by default unless `documentTitle.enabled` is `false`.
@@ -59,6 +84,7 @@ function NavigationContainerInner(
59
84
  fallback = null,
60
85
  documentTitle,
61
86
  onReady,
87
+ onStateChange,
62
88
  ...rest
63
89
  }: Props<ParamListBase>,
64
90
  ref?: React.Ref<NavigationContainerRef<ParamListBase> | null>
@@ -74,12 +100,50 @@ function NavigationContainerInner(
74
100
  useBackButton(refContainer)
75
101
  useDocumentTitle(refContainer, documentTitle)
76
102
 
77
- const { getInitialState } = useLinking(refContainer, {
78
- enabled: isLinkingEnabled,
79
- prefixes: [],
80
- ...linking,
103
+ const [lastUnhandledLink, setLastUnhandledLink] = React.useState<string | undefined>()
104
+
105
+ const { getInitialState } = useLinking(
106
+ refContainer,
107
+ {
108
+ enabled: isLinkingEnabled,
109
+ prefixes: [],
110
+ ...linking,
111
+ },
112
+ setLastUnhandledLink
113
+ )
114
+
115
+ const linkingContext = React.useMemo(() => ({ options: linking }), [linking])
116
+
117
+ const unhandledLinkingContext = React.useMemo(
118
+ () => ({ lastUnhandledLink, setLastUnhandledLink }),
119
+ [lastUnhandledLink, setLastUnhandledLink]
120
+ )
121
+
122
+ const onReadyForLinkingHandling = useLatestCallback(() => {
123
+ // If the screen path matches lastUnhandledLink, we do not track it
124
+ const path = refContainer.current?.getCurrentRoute()?.path
125
+ setLastUnhandledLink((previousLastUnhandledLink) => {
126
+ if (previousLastUnhandledLink === path) {
127
+ return undefined
128
+ }
129
+ return previousLastUnhandledLink
130
+ })
131
+ onReady?.()
81
132
  })
82
133
 
134
+ const onStateChangeForLinkingHandling = useLatestCallback(
135
+ (state: Readonly<NavigationState> | undefined) => {
136
+ // If the screen path matches lastUnhandledLink, we do not track it
137
+ const path = refContainer.current?.getCurrentRoute()?.path
138
+ setLastUnhandledLink((previousLastUnhandledLink) => {
139
+ if (previousLastUnhandledLink === path) {
140
+ return undefined
141
+ }
142
+ return previousLastUnhandledLink
143
+ })
144
+ onStateChange?.(state)
145
+ }
146
+ )
83
147
  // Add additional linking related info to the ref
84
148
  // This will be used by the devtools
85
149
  React.useEffect(() => {
@@ -103,38 +167,36 @@ function NavigationContainerInner(
103
167
 
104
168
  React.useImperativeHandle(ref, () => refContainer.current)
105
169
 
106
- const linkingContext = React.useMemo(() => ({ options: linking }), [linking])
170
+ const isLinkingReady = rest.initialState != null || !isLinkingEnabled || isResolved
107
171
 
108
- React.useEffect(() => {
109
- onReady?.()
110
- }, [onReady])
111
-
112
- if (!isResolved) {
172
+ if (!isLinkingReady) {
173
+ // This is temporary until we have Suspense for data-fetching
174
+ // Then the fallback will be handled by a parent `Suspense` component
113
175
  return <ThemeProvider value={theme}>{fallback}</ThemeProvider>
114
176
  }
115
177
 
116
178
  return (
117
179
  <LocaleDirContext.Provider value={direction}>
118
- <LinkingContext.Provider value={linkingContext}>
119
- <ThemeProvider value={theme}>
180
+ <UnhandledLinkingContext.Provider value={unhandledLinkingContext}>
181
+ <LinkingContext.Provider value={linkingContext}>
120
182
  <BaseNavigationContainer
121
183
  {...rest}
122
184
  theme={theme}
185
+ onReady={onReadyForLinkingHandling}
186
+ onStateChange={onStateChangeForLinkingHandling}
187
+ initialState={rest.initialState == null ? initialState : rest.initialState}
123
188
  ref={refContainer}
124
- initialState={initialState ?? rest.initialState}
125
189
  />
126
- </ThemeProvider>
127
- </LinkingContext.Provider>
190
+ </LinkingContext.Provider>
191
+ </UnhandledLinkingContext.Provider>
128
192
  </LocaleDirContext.Provider>
129
193
  )
130
194
  }
131
195
 
132
- const NavigationContainer = React.forwardRef(NavigationContainerInner) as <
133
- RootParamList extends object = ReactNavigation.RootParamList,
196
+ export const NavigationContainer = React.forwardRef(NavigationContainerInner) as <
197
+ RootParamList extends {} = ReactNavigation.RootParamList
134
198
  >(
135
199
  props: Props<RootParamList> & {
136
200
  ref?: React.Ref<NavigationContainerRef<RootParamList>>
137
201
  }
138
202
  ) => React.ReactElement
139
-
140
- export default NavigationContainer
@@ -1,10 +1,16 @@
1
+ /**
2
+ * This file is copied from the react-navigation repo:
3
+ * https://github.com/react-navigation/react-navigation/blob/%40react-navigation/core%407.1.2/packages/native/src/createMemoryHistory.tsx
4
+ *
5
+ * Please refrain from making changes to this file, as it will make merging updates from the upstream harder.
6
+ * All modifications except formatting should be marked with `// @modified` comment.
7
+ *
8
+ * No modifications currently, copied only in order to use a custom `useLinking` function.
9
+ */
10
+
1
11
  import type { NavigationState } from '@react-navigation/core'
2
12
  import { nanoid } from 'nanoid/non-secure'
3
13
 
4
- // forked from @react-navigation/native/src/createMemoryHistory.tsx
5
- // NOTE there was a change we made for search params, but we've fixed it upstream
6
- // we can revert this back to the react-navigation one if we want
7
-
8
14
  type HistoryRecord = {
9
15
  // Unique identifier for this record to match it with window.history.state
10
16
  id: string
@@ -14,7 +20,7 @@ type HistoryRecord = {
14
20
  path: string
15
21
  }
16
22
 
17
- export default function createMemoryHistory() {
23
+ export function createMemoryHistory() {
18
24
  let index = 0
19
25
  let items: HistoryRecord[] = []
20
26
 
@@ -91,12 +97,7 @@ export default function createMemoryHistory() {
91
97
  // Need to keep the hash part of the path if there was no previous history entry
92
98
  // or the previous history entry had the same path
93
99
  let pathWithHash = path
94
-
95
- // NOTE: this was the wrong fix
96
- // if (window.location.search) {
97
- // console.log('replacing!')
98
- // pathWithHash = pathWithHash + window.location.search
99
- // }
100
+ const hash = pathWithHash.includes('#') ? '' : location.hash
100
101
 
101
102
  if (!items.length || items.findIndex((item) => item.id === id) < 0) {
102
103
  // There are two scenarios for creating an array with only one history record:
@@ -105,12 +106,13 @@ export default function createMemoryHistory() {
105
106
  // the page when navigating forward in history.
106
107
  // - This is the first time any state modifications are done
107
108
  // So we need to push the entry as there's nothing to replace
108
- pathWithHash = pathWithHash + location.hash
109
+
110
+ pathWithHash = pathWithHash + hash
109
111
  items = [{ path: pathWithHash, state, id }]
110
112
  index = 0
111
113
  } else {
112
114
  if (items[index].path === path) {
113
- pathWithHash = pathWithHash + location.hash
115
+ pathWithHash = pathWithHash + hash
114
116
  }
115
117
  items[index] = { path, state, id }
116
118
  }
@@ -1,4 +1,23 @@
1
- import URL from 'url-parse'
1
+ export function parsePathAndParamsFromExpoGoLink(url: string): {
2
+ pathname: string
3
+ queryString: string
4
+ } {
5
+ // If the URL is defined (default in Expo Go dev apps) and the URL has no path:
6
+ // `exp://192.168.87.39:19000/` then use the default `exp://192.168.87.39:19000/--/`
7
+
8
+ const href = parsePathFromExpoGoLink(url)
9
+ const results = href.match(/([^?]*)(\?.*)?/)
10
+ return {
11
+ pathname: results?.[1] ?? '',
12
+ queryString: results?.[2] ?? '',
13
+ }
14
+ }
15
+
16
+ export function parsePathFromExpoGoLink(url: string): string {
17
+ // If the URL is defined (default in Expo Go dev apps) and the URL has no path:
18
+ // `exp://192.168.87.39:19000/` then use the default `exp://192.168.87.39:19000/--/`
19
+ return url.match(/exps?:\/\/.*?\/--\/(.*)/)?.[1] ?? ''
20
+ }
2
21
 
3
22
  // This is only run on native.
4
23
  function extractExactPathFromURL(url: string): string {
@@ -7,33 +26,38 @@ function extractExactPathFromURL(url: string): string {
7
26
  // from the URL, while stripping the origin.
8
27
  url.match(/^https?:\/\//)
9
28
  ) {
10
- const { origin, href } = new URL(url)
29
+ const { origin, href, hostname } = new URL(url)
30
+
31
+ if (hostname === 'exp.host' || hostname === 'u.expo.dev') {
32
+ // These are QR code generate deep-link that always like to the '/' path
33
+ // TODO: In the future, QR code may link to a specific path and this logic will need to be udpated
34
+ return ''
35
+ }
36
+
11
37
  return href.replace(origin, '')
12
38
  }
13
39
 
40
+ const isExpoGo = typeof expo !== 'undefined' && globalThis.expo?.modules?.ExpoGo
41
+
14
42
  // Handle special URLs used in Expo Go: `/--/pathname` -> `pathname`
15
- // if (
16
- // Constants.executionEnvironment === ExecutionEnvironment.StoreClient &&
17
- // // while not exhaustive, `exp` and `exps` are the only two schemes which
18
- // // are passed through to other apps in Expo Go.
19
- // url.match(/^exp(s)?:\/\//)
20
- // ) {
21
- // const pathname = url.match(/exps?:\/\/.*?\/--\/(.*)/)?.[1]
22
- // if (pathname) {
23
- // return fromDeepLink('a://' + pathname)
24
- // }
25
-
26
- // const res = Linking.parse(url)
27
-
28
- // const qs = !res.queryParams
29
- // ? ''
30
- // : Object.entries(res.queryParams)
31
- // .map(([k, v]) => `${k}=${v}`)
32
- // .join('&')
33
- // return (
34
- // adjustPathname({ hostname: res.hostname, pathname: res.path || '' }) + (qs ? '?' + qs : '')
35
- // )
36
- // }
43
+ if (
44
+ isExpoGo &&
45
+ // while not exhaustive, `exp` and `exps` are the only two schemes which
46
+ // are passed through to other apps in Expo Go.
47
+ url.match(/^exp(s)?:\/\//)
48
+ ) {
49
+ const pathname = parsePathFromExpoGoLink(url)
50
+ if (pathname) {
51
+ return fromDeepLink('a://' + pathname)
52
+ }
53
+ // Match the `?.*` segment of the URL.
54
+ const queryParams = url.match(/exps?:\/\/.*\?(.*)/)?.[1]
55
+ if (queryParams) {
56
+ return fromDeepLink('a://?' + queryParams)
57
+ }
58
+
59
+ return ''
60
+ }
37
61
 
38
62
  // TODO: Support dev client URLs
39
63
 
@@ -41,29 +65,38 @@ function extractExactPathFromURL(url: string): string {
41
65
  }
42
66
 
43
67
  /** Major hack to support the makeshift expo-development-client system. */
44
- function isExpoDevelopmentClient(url: URL<Record<string, string | undefined>>): boolean {
45
- return !!url.hostname.match(/^expo-development-client$/)
68
+ function isExpoDevelopmentClient(url: URL): boolean {
69
+ return url.hostname === 'expo-development-client'
46
70
  }
47
71
 
48
72
  function fromDeepLink(url: string): string {
49
- // This is for all standard deep links, e.g. `foobar://` where everything
50
- // after the `://` is the path.
51
- const res = new URL(url, true)
73
+ let res: URL | null
74
+ try {
75
+ // This is for all standard deep links, e.g. `foobar://` where everything
76
+ // after the `://` is the path.
77
+ res = new URL(url)
78
+ } catch {
79
+ /**
80
+ * We failed to parse the URL. This can occur for a variety of reasons, including:
81
+ * - Its a partial URL (e.g. `/route?query=param`).
82
+ * - It has a valid App scheme, but the scheme isn't a valid URL scheme (e.g. `my_app://`)
83
+ */
84
+
85
+ /**
86
+ * App schemes are not valid URL schemes, so they will fail to parse.
87
+ * We need to strip the scheme from these URLs
88
+ */
89
+ return url.replace(/^[^:]+:\/\//, '')
90
+ }
52
91
 
53
92
  if (isExpoDevelopmentClient(res)) {
54
- if (!res.query || !res.query.url) {
93
+ if (!res.searchParams.get('url')) {
55
94
  return ''
56
95
  }
57
- const incomingUrl = res.query.url
96
+ const incomingUrl = res.searchParams.get('url')!
58
97
  return extractExactPathFromURL(decodeURI(incomingUrl))
59
98
  }
60
99
 
61
- const qs = !res.query
62
- ? ''
63
- : Object.entries(res.query as Record<string, string>)
64
- .map(([k, v]) => `${k}=${decodeURIComponent(v)}`)
65
- .join('&')
66
-
67
100
  let results = ''
68
101
 
69
102
  if (res.host) {
@@ -74,6 +107,13 @@ function fromDeepLink(url: string): string {
74
107
  results += res.pathname
75
108
  }
76
109
 
110
+ const qs = !res.search
111
+ ? ''
112
+ : // @ts-ignore: `entries` is not on `URLSearchParams` in some typechecks.
113
+ [...res.searchParams.entries()]
114
+ .map(([k, v]) => `${k}=${decodeURIComponent(v)}`)
115
+ .join('&')
116
+
77
117
  if (qs) {
78
118
  results += '?' + qs
79
119
  }
@@ -81,9 +121,12 @@ function fromDeepLink(url: string): string {
81
121
  return results
82
122
  }
83
123
 
84
- export function extractExpoPathFromURL(url = '') {
85
- // TODO: We should get rid of this, dropping specificities is not good
86
- return extractExactPathFromURL(url).replace(/^\//, '')
124
+ export function extractExpoPathFromURL(_prefixes: string[], url = '') {
125
+ return (
126
+ extractExactPathFromURL(url)
127
+ // TODO: We should get rid of this, dropping specificities is not good
128
+ .replace(/^\//, '')
129
+ )
87
130
  }
88
131
 
89
132
  export function adjustPathname(url: { hostname?: string | null; pathname: string }) {
@@ -93,3 +136,5 @@ export function adjustPathname(url: { hostname?: string | null; pathname: string
93
136
  }
94
137
  return url.pathname
95
138
  }
139
+
140
+ export const extractPathFromURL = extractExpoPathFromURL
@@ -1,4 +1,12 @@
1
- // Forked so we can access without importing any React Native code in Node.js environments.
1
+ /**
2
+ * This file is copied from the react-navigation repo:
3
+ * https://github.com/react-navigation/react-navigation/blob/%40react-navigation/core%407.1.2/packages/core/src/findFocusedRoute.tsx
4
+ *
5
+ * Please refrain from making changes to this file, as it will make merging updates from the upstream harder.
6
+ * All modifications except formatting should be marked with `// @modified` comment.
7
+ *
8
+ * No modifications currently, copied so we can access without importing any React Native code in Node.js environments.
9
+ */
2
10
 
3
11
  import type { InitialState } from '@react-navigation/routers'
4
12
 
@@ -0,0 +1,142 @@
1
+ /**
2
+ * This file exports things that will be used to modify the forked code in `getPathFromState.ts`.
3
+ *
4
+ * The purpose of keeping things in this separated file is to keep changes to the copied code as little as possible, making merging upstream updates easier.
5
+ */
6
+
7
+ import type { Route } from '@react-navigation/core'
8
+
9
+ import { matchDeepDynamicRouteName, matchDynamicName, matchGroupName } from '../router/matchers'
10
+
11
+ export type AdditionalOptions = {
12
+ preserveDynamicRoutes?: boolean
13
+ preserveGroups?: boolean
14
+ shouldEncodeURISegment?: boolean
15
+ }
16
+
17
+ export type ConfigItemMods = {
18
+ // Used as fallback for groups
19
+ initialRouteName?: string
20
+ }
21
+
22
+ export function getPathWithConventionsCollapsed({
23
+ pattern,
24
+ route,
25
+ params,
26
+ preserveGroups,
27
+ preserveDynamicRoutes,
28
+ shouldEncodeURISegment = true,
29
+ initialRouteName,
30
+ }: AdditionalOptions & {
31
+ pattern: string
32
+ route: Route<any>
33
+ params: Record<string, any>
34
+ initialRouteName?: string
35
+ }) {
36
+ const segments = pattern.split('/');
37
+
38
+ return segments
39
+ .map((p, i) => {
40
+ const name = getParamName(p)
41
+
42
+ // Showing the route name seems ok, though whatever we show here will be incorrect
43
+ // Since the page doesn't actually exist
44
+ if (p.startsWith('*')) {
45
+ if (preserveDynamicRoutes) {
46
+ if (name === 'not-found') {
47
+ return '+not-found'
48
+ }
49
+
50
+ return `[...${name}]`
51
+ }
52
+
53
+ if (params[name]) {
54
+ if (Array.isArray(params[name])) {
55
+ return params[name].join('/')
56
+ }
57
+ return params[name]
58
+ }
59
+
60
+ if (route.name.startsWith('[') && route.name.endsWith(']')) {
61
+ return ''
62
+ }
63
+
64
+ if (p === '*not-found') {
65
+ return ''
66
+ }
67
+
68
+ return route.name
69
+ }
70
+
71
+ // If the path has a pattern for a param, put the param in the path
72
+ if (p.startsWith(':')) {
73
+ if (preserveDynamicRoutes) {
74
+ return `[${name}]`
75
+ }
76
+ // Optional params without value assigned in route.params should be ignored
77
+ const value = params[name]
78
+ if (value === undefined && p.endsWith('?')) {
79
+ return
80
+ }
81
+
82
+ return (shouldEncodeURISegment ? encodeURISegment(value) : value) ?? 'undefined'
83
+ }
84
+
85
+ if (!preserveGroups && matchGroupName(p) != null) {
86
+ // When the last part is a group it could be a shared URL
87
+ // if the route has an initialRouteName defined, then we should
88
+ // use that as the component path as we can assume it will be shown.
89
+ if (segments.length - 1 === i) {
90
+ if (initialRouteName) {
91
+ // Return an empty string if the init route is ambiguous.
92
+ if (segmentMatchesConvention(initialRouteName)) {
93
+ return ''
94
+ }
95
+ return shouldEncodeURISegment
96
+ ? encodeURISegment(initialRouteName, { preserveBrackets: true })
97
+ : initialRouteName
98
+ }
99
+ }
100
+ return ''
101
+ }
102
+ // Preserve dynamic syntax for rehydration
103
+ return shouldEncodeURISegment ? encodeURISegment(p, { preserveBrackets: true }) : p
104
+ })
105
+ .map((v) => v ?? '')
106
+ .join('/')
107
+ }
108
+
109
+ export const getParamName = (pattern: string) => pattern.replace(/^[:*]/, '').replace(/\?$/, '')
110
+
111
+ export function appendBaseUrl(
112
+ path: string,
113
+ baseUrl: string | undefined = process.env.EXPO_BASE_URL
114
+ ) {
115
+ if (process.env.NODE_ENV !== 'development') {
116
+ if (baseUrl) {
117
+ return `/${baseUrl.replace(/^\/+/, '').replace(/\/$/, '')}${path}`
118
+ }
119
+ }
120
+ return path
121
+ }
122
+
123
+ function segmentMatchesConvention(segment: string): boolean {
124
+ return (
125
+ segment === 'index' ||
126
+ matchDynamicName(segment) != null ||
127
+ matchGroupName(segment) != null ||
128
+ matchDeepDynamicRouteName(segment) != null
129
+ )
130
+ }
131
+
132
+ function encodeURISegment(str: string, { preserveBrackets = false } = {}) {
133
+ // Valid characters according to
134
+ // https://datatracker.ietf.org/doc/html/rfc3986#section-3.3 (see pchar definition)
135
+ str = String(str).replace(/[^A-Za-z0-9\-._~!$&'()*+,;=:@]/g, (char) => encodeURIComponent(char))
136
+
137
+ if (preserveBrackets) {
138
+ // Preserve brackets
139
+ str = str.replace(/%5B/g, '[').replace(/%5D/g, ']')
140
+ }
141
+ return str
142
+ }