@amazon-devices/react-navigation__native 7.0.9000000000 → 8.0.9000000000-rn-83

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 (232) hide show
  1. package/SystemBundles/c0d77be093c9724f49566be215c67240e6443c16760f772a745108ddaef15503.bundle +9117 -0
  2. package/SystemBundles/c0d77be093c9724f49566be215c67240e6443c16760f772a745108ddaef15503.map +3543 -0
  3. package/SystemModules/amzn__react-navigation__native-8.modules.txt +24 -0
  4. package/SystemModules/amzn__react-navigation__native-8.private.modules.txt +77 -0
  5. package/SystemModules/keplerscript-system-bundle-config.json +4 -4
  6. package/kepler-compatibility.json +2 -2
  7. package/lib/module/Link.js +31 -10
  8. package/lib/module/Link.js.map +1 -1
  9. package/lib/module/LinkingContext.js +7 -3
  10. package/lib/module/LinkingContext.js.map +1 -1
  11. package/lib/module/LocaleDirContext.js +6 -0
  12. package/lib/module/LocaleDirContext.js.map +1 -0
  13. package/lib/module/NavigationContainer.js +87 -59
  14. package/lib/module/NavigationContainer.js.map +1 -1
  15. package/lib/module/ServerContainer.js +20 -10
  16. package/lib/module/ServerContainer.js.map +1 -1
  17. package/lib/module/ServerContext.js +3 -2
  18. package/lib/module/ServerContext.js.map +1 -1
  19. package/lib/module/UnhandledLinkingContext.js +14 -0
  20. package/lib/module/UnhandledLinkingContext.js.map +1 -0
  21. package/lib/module/__stubs__/createStackNavigator.js +18 -0
  22. package/lib/module/__stubs__/createStackNavigator.js.map +1 -0
  23. package/lib/module/__stubs__/window.js +75 -0
  24. package/lib/module/__stubs__/window.js.map +1 -0
  25. package/lib/module/createMemoryHistory.js +19 -17
  26. package/lib/module/createMemoryHistory.js.map +1 -1
  27. package/lib/module/createStaticNavigation.js +54 -0
  28. package/lib/module/createStaticNavigation.js.map +1 -0
  29. package/lib/module/extractPathFromURL.js +6 -5
  30. package/lib/module/extractPathFromURL.js.map +1 -1
  31. package/lib/module/index.js +18 -13
  32. package/lib/module/index.js.map +1 -1
  33. package/lib/module/package.json +1 -0
  34. package/lib/module/theming/DarkTheme.js +6 -3
  35. package/lib/module/theming/DarkTheme.js.map +1 -1
  36. package/lib/module/theming/DefaultTheme.js +6 -3
  37. package/lib/module/theming/DefaultTheme.js.map +1 -1
  38. package/lib/module/theming/fonts.js +61 -0
  39. package/lib/module/theming/fonts.js.map +1 -0
  40. package/lib/module/types.js +2 -0
  41. package/lib/module/types.js.map +1 -1
  42. package/lib/module/useBackButton.js +3 -1
  43. package/lib/module/useBackButton.js.map +1 -1
  44. package/lib/module/useBackButton.native.js +3 -1
  45. package/lib/module/useBackButton.native.js.map +1 -1
  46. package/lib/module/useDocumentTitle.js +6 -4
  47. package/lib/module/useDocumentTitle.js.map +1 -1
  48. package/lib/module/useDocumentTitle.native.js +4 -2
  49. package/lib/module/useDocumentTitle.native.js.map +1 -1
  50. package/lib/module/useLinkBuilder.js +71 -40
  51. package/lib/module/useLinkBuilder.js.map +1 -1
  52. package/lib/module/useLinkProps.js +41 -36
  53. package/lib/module/useLinkProps.js.map +1 -1
  54. package/lib/module/useLinkTo.js +18 -28
  55. package/lib/module/useLinkTo.js.map +1 -1
  56. package/lib/module/useLinking.js +47 -19
  57. package/lib/module/useLinking.js.map +1 -1
  58. package/lib/module/useLinking.native.js +33 -28
  59. package/lib/module/useLinking.native.js.map +1 -1
  60. package/lib/module/useLocale.js +18 -0
  61. package/lib/module/useLocale.js.map +1 -0
  62. package/lib/module/useRoutePath.js +30 -0
  63. package/lib/module/useRoutePath.js.map +1 -0
  64. package/lib/module/useScrollToTop.js +11 -7
  65. package/lib/module/useScrollToTop.js.map +1 -1
  66. package/lib/module/useThenable.js +4 -1
  67. package/lib/module/useThenable.js.map +1 -1
  68. package/lib/typescript/package.json +1 -0
  69. package/lib/typescript/src/Link.d.ts +8 -10
  70. package/lib/typescript/src/Link.d.ts.map +1 -1
  71. package/lib/typescript/src/LinkingContext.d.ts +2 -3
  72. package/lib/typescript/src/LinkingContext.d.ts.map +1 -1
  73. package/lib/typescript/src/LocaleDirContext.d.ts +4 -0
  74. package/lib/typescript/src/LocaleDirContext.d.ts.map +1 -0
  75. package/lib/typescript/src/NavigationContainer.d.ts +36 -13
  76. package/lib/typescript/src/NavigationContainer.d.ts.map +1 -1
  77. package/lib/typescript/src/ServerContainer.d.ts +2 -3
  78. package/lib/typescript/src/ServerContainer.d.ts.map +1 -1
  79. package/lib/typescript/src/ServerContext.d.ts +1 -2
  80. package/lib/typescript/src/ServerContext.d.ts.map +1 -1
  81. package/lib/typescript/src/UnhandledLinkingContext.d.ts +6 -0
  82. package/lib/typescript/src/UnhandledLinkingContext.d.ts.map +1 -0
  83. package/lib/typescript/src/__stubs__/createStackNavigator.d.ts +13 -0
  84. package/lib/typescript/src/__stubs__/createStackNavigator.d.ts.map +1 -0
  85. package/lib/typescript/src/{__mocks__ → __stubs__}/window.d.ts +5 -6
  86. package/lib/typescript/src/__stubs__/window.d.ts.map +1 -0
  87. package/lib/typescript/src/createMemoryHistory.d.ts +1 -1
  88. package/lib/typescript/src/createMemoryHistory.d.ts.map +1 -1
  89. package/lib/typescript/src/createStaticNavigation.d.ts +34 -0
  90. package/lib/typescript/src/createStaticNavigation.d.ts.map +1 -0
  91. package/lib/typescript/src/extractPathFromURL.d.ts +1 -1
  92. package/lib/typescript/src/extractPathFromURL.d.ts.map +1 -1
  93. package/lib/typescript/src/index.d.ts +15 -12
  94. package/lib/typescript/src/index.d.ts.map +1 -1
  95. package/lib/typescript/src/theming/DarkTheme.d.ts +1 -2
  96. package/lib/typescript/src/theming/DarkTheme.d.ts.map +1 -1
  97. package/lib/typescript/src/theming/DefaultTheme.d.ts +1 -2
  98. package/lib/typescript/src/theming/DefaultTheme.d.ts.map +1 -1
  99. package/lib/typescript/src/theming/fonts.d.ts +53 -0
  100. package/lib/typescript/src/theming/fonts.d.ts.map +1 -0
  101. package/lib/typescript/src/types.d.ts +35 -3
  102. package/lib/typescript/src/types.d.ts.map +1 -1
  103. package/lib/typescript/src/useBackButton.d.ts +1 -2
  104. package/lib/typescript/src/useBackButton.d.ts.map +1 -1
  105. package/lib/typescript/src/useBackButton.native.d.ts +1 -1
  106. package/lib/typescript/src/useBackButton.native.d.ts.map +1 -1
  107. package/lib/typescript/src/useDocumentTitle.d.ts +1 -1
  108. package/lib/typescript/src/useDocumentTitle.d.ts.map +1 -1
  109. package/lib/typescript/src/useDocumentTitle.native.d.ts +1 -1
  110. package/lib/typescript/src/useDocumentTitle.native.d.ts.map +1 -1
  111. package/lib/typescript/src/useLinkBuilder.d.ts +97 -3
  112. package/lib/typescript/src/useLinkBuilder.d.ts.map +1 -1
  113. package/lib/typescript/src/useLinkProps.d.ts +23 -10
  114. package/lib/typescript/src/useLinkProps.d.ts.map +1 -1
  115. package/lib/typescript/src/useLinkTo.d.ts +6 -8
  116. package/lib/typescript/src/useLinkTo.d.ts.map +1 -1
  117. package/lib/typescript/src/useLinking.d.ts +5 -46
  118. package/lib/typescript/src/useLinking.d.ts.map +1 -1
  119. package/lib/typescript/src/useLinking.native.d.ts +11 -29
  120. package/lib/typescript/src/useLinking.native.d.ts.map +1 -1
  121. package/lib/typescript/src/useLocale.d.ts +7 -0
  122. package/lib/typescript/src/useLocale.d.ts.map +1 -0
  123. package/lib/typescript/src/useRoutePath.d.ts +7 -0
  124. package/lib/typescript/src/useRoutePath.d.ts.map +1 -0
  125. package/lib/typescript/src/useScrollToTop.d.ts +2 -2
  126. package/lib/typescript/src/useScrollToTop.d.ts.map +1 -1
  127. package/lib/typescript/src/useThenable.d.ts +1 -1
  128. package/lib/typescript/src/useThenable.d.ts.map +1 -1
  129. package/oss-attribution/attribution.txt +50 -0
  130. package/oss-attribution/licenseInfos.json +18 -0
  131. package/package.json +97 -1
  132. package/src/Link.tsx +36 -20
  133. package/src/LinkingContext.tsx +9 -5
  134. package/src/LocaleDirContext.tsx +7 -0
  135. package/src/NavigationContainer.tsx +128 -69
  136. package/src/ServerContainer.tsx +4 -3
  137. package/src/ServerContext.tsx +1 -3
  138. package/src/UnhandledLinkingContext.tsx +18 -0
  139. package/src/__stubs__/createStackNavigator.tsx +46 -0
  140. package/src/{__mocks__ → __stubs__}/window.tsx +8 -8
  141. package/src/createMemoryHistory.tsx +16 -11
  142. package/src/createStaticNavigation.tsx +109 -0
  143. package/src/extractPathFromURL.tsx +3 -3
  144. package/src/index.tsx +15 -12
  145. package/src/theming/DarkTheme.tsx +3 -3
  146. package/src/theming/DefaultTheme.tsx +3 -3
  147. package/src/theming/fonts.tsx +63 -0
  148. package/src/types.tsx +49 -3
  149. package/src/useBackButton.native.tsx +2 -2
  150. package/src/useBackButton.tsx +2 -2
  151. package/src/useDocumentTitle.native.tsx +2 -2
  152. package/src/useDocumentTitle.tsx +2 -2
  153. package/src/useLinkBuilder.tsx +100 -55
  154. package/src/useLinkProps.tsx +80 -50
  155. package/src/useLinkTo.tsx +13 -53
  156. package/src/useLinking.native.tsx +33 -31
  157. package/src/useLinking.tsx +70 -23
  158. package/src/useLocale.tsx +18 -0
  159. package/src/useRoutePath.tsx +34 -0
  160. package/src/useScrollToTop.tsx +16 -12
  161. package/src/useThenable.tsx +2 -1
  162. package/SystemBundles/41869b563992545ca95a9a2f729e958cbdcada7391919e8e02112d791754072a.bundle +0 -14508
  163. package/SystemBundles/41869b563992545ca95a9a2f729e958cbdcada7391919e8e02112d791754072a.map +0 -5157
  164. package/SystemModules/amzn__react-navigation__native-7.modules.txt +0 -76
  165. package/SystemModules/amzn__react-navigation__native-7.private.modules.txt +0 -100
  166. package/THIRD_PARTY_NOTICES.txt +0 -24
  167. package/lib/commonjs/Link.js +0 -50
  168. package/lib/commonjs/Link.js.map +0 -1
  169. package/lib/commonjs/LinkingContext.js +0 -15
  170. package/lib/commonjs/LinkingContext.js.map +0 -1
  171. package/lib/commonjs/NavigationContainer.js +0 -109
  172. package/lib/commonjs/NavigationContainer.js.map +0 -1
  173. package/lib/commonjs/ServerContainer.js +0 -54
  174. package/lib/commonjs/ServerContainer.js.map +0 -1
  175. package/lib/commonjs/ServerContext.js +0 -12
  176. package/lib/commonjs/ServerContext.js.map +0 -1
  177. package/lib/commonjs/createMemoryHistory.js +0 -220
  178. package/lib/commonjs/createMemoryHistory.js.map +0 -1
  179. package/lib/commonjs/extractPathFromURL.js +0 -25
  180. package/lib/commonjs/extractPathFromURL.js.map +0 -1
  181. package/lib/commonjs/index.js +0 -129
  182. package/lib/commonjs/index.js.map +0 -1
  183. package/lib/commonjs/theming/DarkTheme.js +0 -19
  184. package/lib/commonjs/theming/DarkTheme.js.map +0 -1
  185. package/lib/commonjs/theming/DefaultTheme.js +0 -19
  186. package/lib/commonjs/theming/DefaultTheme.js.map +0 -1
  187. package/lib/commonjs/theming/ThemeContext.js +0 -15
  188. package/lib/commonjs/theming/ThemeContext.js.map +0 -1
  189. package/lib/commonjs/theming/ThemeProvider.js +0 -20
  190. package/lib/commonjs/theming/ThemeProvider.js.map +0 -1
  191. package/lib/commonjs/theming/useTheme.js +0 -16
  192. package/lib/commonjs/theming/useTheme.js.map +0 -1
  193. package/lib/commonjs/types.js +0 -6
  194. package/lib/commonjs/types.js.map +0 -1
  195. package/lib/commonjs/useBackButton.js +0 -11
  196. package/lib/commonjs/useBackButton.js.map +0 -1
  197. package/lib/commonjs/useBackButton.native.js +0 -27
  198. package/lib/commonjs/useBackButton.native.js.map +0 -1
  199. package/lib/commonjs/useDocumentTitle.js +0 -32
  200. package/lib/commonjs/useDocumentTitle.js.map +0 -1
  201. package/lib/commonjs/useDocumentTitle.native.js +0 -10
  202. package/lib/commonjs/useDocumentTitle.native.js.map +0 -1
  203. package/lib/commonjs/useLinkBuilder.js +0 -63
  204. package/lib/commonjs/useLinkBuilder.js.map +0 -1
  205. package/lib/commonjs/useLinkProps.js +0 -97
  206. package/lib/commonjs/useLinkProps.js.map +0 -1
  207. package/lib/commonjs/useLinkTo.js +0 -45
  208. package/lib/commonjs/useLinkTo.js.map +0 -1
  209. package/lib/commonjs/useLinking.js +0 -303
  210. package/lib/commonjs/useLinking.js.map +0 -1
  211. package/lib/commonjs/useLinking.native.js +0 -152
  212. package/lib/commonjs/useLinking.native.js.map +0 -1
  213. package/lib/commonjs/useScrollToTop.js +0 -95
  214. package/lib/commonjs/useScrollToTop.js.map +0 -1
  215. package/lib/commonjs/useThenable.js +0 -41
  216. package/lib/commonjs/useThenable.js.map +0 -1
  217. package/lib/module/theming/ThemeContext.js +0 -6
  218. package/lib/module/theming/ThemeContext.js.map +0 -1
  219. package/lib/module/theming/ThemeProvider.js +0 -11
  220. package/lib/module/theming/ThemeProvider.js.map +0 -1
  221. package/lib/module/theming/useTheme.js +0 -7
  222. package/lib/module/theming/useTheme.js.map +0 -1
  223. package/lib/typescript/src/__mocks__/window.d.ts.map +0 -1
  224. package/lib/typescript/src/theming/ThemeContext.d.ts +0 -5
  225. package/lib/typescript/src/theming/ThemeContext.d.ts.map +0 -1
  226. package/lib/typescript/src/theming/ThemeProvider.d.ts +0 -9
  227. package/lib/typescript/src/theming/ThemeProvider.d.ts.map +0 -1
  228. package/lib/typescript/src/theming/useTheme.d.ts +0 -2
  229. package/lib/typescript/src/theming/useTheme.d.ts.map +0 -1
  230. package/src/theming/ThemeContext.tsx +0 -10
  231. package/src/theming/ThemeProvider.tsx +0 -15
  232. package/src/theming/useTheme.tsx +0 -9
@@ -1,4 +1,4 @@
1
- const location = new URL('', 'http://example.com');
1
+ let location = new URL('', 'http://example.com');
2
2
 
3
3
  let listeners: (() => void)[] = [];
4
4
  let entries = [{ state: null, href: location.href }];
@@ -12,7 +12,7 @@ const history = {
12
12
  },
13
13
 
14
14
  pushState(state: any, _: string, path: string) {
15
- Object.assign(location, new URL(path, location.origin));
15
+ location = new URL(path, location.origin);
16
16
 
17
17
  currentState = state;
18
18
  entries = entries.slice(0, index + 1);
@@ -21,7 +21,7 @@ const history = {
21
21
  },
22
22
 
23
23
  replaceState(state: any, _: string, path: string) {
24
- Object.assign(location, new URL(path, location.origin));
24
+ location = new URL(path, location.origin);
25
25
 
26
26
  currentState = state;
27
27
  entries[index] = { state, href: location.href };
@@ -35,7 +35,7 @@ const history = {
35
35
  ) {
36
36
  index += n;
37
37
  const entry = entries[index];
38
- Object.assign(location, new URL(entry.href));
38
+ location = new URL(entry.href);
39
39
  currentState = entry.state;
40
40
  listeners.forEach((cb) => cb());
41
41
  }
@@ -63,9 +63,11 @@ const removeEventListener = (type: 'popstate', listener: () => void) => {
63
63
  }
64
64
  };
65
65
 
66
- const window = {
66
+ export const window = {
67
67
  document: { title: '' },
68
- location,
68
+ get location() {
69
+ return location;
70
+ },
69
71
  history,
70
72
  addEventListener,
71
73
  removeEventListener,
@@ -73,5 +75,3 @@ const window = {
73
75
  return window;
74
76
  },
75
77
  };
76
-
77
- export default window;
@@ -10,7 +10,7 @@ type HistoryRecord = {
10
10
  path: string;
11
11
  };
12
12
 
13
- export default function createMemoryHistory() {
13
+ export function createMemoryHistory() {
14
14
  let index = 0;
15
15
  let items: HistoryRecord[] = [];
16
16
 
@@ -87,6 +87,7 @@ export default function createMemoryHistory() {
87
87
  // Need to keep the hash part of the path if there was no previous history entry
88
88
  // or the previous history entry had the same path
89
89
  let pathWithHash = path;
90
+ const hash = pathWithHash.includes('#') ? '' : location.hash;
90
91
 
91
92
  if (!items.length || items.findIndex((item) => item.id === id) < 0) {
92
93
  // There are two scenarios for creating an array with only one history record:
@@ -95,12 +96,13 @@ export default function createMemoryHistory() {
95
96
  // the page when navigating forward in history.
96
97
  // - This is the first time any state modifications are done
97
98
  // So we need to push the entry as there's nothing to replace
98
- pathWithHash = pathWithHash + location.hash;
99
+
100
+ pathWithHash = pathWithHash + hash;
99
101
  items = [{ path: pathWithHash, state, id }];
100
102
  index = 0;
101
103
  } else {
102
104
  if (items[index].path === path) {
103
- pathWithHash = pathWithHash + location.hash;
105
+ pathWithHash = pathWithHash + hash;
104
106
  }
105
107
  items[index] = { path, state, id };
106
108
  }
@@ -174,21 +176,20 @@ export default function createMemoryHistory() {
174
176
  // But on Firefox, it seems to take much longer, around 50ms from our testing
175
177
  // We're using a hacky timeout since there doesn't seem to be way to know for sure
176
178
  const timer = setTimeout(() => {
177
- const index = pending.findIndex((it) => it.ref === done);
179
+ const foundIndex = pending.findIndex((it) => it.ref === done);
178
180
 
179
- if (index > -1) {
180
- pending[index].cb();
181
- pending.splice(index, 1);
181
+ if (foundIndex > -1) {
182
+ pending[foundIndex].cb();
183
+ pending.splice(foundIndex, 1);
182
184
  }
185
+
186
+ index = this.index;
183
187
  }, 100);
184
188
 
185
189
  const onPopState = () => {
186
- const id = window.history.state?.id;
187
- const currentIndex = items.findIndex((item) => item.id === id);
188
-
189
190
  // Fix createMemoryHistory.index variable's value
190
191
  // as it may go out of sync when navigating in the browser.
191
- index = Math.max(currentIndex, 0);
192
+ index = this.index;
192
193
 
193
194
  const last = pending.pop();
194
195
 
@@ -206,6 +207,10 @@ export default function createMemoryHistory() {
206
207
  // Here we normalize it so that only external changes (e.g. user pressing back/forward) trigger the listener
207
208
  listen(listener: () => void) {
208
209
  const onPopState = () => {
210
+ // Fix createMemoryHistory.index variable's value
211
+ // as it may go out of sync when navigating in the browser.
212
+ index = this.index;
213
+
209
214
  if (pending.length) {
210
215
  // This was triggered by `history.go(n)`, we shouldn't call the listener
211
216
  return;
@@ -0,0 +1,109 @@
1
+ import {
2
+ createComponentForStaticNavigation,
3
+ createPathConfigForStaticNavigation,
4
+ type NavigationContainerRef,
5
+ type ParamListBase,
6
+ type StaticNavigation,
7
+ } from '@amazon-devices/react-navigation__core';
8
+ import * as React from 'react';
9
+
10
+ import { NavigationContainer } from './NavigationContainer';
11
+ import type { LinkingOptions } from './types';
12
+
13
+ type Props = Omit<
14
+ React.ComponentProps<typeof NavigationContainer>,
15
+ 'linking' | 'children'
16
+ > & {
17
+ /**
18
+ * Options for deep linking.
19
+ */
20
+ linking?: Omit<LinkingOptions<ParamListBase>, 'config' | 'enabled'> & {
21
+ /**
22
+ * Whether deep link handling should be enabled.
23
+ * Defaults to `true` if any `linking` options are specified, `false` otherwise.
24
+ *
25
+ * When 'auto' is specified, all leaf screens will get a autogenerated path.
26
+ * The generated path will be a kebab-case version of the screen name.
27
+ * This can be overridden for specific screens by specifying `linking` for the screen.
28
+ */
29
+ enabled?: 'auto' | true | false;
30
+ /**
31
+ * Additional configuration
32
+ */
33
+ config?: Omit<
34
+ NonNullable<LinkingOptions<ParamListBase>['config']>,
35
+ 'screens'
36
+ >;
37
+ };
38
+ };
39
+
40
+ /**
41
+ * Create a navigation component from a static navigation config.
42
+ * The returned component is a wrapper around `NavigationContainer`.
43
+ *
44
+ * @param tree Static navigation config.
45
+ * @returns Navigation component to use in your app.
46
+ */
47
+ export function createStaticNavigation(tree: StaticNavigation<any, any, any>) {
48
+ const Component = createComponentForStaticNavigation(tree, 'RootNavigator');
49
+
50
+ function Navigation(
51
+ { linking, ...rest }: Props,
52
+ ref: React.Ref<NavigationContainerRef<ParamListBase>>
53
+ ) {
54
+ const linkingConfig = React.useMemo(() => {
55
+ const screens = createPathConfigForStaticNavigation(
56
+ tree,
57
+ { initialRouteName: linking?.config?.initialRouteName },
58
+ linking?.enabled === 'auto'
59
+ );
60
+
61
+ if (!screens) return;
62
+
63
+ return {
64
+ path: linking?.config?.path,
65
+ initialRouteName: linking?.config?.initialRouteName,
66
+ screens,
67
+ };
68
+ }, [
69
+ linking?.enabled,
70
+ linking?.config?.path,
71
+ linking?.config?.initialRouteName,
72
+ ]);
73
+
74
+ const memoizedLinking = React.useMemo(() => {
75
+ if (!linking) {
76
+ return undefined;
77
+ }
78
+
79
+ const enabled =
80
+ typeof linking.enabled === 'boolean'
81
+ ? linking.enabled
82
+ : linkingConfig?.screens != null;
83
+
84
+ return {
85
+ ...linking,
86
+ enabled,
87
+ config: linkingConfig,
88
+ };
89
+ }, [linking, linkingConfig]);
90
+
91
+ if (linking?.enabled === true && linkingConfig?.screens == null) {
92
+ throw new Error(
93
+ 'Linking is enabled but no linking configuration was found for the screens.\n\n' +
94
+ 'To solve this:\n' +
95
+ "- Specify a 'linking' property for the screens you want to link to.\n" +
96
+ "- Or set 'linking.enabled' to 'auto' to generate paths automatically.\n\n" +
97
+ 'See usage guide: https://reactnavigation.org/docs/static-configuration#linking'
98
+ );
99
+ }
100
+
101
+ return (
102
+ <NavigationContainer {...rest} ref={ref} linking={memoizedLinking}>
103
+ <Component />
104
+ </NavigationContainer>
105
+ );
106
+ }
107
+
108
+ return React.forwardRef(Navigation);
109
+ }
@@ -1,6 +1,6 @@
1
1
  import escapeStringRegexp from 'escape-string-regexp';
2
2
 
3
- export default function extractPathFromURL(prefixes: string[], url: string) {
3
+ export function extractPathFromURL(prefixes: string[], url: string) {
4
4
  for (const prefix of prefixes) {
5
5
  const protocol = prefix.match(/^[^:]+:/)?.[0] ?? '';
6
6
  const host = prefix
@@ -15,10 +15,10 @@ export default function extractPathFromURL(prefixes: string[], url: string) {
15
15
  .join('\\.')}`
16
16
  );
17
17
 
18
- const [originAndPath, searchParams] = url.split('?');
18
+ const [originAndPath, ...searchParams] = url.split('?');
19
19
  const normalizedURL = originAndPath
20
20
  .replace(/\/+/g, '/')
21
- .concat(searchParams ? `?${searchParams}` : '');
21
+ .concat(searchParams.length ? `?${searchParams.join('?')}` : '');
22
22
 
23
23
  if (prefixRegex.test(normalizedURL)) {
24
24
  return normalizedURL.replace(prefixRegex, '');
package/src/index.tsx CHANGED
@@ -1,14 +1,17 @@
1
- export { default as Link } from './Link';
2
- export { default as LinkingContext } from './LinkingContext';
3
- export { default as NavigationContainer } from './NavigationContainer';
4
- export { default as ServerContainer } from './ServerContainer';
5
- export { default as DarkTheme } from './theming/DarkTheme';
6
- export { default as DefaultTheme } from './theming/DefaultTheme';
7
- export { default as ThemeProvider } from './theming/ThemeProvider';
8
- export { default as useTheme } from './theming/useTheme';
1
+ export { createStaticNavigation } from './createStaticNavigation';
2
+ export { Link } from './Link';
3
+ export { LinkingContext } from './LinkingContext';
4
+ export { LocaleDirContext } from './LocaleDirContext';
5
+ export { NavigationContainer } from './NavigationContainer';
6
+ export { ServerContainer } from './ServerContainer';
7
+ export { DarkTheme } from './theming/DarkTheme';
8
+ export { DefaultTheme } from './theming/DefaultTheme';
9
9
  export * from './types';
10
- export { default as useLinkBuilder } from './useLinkBuilder';
11
- export { default as useLinkProps } from './useLinkProps';
12
- export { default as useLinkTo } from './useLinkTo';
13
- export { default as useScrollToTop } from './useScrollToTop';
10
+ export { UnhandledLinkingContext as UNSTABLE_UnhandledLinkingContext } from './UnhandledLinkingContext';
11
+ export { useLinkBuilder } from './useLinkBuilder';
12
+ export { type LinkProps, useLinkProps } from './useLinkProps';
13
+ export { useLinkTo } from './useLinkTo';
14
+ export { useLocale } from './useLocale';
15
+ export { useRoutePath } from './useRoutePath';
16
+ export { useScrollToTop } from './useScrollToTop';
14
17
  export * from '@amazon-devices/react-navigation__core';
@@ -1,6 +1,7 @@
1
1
  import type { Theme } from '../types';
2
+ import { fonts } from './fonts';
2
3
 
3
- const DarkTheme: Theme = {
4
+ export const DarkTheme: Theme = {
4
5
  dark: true,
5
6
  colors: {
6
7
  primary: 'rgb(10, 132, 255)',
@@ -10,6 +11,5 @@ const DarkTheme: Theme = {
10
11
  border: 'rgb(39, 39, 41)',
11
12
  notification: 'rgb(255, 69, 58)',
12
13
  },
14
+ fonts,
13
15
  };
14
-
15
- export default DarkTheme;
@@ -1,6 +1,7 @@
1
1
  import type { Theme } from '../types';
2
+ import { fonts } from './fonts';
2
3
 
3
- const DefaultTheme: Theme = {
4
+ export const DefaultTheme: Theme = {
4
5
  dark: false,
5
6
  colors: {
6
7
  primary: 'rgb(0, 122, 255)',
@@ -10,6 +11,5 @@ const DefaultTheme: Theme = {
10
11
  border: 'rgb(216, 216, 216)',
11
12
  notification: 'rgb(255, 59, 48)',
12
13
  },
14
+ fonts,
13
15
  };
14
-
15
- export default DefaultTheme;
@@ -0,0 +1,63 @@
1
+ import { Platform } from 'react-native';
2
+
3
+ import type { Theme } from '../types';
4
+
5
+ const WEB_FONT_STACK =
6
+ 'system-ui, "Segoe UI", Roboto, Helvetica, Arial, sans-serif, "Apple Color Emoji", "Segoe UI Emoji", "Segoe UI Symbol"';
7
+
8
+ export const fonts = Platform.select({
9
+ web: {
10
+ regular: {
11
+ fontFamily: WEB_FONT_STACK,
12
+ fontWeight: '400',
13
+ },
14
+ medium: {
15
+ fontFamily: WEB_FONT_STACK,
16
+ fontWeight: '500',
17
+ },
18
+ bold: {
19
+ fontFamily: WEB_FONT_STACK,
20
+ fontWeight: '600',
21
+ },
22
+ heavy: {
23
+ fontFamily: WEB_FONT_STACK,
24
+ fontWeight: '700',
25
+ },
26
+ },
27
+ ios: {
28
+ regular: {
29
+ fontFamily: 'System',
30
+ fontWeight: '400',
31
+ },
32
+ medium: {
33
+ fontFamily: 'System',
34
+ fontWeight: '500',
35
+ },
36
+ bold: {
37
+ fontFamily: 'System',
38
+ fontWeight: '600',
39
+ },
40
+ heavy: {
41
+ fontFamily: 'System',
42
+ fontWeight: '700',
43
+ },
44
+ },
45
+ default: {
46
+ regular: {
47
+ fontFamily: 'sans-serif',
48
+ fontWeight: 'normal',
49
+ },
50
+ medium: {
51
+ fontFamily: 'sans-serif-medium',
52
+ fontWeight: 'normal',
53
+ },
54
+ bold: {
55
+ fontFamily: 'sans-serif',
56
+ fontWeight: '600',
57
+ },
58
+ heavy: {
59
+ fontFamily: 'sans-serif',
60
+ fontWeight: '700',
61
+ },
62
+ },
63
+ } as const satisfies Record<string, Theme['fonts']>);
package/src/types.tsx CHANGED
@@ -6,7 +6,30 @@ import type {
6
6
  Route,
7
7
  } from '@amazon-devices/react-navigation__core';
8
8
 
9
- export type Theme = {
9
+ declare global {
10
+ // eslint-disable-next-line @typescript-eslint/no-namespace
11
+ namespace ReactNavigation {
12
+ interface Theme extends NativeTheme {}
13
+ }
14
+ }
15
+
16
+ type FontStyle = {
17
+ fontFamily: string;
18
+ fontWeight:
19
+ | 'normal'
20
+ | 'bold'
21
+ | '100'
22
+ | '200'
23
+ | '300'
24
+ | '400'
25
+ | '500'
26
+ | '600'
27
+ | '700'
28
+ | '800'
29
+ | '900';
30
+ };
31
+
32
+ interface NativeTheme {
10
33
  dark: boolean;
11
34
  colors: {
12
35
  primary: string;
@@ -16,7 +39,17 @@ export type Theme = {
16
39
  border: string;
17
40
  notification: string;
18
41
  };
19
- };
42
+ fonts: {
43
+ regular: FontStyle;
44
+ medium: FontStyle;
45
+ bold: FontStyle;
46
+ heavy: FontStyle;
47
+ };
48
+ }
49
+
50
+ export type Theme = NativeTheme;
51
+
52
+ export type LocaleDirection = 'ltr' | 'rtl';
20
53
 
21
54
  export type LinkingOptions<ParamList extends {}> = {
22
55
  /**
@@ -74,8 +107,21 @@ export type LinkingOptions<ParamList extends {}> = {
74
107
  * ```
75
108
  */
76
109
  config?: {
77
- initialRouteName?: keyof ParamList;
110
+ /**
111
+ * Path string to match against for the whole navigation tree.
112
+ * It's not possible to specify params here since this doesn't belong to a screen.
113
+ * This is useful when the whole app is under a specific path.
114
+ * e.g. all of the screens are under `/admin` in `https://example.com/admin`
115
+ */
116
+ path?: string;
117
+ /**
118
+ * Path configuration for child screens.
119
+ */
78
120
  screens: PathConfigMap<ParamList>;
121
+ /**
122
+ * Name of the initial route to use for the root navigator.
123
+ */
124
+ initialRouteName?: keyof ParamList;
79
125
  };
80
126
  /**
81
127
  * Custom function to get the initial URL used for linking.
@@ -5,8 +5,8 @@ import type {
5
5
  import * as React from 'react';
6
6
  import { BackHandler } from 'react-native';
7
7
 
8
- export default function useBackButton(
9
- ref: React.RefObject<NavigationContainerRef<ParamListBase>>
8
+ export function useBackButton(
9
+ ref: React.RefObject<NavigationContainerRef<ParamListBase> | null>
10
10
  ) {
11
11
  React.useEffect(() => {
12
12
  const subscription = BackHandler.addEventListener(
@@ -3,8 +3,8 @@ import type {
3
3
  ParamListBase,
4
4
  } from '@amazon-devices/react-navigation__core';
5
5
 
6
- export default function useBackButton(
7
- _: React.RefObject<NavigationContainerRef<ParamListBase>>
6
+ export function useBackButton(
7
+ _: React.RefObject<NavigationContainerRef<ParamListBase> | null>
8
8
  ) {
9
9
  // No-op
10
10
  // BackHandler is not available on web
@@ -1,3 +1,3 @@
1
- export default function useDocumentTitle() {
2
- // Noop for React Native
1
+ export function useDocumentTitle() {
2
+ // Noop for native platforms
3
3
  }
@@ -9,8 +9,8 @@ import type { DocumentTitleOptions } from './types';
9
9
  /**
10
10
  * Set the document title for the active screen
11
11
  */
12
- export default function useDocumentTitle(
13
- ref: React.RefObject<NavigationContainerRef<ParamListBase>>,
12
+ export function useDocumentTitle(
13
+ ref: React.RefObject<NavigationContainerRef<ParamListBase> | null>,
14
14
  {
15
15
  enabled = true,
16
16
  formatter = (options, route) => options?.title ?? route?.name,
@@ -1,82 +1,127 @@
1
1
  import {
2
+ CommonActions,
3
+ findFocusedRoute,
4
+ getActionFromState,
2
5
  getPathFromState,
3
- NavigationHelpers,
6
+ getStateFromPath,
4
7
  NavigationHelpersContext,
5
- NavigationProp,
6
- ParamListBase,
8
+ NavigationRouteContext,
9
+ useStateForPath,
7
10
  } from '@amazon-devices/react-navigation__core';
8
11
  import * as React from 'react';
9
12
 
10
- import LinkingContext from './LinkingContext';
11
-
12
- type NavigationObject =
13
- | NavigationHelpers<ParamListBase>
14
- | NavigationProp<ParamListBase>;
13
+ import { LinkingContext } from './LinkingContext';
15
14
 
16
15
  type MinimalState = {
17
- index: number;
18
- routes: { name: string; params?: object; state?: MinimalState }[];
19
- };
20
-
21
- const getRootStateForNavigate = (
22
- navigation: NavigationObject,
23
- state: MinimalState
24
- ): MinimalState => {
25
- const parent = navigation.getParent();
26
-
27
- if (parent) {
28
- const parentState = parent.getState();
29
-
30
- return getRootStateForNavigate(parent, {
31
- index: 0,
32
- routes: [
33
- {
34
- ...parentState.routes[parentState.index],
35
- state: state,
36
- },
37
- ],
38
- });
39
- }
40
-
41
- return state;
16
+ routes: [{ name: string; params?: object; state?: MinimalState }];
42
17
  };
43
18
 
44
19
  /**
45
- * Build destination link for a navigate action.
46
- * Useful for showing anchor tags on the web for buttons that perform navigation.
20
+ * Helpers to build href or action based on the linking options.
21
+ *
22
+ * @returns `buildHref` to build an `href` for screen and `buildAction` to build an action from an `href`.
47
23
  */
48
- export default function useLinkBuilder() {
24
+ export function useLinkBuilder() {
49
25
  const navigation = React.useContext(NavigationHelpersContext);
50
- const linking = React.useContext(LinkingContext);
26
+ const route = React.useContext(NavigationRouteContext);
51
27
 
52
- const buildLink = React.useCallback(
53
- (name: string, params?: object) => {
54
- const { options } = linking;
28
+ const { options } = React.useContext(LinkingContext);
29
+
30
+ const focusedRouteState = useStateForPath();
55
31
 
32
+ const getPathFromStateHelper = options?.getPathFromState ?? getPathFromState;
33
+ const getStateFromPathHelper = options?.getStateFromPath ?? getStateFromPath;
34
+ const getActionFromStateHelper =
35
+ options?.getActionFromState ?? getActionFromState;
36
+
37
+ const buildHref = React.useCallback(
38
+ (name: string, params?: object) => {
56
39
  if (options?.enabled === false) {
57
40
  return undefined;
58
41
  }
59
42
 
60
- const state = navigation
61
- ? getRootStateForNavigate(navigation, {
62
- index: 0,
63
- routes: [{ name, params }],
64
- })
65
- : // If we couldn't find a navigation object in context, we're at root
66
- // So we'll construct a basic state object to use
67
- {
68
- index: 0,
69
- routes: [{ name, params }],
43
+ // Check that we're inside:
44
+ // - navigator's context
45
+ // - route context of the navigator (could be a screen, tab, etc.)
46
+ // - route matches the state for path (from the screen's context)
47
+ // This ensures that we're inside a screen
48
+ const isScreen =
49
+ navigation && route?.key && focusedRouteState
50
+ ? route.key === findFocusedRoute(focusedRouteState)?.key &&
51
+ navigation.getState().routes.some((r) => r.key === route.key)
52
+ : false;
53
+
54
+ const stateForRoute: MinimalState = {
55
+ routes: [{ name, params }],
56
+ };
57
+
58
+ const constructState = (
59
+ state: MinimalState | undefined
60
+ ): MinimalState => {
61
+ if (state) {
62
+ const route = state.routes[0];
63
+
64
+ // If we're inside a screen and at the innermost route
65
+ // We need to replace the state with the provided one
66
+ // This assumes that we're navigating to a sibling route
67
+ if (isScreen && !route.state) {
68
+ return stateForRoute;
69
+ }
70
+
71
+ // Otherwise, dive into the nested state of the route
72
+ return {
73
+ routes: [
74
+ {
75
+ ...route,
76
+ state: constructState(route.state),
77
+ },
78
+ ],
70
79
  };
80
+ }
81
+
82
+ // Once there is no more nested state, we're at the innermost route
83
+ // We can add a state based on provided parameters
84
+ // This assumes that we're navigating to a child of this route
85
+ // In this case, the helper is used in a navigator for its routes
86
+ return stateForRoute;
87
+ };
71
88
 
72
- const path = options?.getPathFromState
73
- ? options.getPathFromState(state, options?.config)
74
- : getPathFromState(state, options?.config);
89
+ const state = constructState(focusedRouteState);
90
+ const path = getPathFromStateHelper(state, options?.config);
75
91
 
76
92
  return path;
77
93
  },
78
- [linking, navigation]
94
+ [
95
+ options?.enabled,
96
+ options?.config,
97
+ route?.key,
98
+ navigation,
99
+ focusedRouteState,
100
+ getPathFromStateHelper,
101
+ ]
102
+ );
103
+
104
+ const buildAction = React.useCallback(
105
+ (href: string) => {
106
+ if (!href.startsWith('/')) {
107
+ throw new Error(`The href must start with '/' (${href}).`);
108
+ }
109
+
110
+ const state = getStateFromPathHelper(href, options?.config);
111
+
112
+ if (state) {
113
+ const action = getActionFromStateHelper(state, options?.config);
114
+
115
+ return action ?? CommonActions.reset(state);
116
+ } else {
117
+ throw new Error('Failed to parse the href to a navigation state.');
118
+ }
119
+ },
120
+ [options?.config, getStateFromPathHelper, getActionFromStateHelper]
79
121
  );
80
122
 
81
- return buildLink;
123
+ return {
124
+ buildHref,
125
+ buildAction,
126
+ };
82
127
  }