@amazon-devices/react-navigation__native 2.0.1758683737
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.
- package/LICENSE +7 -0
- package/README.md +5 -0
- package/SystemBundles/6132afb62bda3afb78ba1a1aca51924df73e9dbcc77106aa0f97a0ef68b04ebb.bundle +15196 -0
- package/SystemBundles/6132afb62bda3afb78ba1a1aca51924df73e9dbcc77106aa0f97a0ef68b04ebb.map +1 -0
- package/SystemModules/amzn__react-navigation__native-2.modules.txt +76 -0
- package/SystemModules/amzn__react-navigation__native-2.private.modules.txt +101 -0
- package/SystemModules/keplerscript-system-bundle-config.json +7 -0
- package/THIRD_PARTY_NOTICES.txt +24 -0
- package/kepler-compatibility.json +8 -0
- package/kepler-transformed-package-info.json +3 -0
- package/lib/commonjs/Link.js +50 -0
- package/lib/commonjs/Link.js.map +1 -0
- package/lib/commonjs/LinkingContext.js +15 -0
- package/lib/commonjs/LinkingContext.js.map +1 -0
- package/lib/commonjs/NavigationContainer.js +109 -0
- package/lib/commonjs/NavigationContainer.js.map +1 -0
- package/lib/commonjs/ServerContainer.js +54 -0
- package/lib/commonjs/ServerContainer.js.map +1 -0
- package/lib/commonjs/ServerContext.js +12 -0
- package/lib/commonjs/ServerContext.js.map +1 -0
- package/lib/commonjs/createMemoryHistory.js +220 -0
- package/lib/commonjs/createMemoryHistory.js.map +1 -0
- package/lib/commonjs/extractPathFromURL.js +25 -0
- package/lib/commonjs/extractPathFromURL.js.map +1 -0
- package/lib/commonjs/index.js +129 -0
- package/lib/commonjs/index.js.map +1 -0
- package/lib/commonjs/theming/DarkTheme.js +19 -0
- package/lib/commonjs/theming/DarkTheme.js.map +1 -0
- package/lib/commonjs/theming/DefaultTheme.js +19 -0
- package/lib/commonjs/theming/DefaultTheme.js.map +1 -0
- package/lib/commonjs/theming/ThemeContext.js +15 -0
- package/lib/commonjs/theming/ThemeContext.js.map +1 -0
- package/lib/commonjs/theming/ThemeProvider.js +20 -0
- package/lib/commonjs/theming/ThemeProvider.js.map +1 -0
- package/lib/commonjs/theming/useTheme.js +16 -0
- package/lib/commonjs/theming/useTheme.js.map +1 -0
- package/lib/commonjs/types.js +6 -0
- package/lib/commonjs/types.js.map +1 -0
- package/lib/commonjs/useBackButton.js +11 -0
- package/lib/commonjs/useBackButton.js.map +1 -0
- package/lib/commonjs/useBackButton.native.js +27 -0
- package/lib/commonjs/useBackButton.native.js.map +1 -0
- package/lib/commonjs/useDocumentTitle.js +32 -0
- package/lib/commonjs/useDocumentTitle.js.map +1 -0
- package/lib/commonjs/useDocumentTitle.native.js +10 -0
- package/lib/commonjs/useDocumentTitle.native.js.map +1 -0
- package/lib/commonjs/useLinkBuilder.js +63 -0
- package/lib/commonjs/useLinkBuilder.js.map +1 -0
- package/lib/commonjs/useLinkProps.js +97 -0
- package/lib/commonjs/useLinkProps.js.map +1 -0
- package/lib/commonjs/useLinkTo.js +45 -0
- package/lib/commonjs/useLinkTo.js.map +1 -0
- package/lib/commonjs/useLinking.js +303 -0
- package/lib/commonjs/useLinking.js.map +1 -0
- package/lib/commonjs/useLinking.native.js +152 -0
- package/lib/commonjs/useLinking.native.js.map +1 -0
- package/lib/commonjs/useScrollToTop.js +95 -0
- package/lib/commonjs/useScrollToTop.js.map +1 -0
- package/lib/commonjs/useThenable.js +41 -0
- package/lib/commonjs/useThenable.js.map +1 -0
- package/lib/module/Link.js +41 -0
- package/lib/module/Link.js.map +1 -0
- package/lib/module/LinkingContext.js +7 -0
- package/lib/module/LinkingContext.js.map +1 -0
- package/lib/module/NavigationContainer.js +100 -0
- package/lib/module/NavigationContainer.js.map +1 -0
- package/lib/module/ServerContainer.js +45 -0
- package/lib/module/ServerContainer.js.map +1 -0
- package/lib/module/ServerContext.js +4 -0
- package/lib/module/ServerContext.js.map +1 -0
- package/lib/module/createMemoryHistory.js +214 -0
- package/lib/module/createMemoryHistory.js.map +1 -0
- package/lib/module/extractPathFromURL.js +18 -0
- package/lib/module/extractPathFromURL.js.map +1 -0
- package/lib/module/index.js +15 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/theming/DarkTheme.js +13 -0
- package/lib/module/theming/DarkTheme.js.map +1 -0
- package/lib/module/theming/DefaultTheme.js +13 -0
- package/lib/module/theming/DefaultTheme.js.map +1 -0
- package/lib/module/theming/ThemeContext.js +6 -0
- package/lib/module/theming/ThemeContext.js.map +1 -0
- package/lib/module/theming/ThemeProvider.js +11 -0
- package/lib/module/theming/ThemeProvider.js.map +1 -0
- package/lib/module/theming/useTheme.js +7 -0
- package/lib/module/theming/useTheme.js.map +1 -0
- package/lib/module/types.js +2 -0
- package/lib/module/types.js.map +1 -0
- package/lib/module/useBackButton.js +5 -0
- package/lib/module/useBackButton.js.map +1 -0
- package/lib/module/useBackButton.native.js +19 -0
- package/lib/module/useBackButton.native.js.map +1 -0
- package/lib/module/useDocumentTitle.js +24 -0
- package/lib/module/useDocumentTitle.js.map +1 -0
- package/lib/module/useDocumentTitle.native.js +4 -0
- package/lib/module/useDocumentTitle.native.js.map +1 -0
- package/lib/module/useLinkBuilder.js +54 -0
- package/lib/module/useLinkBuilder.js.map +1 -0
- package/lib/module/useLinkProps.js +88 -0
- package/lib/module/useLinkProps.js.map +1 -0
- package/lib/module/useLinkTo.js +36 -0
- package/lib/module/useLinkTo.js.map +1 -0
- package/lib/module/useLinking.js +292 -0
- package/lib/module/useLinking.js.map +1 -0
- package/lib/module/useLinking.native.js +143 -0
- package/lib/module/useLinking.native.js.map +1 -0
- package/lib/module/useScrollToTop.js +87 -0
- package/lib/module/useScrollToTop.js.map +1 -0
- package/lib/module/useThenable.js +33 -0
- package/lib/module/useThenable.js.map +1 -0
- package/lib/typescript/src/Link.d.ts +24 -0
- package/lib/typescript/src/Link.d.ts.map +1 -0
- package/lib/typescript/src/LinkingContext.d.ts +8 -0
- package/lib/typescript/src/LinkingContext.d.ts.map +1 -0
- package/lib/typescript/src/NavigationContainer.d.ts +26 -0
- package/lib/typescript/src/NavigationContainer.d.ts.map +1 -0
- package/lib/typescript/src/ServerContainer.d.ts +15 -0
- package/lib/typescript/src/ServerContainer.d.ts.map +1 -0
- package/lib/typescript/src/ServerContext.d.ts +10 -0
- package/lib/typescript/src/ServerContext.d.ts.map +1 -0
- package/lib/typescript/src/__mocks__/window.d.ts +19 -0
- package/lib/typescript/src/__mocks__/window.d.ts.map +1 -0
- package/lib/typescript/src/createMemoryHistory.d.ts +25 -0
- package/lib/typescript/src/createMemoryHistory.d.ts.map +1 -0
- package/lib/typescript/src/extractPathFromURL.d.ts +2 -0
- package/lib/typescript/src/extractPathFromURL.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +15 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/lib/typescript/src/theming/DarkTheme.d.ts +4 -0
- package/lib/typescript/src/theming/DarkTheme.d.ts.map +1 -0
- package/lib/typescript/src/theming/DefaultTheme.d.ts +4 -0
- package/lib/typescript/src/theming/DefaultTheme.d.ts.map +1 -0
- package/lib/typescript/src/theming/ThemeContext.d.ts +5 -0
- package/lib/typescript/src/theming/ThemeContext.d.ts.map +1 -0
- package/lib/typescript/src/theming/ThemeProvider.d.ts +9 -0
- package/lib/typescript/src/theming/ThemeProvider.d.ts.map +1 -0
- package/lib/typescript/src/theming/useTheme.d.ts +2 -0
- package/lib/typescript/src/theming/useTheme.d.ts.map +1 -0
- package/lib/typescript/src/types.d.ts +127 -0
- package/lib/typescript/src/types.d.ts.map +1 -0
- package/lib/typescript/src/useBackButton.d.ts +4 -0
- package/lib/typescript/src/useBackButton.d.ts.map +1 -0
- package/lib/typescript/src/useBackButton.native.d.ts +4 -0
- package/lib/typescript/src/useBackButton.native.d.ts.map +1 -0
- package/lib/typescript/src/useDocumentTitle.d.ts +8 -0
- package/lib/typescript/src/useDocumentTitle.d.ts.map +1 -0
- package/lib/typescript/src/useDocumentTitle.native.d.ts +2 -0
- package/lib/typescript/src/useDocumentTitle.native.d.ts.map +1 -0
- package/lib/typescript/src/useLinkBuilder.d.ts +6 -0
- package/lib/typescript/src/useLinkBuilder.d.ts.map +1 -0
- package/lib/typescript/src/useLinkProps.d.ts +21 -0
- package/lib/typescript/src/useLinkProps.d.ts.map +1 -0
- package/lib/typescript/src/useLinkTo.d.ts +9 -0
- package/lib/typescript/src/useLinkTo.d.ts.map +1 -0
- package/lib/typescript/src/useLinking.d.ts +55 -0
- package/lib/typescript/src/useLinking.d.ts.map +1 -0
- package/lib/typescript/src/useLinking.native.d.ts +51 -0
- package/lib/typescript/src/useLinking.native.d.ts.map +1 -0
- package/lib/typescript/src/useScrollToTop.d.ts +27 -0
- package/lib/typescript/src/useScrollToTop.d.ts.map +1 -0
- package/lib/typescript/src/useThenable.d.ts +2 -0
- package/lib/typescript/src/useThenable.d.ts.map +1 -0
- package/package.json +1 -0
- package/src/Link.tsx +53 -0
- package/src/LinkingContext.tsx +12 -0
- package/src/NavigationContainer.tsx +152 -0
- package/src/ServerContainer.tsx +56 -0
- package/src/ServerContext.tsx +14 -0
- package/src/__mocks__/window.tsx +77 -0
- package/src/createMemoryHistory.tsx +224 -0
- package/src/extractPathFromURL.tsx +29 -0
- package/src/index.tsx +14 -0
- package/src/theming/DarkTheme.tsx +15 -0
- package/src/theming/DefaultTheme.tsx +15 -0
- package/src/theming/ThemeContext.tsx +10 -0
- package/src/theming/ThemeProvider.tsx +15 -0
- package/src/theming/useTheme.tsx +9 -0
- package/src/types.tsx +145 -0
- package/src/useBackButton.native.tsx +33 -0
- package/src/useBackButton.tsx +11 -0
- package/src/useDocumentTitle.native.tsx +3 -0
- package/src/useDocumentTitle.tsx +41 -0
- package/src/useLinkBuilder.tsx +82 -0
- package/src/useLinkProps.tsx +126 -0
- package/src/useLinkTo.tsx +71 -0
- package/src/useLinking.native.tsx +215 -0
- package/src/useLinking.tsx +395 -0
- package/src/useScrollToTop.tsx +116 -0
- package/src/useThenable.tsx +41 -0
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
import * as React from 'react';
|
|
2
|
+
|
|
3
|
+
import type { Theme } from '../types';
|
|
4
|
+
import ThemeContext from './ThemeContext';
|
|
5
|
+
|
|
6
|
+
type Props = {
|
|
7
|
+
value: Theme;
|
|
8
|
+
children: React.ReactNode;
|
|
9
|
+
};
|
|
10
|
+
|
|
11
|
+
export default function ThemeProvider({ value, children }: Props) {
|
|
12
|
+
return (
|
|
13
|
+
<ThemeContext.Provider value={value}>{children}</ThemeContext.Provider>
|
|
14
|
+
);
|
|
15
|
+
}
|
package/src/types.tsx
ADDED
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
getActionFromState as getActionFromStateDefault,
|
|
3
|
+
getPathFromState as getPathFromStateDefault,
|
|
4
|
+
getStateFromPath as getStateFromPathDefault,
|
|
5
|
+
PathConfigMap,
|
|
6
|
+
Route,
|
|
7
|
+
} from '@amazon-devices/react-navigation__core';
|
|
8
|
+
|
|
9
|
+
export type Theme = {
|
|
10
|
+
dark: boolean;
|
|
11
|
+
colors: {
|
|
12
|
+
primary: string;
|
|
13
|
+
background: string;
|
|
14
|
+
card: string;
|
|
15
|
+
text: string;
|
|
16
|
+
border: string;
|
|
17
|
+
notification: string;
|
|
18
|
+
};
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
export type LinkingOptions<ParamList extends {}> = {
|
|
22
|
+
/**
|
|
23
|
+
* Whether deep link handling should be enabled.
|
|
24
|
+
* Defaults to true.
|
|
25
|
+
*/
|
|
26
|
+
enabled?: boolean;
|
|
27
|
+
/**
|
|
28
|
+
* The prefixes are stripped from the URL before parsing them.
|
|
29
|
+
* Usually they are the `scheme` + `host` (e.g. `myapp://chat?user=jane`)
|
|
30
|
+
*
|
|
31
|
+
* This is not supported on Web.
|
|
32
|
+
*
|
|
33
|
+
* @example
|
|
34
|
+
* ```js
|
|
35
|
+
* {
|
|
36
|
+
* prefixes: [
|
|
37
|
+
* "myapp://", // App-specific scheme
|
|
38
|
+
* "https://example.com", // Prefix for universal links
|
|
39
|
+
* "https://*.example.com" // Prefix which matches any subdomain
|
|
40
|
+
* ]
|
|
41
|
+
* }
|
|
42
|
+
* ```
|
|
43
|
+
*/
|
|
44
|
+
prefixes: string[];
|
|
45
|
+
/**
|
|
46
|
+
* Optional function which takes an incoming URL returns a boolean
|
|
47
|
+
* indicating whether React Navigation should handle it.
|
|
48
|
+
*
|
|
49
|
+
* This can be used to disable deep linking for specific URLs.
|
|
50
|
+
* e.g. URLs used for authentication, and not for deep linking to screens.
|
|
51
|
+
*
|
|
52
|
+
* This is not supported on Web.
|
|
53
|
+
*
|
|
54
|
+
* @example
|
|
55
|
+
* ```js
|
|
56
|
+
* {
|
|
57
|
+
* // Filter out URLs used by expo-auth-session
|
|
58
|
+
* filter: (url) => !url.includes('+expo-auth-session')
|
|
59
|
+
* }
|
|
60
|
+
* ```
|
|
61
|
+
*/
|
|
62
|
+
filter?: (url: string) => boolean;
|
|
63
|
+
/**
|
|
64
|
+
* Config to fine-tune how to parse the path.
|
|
65
|
+
*
|
|
66
|
+
* @example
|
|
67
|
+
* ```js
|
|
68
|
+
* {
|
|
69
|
+
* Chat: {
|
|
70
|
+
* path: 'chat/:author/:id',
|
|
71
|
+
* parse: { id: Number }
|
|
72
|
+
* }
|
|
73
|
+
* }
|
|
74
|
+
* ```
|
|
75
|
+
*/
|
|
76
|
+
config?: {
|
|
77
|
+
initialRouteName?: keyof ParamList;
|
|
78
|
+
screens: PathConfigMap<ParamList>;
|
|
79
|
+
};
|
|
80
|
+
/**
|
|
81
|
+
* Custom function to get the initial URL used for linking.
|
|
82
|
+
* Uses `Linking.getInitialURL()` by default.
|
|
83
|
+
*
|
|
84
|
+
* This is not supported on Web.
|
|
85
|
+
*
|
|
86
|
+
* @example
|
|
87
|
+
* ```js
|
|
88
|
+
* {
|
|
89
|
+
* getInitialURL () => Linking.getInitialURL(),
|
|
90
|
+
* }
|
|
91
|
+
* ```
|
|
92
|
+
*/
|
|
93
|
+
getInitialURL?: () =>
|
|
94
|
+
| string
|
|
95
|
+
| null
|
|
96
|
+
| undefined
|
|
97
|
+
| Promise<string | null | undefined>;
|
|
98
|
+
/**
|
|
99
|
+
* Custom function to get subscribe to URL updates.
|
|
100
|
+
* Uses `Linking.addEventListener('url', callback)` by default.
|
|
101
|
+
*
|
|
102
|
+
* This is not supported on Web.
|
|
103
|
+
*
|
|
104
|
+
* @example
|
|
105
|
+
* ```js
|
|
106
|
+
* {
|
|
107
|
+
* subscribe: (listener) => {
|
|
108
|
+
* const onReceiveURL = ({ url }) => listener(url);
|
|
109
|
+
*
|
|
110
|
+
* Linking.addEventListener('url', onReceiveURL);
|
|
111
|
+
*
|
|
112
|
+
* return () => Linking.removeEventListener('url', onReceiveURL);
|
|
113
|
+
* }
|
|
114
|
+
* }
|
|
115
|
+
* ```
|
|
116
|
+
*/
|
|
117
|
+
subscribe?: (
|
|
118
|
+
listener: (url: string) => void
|
|
119
|
+
) => undefined | void | (() => void);
|
|
120
|
+
/**
|
|
121
|
+
* Custom function to parse the URL to a valid navigation state (advanced).
|
|
122
|
+
*/
|
|
123
|
+
getStateFromPath?: typeof getStateFromPathDefault;
|
|
124
|
+
/**
|
|
125
|
+
* Custom function to convert the state object to a valid URL (advanced).
|
|
126
|
+
* Only applicable on Web.
|
|
127
|
+
*/
|
|
128
|
+
getPathFromState?: typeof getPathFromStateDefault;
|
|
129
|
+
/**
|
|
130
|
+
* Custom function to convert the state object to a valid action (advanced).
|
|
131
|
+
*/
|
|
132
|
+
getActionFromState?: typeof getActionFromStateDefault;
|
|
133
|
+
};
|
|
134
|
+
|
|
135
|
+
export type DocumentTitleOptions = {
|
|
136
|
+
enabled?: boolean;
|
|
137
|
+
formatter?: (
|
|
138
|
+
options: Record<string, any> | undefined,
|
|
139
|
+
route: Route<string> | undefined
|
|
140
|
+
) => string;
|
|
141
|
+
};
|
|
142
|
+
|
|
143
|
+
export type ServerContainerRef = {
|
|
144
|
+
getCurrentOptions(): Record<string, any> | undefined;
|
|
145
|
+
};
|
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
NavigationContainerRef,
|
|
3
|
+
ParamListBase,
|
|
4
|
+
} from '@amazon-devices/react-navigation__core';
|
|
5
|
+
import * as React from 'react';
|
|
6
|
+
import { BackHandler } from 'react-native';
|
|
7
|
+
|
|
8
|
+
export default function useBackButton(
|
|
9
|
+
ref: React.RefObject<NavigationContainerRef<ParamListBase>>
|
|
10
|
+
) {
|
|
11
|
+
React.useEffect(() => {
|
|
12
|
+
const subscription = BackHandler.addEventListener(
|
|
13
|
+
'hardwareBackPress',
|
|
14
|
+
() => {
|
|
15
|
+
const navigation = ref.current;
|
|
16
|
+
|
|
17
|
+
if (navigation == null) {
|
|
18
|
+
return false;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
if (navigation.canGoBack()) {
|
|
22
|
+
navigation.goBack();
|
|
23
|
+
|
|
24
|
+
return true;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
);
|
|
30
|
+
|
|
31
|
+
return () => subscription.remove();
|
|
32
|
+
}, [ref]);
|
|
33
|
+
}
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
NavigationContainerRef,
|
|
3
|
+
ParamListBase,
|
|
4
|
+
} from '@amazon-devices/react-navigation__core';
|
|
5
|
+
|
|
6
|
+
export default function useBackButton(
|
|
7
|
+
_: React.RefObject<NavigationContainerRef<ParamListBase>>
|
|
8
|
+
) {
|
|
9
|
+
// No-op
|
|
10
|
+
// BackHandler is not available on web
|
|
11
|
+
}
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
import type {
|
|
2
|
+
NavigationContainerRef,
|
|
3
|
+
ParamListBase,
|
|
4
|
+
} from '@amazon-devices/react-navigation__core';
|
|
5
|
+
import * as React from 'react';
|
|
6
|
+
|
|
7
|
+
import type { DocumentTitleOptions } from './types';
|
|
8
|
+
|
|
9
|
+
/**
|
|
10
|
+
* Set the document title for the active screen
|
|
11
|
+
*/
|
|
12
|
+
export default function useDocumentTitle(
|
|
13
|
+
ref: React.RefObject<NavigationContainerRef<ParamListBase>>,
|
|
14
|
+
{
|
|
15
|
+
enabled = true,
|
|
16
|
+
formatter = (options, route) => options?.title ?? route?.name,
|
|
17
|
+
}: DocumentTitleOptions = {}
|
|
18
|
+
) {
|
|
19
|
+
React.useEffect(() => {
|
|
20
|
+
if (!enabled) {
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
const navigation = ref.current;
|
|
25
|
+
|
|
26
|
+
if (navigation) {
|
|
27
|
+
const title = formatter(
|
|
28
|
+
navigation.getCurrentOptions(),
|
|
29
|
+
navigation.getCurrentRoute()
|
|
30
|
+
);
|
|
31
|
+
|
|
32
|
+
document.title = title;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
return navigation?.addListener('options', (e) => {
|
|
36
|
+
const title = formatter(e.data.options, navigation?.getCurrentRoute());
|
|
37
|
+
|
|
38
|
+
document.title = title;
|
|
39
|
+
});
|
|
40
|
+
});
|
|
41
|
+
}
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getPathFromState,
|
|
3
|
+
NavigationHelpers,
|
|
4
|
+
NavigationHelpersContext,
|
|
5
|
+
NavigationProp,
|
|
6
|
+
ParamListBase,
|
|
7
|
+
} from '@amazon-devices/react-navigation__core';
|
|
8
|
+
import * as React from 'react';
|
|
9
|
+
|
|
10
|
+
import LinkingContext from './LinkingContext';
|
|
11
|
+
|
|
12
|
+
type NavigationObject =
|
|
13
|
+
| NavigationHelpers<ParamListBase>
|
|
14
|
+
| NavigationProp<ParamListBase>;
|
|
15
|
+
|
|
16
|
+
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;
|
|
42
|
+
};
|
|
43
|
+
|
|
44
|
+
/**
|
|
45
|
+
* Build destination link for a navigate action.
|
|
46
|
+
* Useful for showing anchor tags on the web for buttons that perform navigation.
|
|
47
|
+
*/
|
|
48
|
+
export default function useLinkBuilder() {
|
|
49
|
+
const navigation = React.useContext(NavigationHelpersContext);
|
|
50
|
+
const linking = React.useContext(LinkingContext);
|
|
51
|
+
|
|
52
|
+
const buildLink = React.useCallback(
|
|
53
|
+
(name: string, params?: object) => {
|
|
54
|
+
const { options } = linking;
|
|
55
|
+
|
|
56
|
+
if (options?.enabled === false) {
|
|
57
|
+
return undefined;
|
|
58
|
+
}
|
|
59
|
+
|
|
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 }],
|
|
70
|
+
};
|
|
71
|
+
|
|
72
|
+
const path = options?.getPathFromState
|
|
73
|
+
? options.getPathFromState(state, options?.config)
|
|
74
|
+
: getPathFromState(state, options?.config);
|
|
75
|
+
|
|
76
|
+
return path;
|
|
77
|
+
},
|
|
78
|
+
[linking, navigation]
|
|
79
|
+
);
|
|
80
|
+
|
|
81
|
+
return buildLink;
|
|
82
|
+
}
|
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getPathFromState,
|
|
3
|
+
NavigationAction,
|
|
4
|
+
NavigationContainerRefContext,
|
|
5
|
+
NavigationHelpersContext,
|
|
6
|
+
NavigatorScreenParams,
|
|
7
|
+
ParamListBase,
|
|
8
|
+
} from '@amazon-devices/react-navigation__core';
|
|
9
|
+
import type { NavigationState, PartialState } from '@amazon-devices/react-navigation__routers';
|
|
10
|
+
import * as React from 'react';
|
|
11
|
+
import { GestureResponderEvent, Platform } from 'react-native';
|
|
12
|
+
|
|
13
|
+
import LinkingContext from './LinkingContext';
|
|
14
|
+
import useLinkTo, { To } from './useLinkTo';
|
|
15
|
+
|
|
16
|
+
type Props<ParamList extends ReactNavigation.RootParamList> = {
|
|
17
|
+
to: To<ParamList>;
|
|
18
|
+
action?: NavigationAction;
|
|
19
|
+
};
|
|
20
|
+
|
|
21
|
+
const getStateFromParams = (
|
|
22
|
+
params: NavigatorScreenParams<ParamListBase, NavigationState> | undefined
|
|
23
|
+
): PartialState<NavigationState> | NavigationState | undefined => {
|
|
24
|
+
if (params?.state) {
|
|
25
|
+
return params.state;
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
if (params?.screen) {
|
|
29
|
+
return {
|
|
30
|
+
routes: [
|
|
31
|
+
{
|
|
32
|
+
name: params.screen,
|
|
33
|
+
params: params.params,
|
|
34
|
+
// @ts-expect-error
|
|
35
|
+
state: params.screen
|
|
36
|
+
? getStateFromParams(
|
|
37
|
+
params.params as
|
|
38
|
+
| NavigatorScreenParams<ParamListBase, NavigationState>
|
|
39
|
+
| undefined
|
|
40
|
+
)
|
|
41
|
+
: undefined,
|
|
42
|
+
},
|
|
43
|
+
],
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
return undefined;
|
|
48
|
+
};
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* Hook to get props for an anchor tag so it can work with in page navigation.
|
|
52
|
+
*
|
|
53
|
+
* @param props.to Absolute path to screen (e.g. `/feeds/hot`).
|
|
54
|
+
* @param props.action Optional action to use for in-page navigation. By default, the path is parsed to an action based on linking config.
|
|
55
|
+
*/
|
|
56
|
+
export default function useLinkProps<
|
|
57
|
+
ParamList extends ReactNavigation.RootParamList
|
|
58
|
+
>({ to, action }: Props<ParamList>) {
|
|
59
|
+
const root = React.useContext(NavigationContainerRefContext);
|
|
60
|
+
const navigation = React.useContext(NavigationHelpersContext);
|
|
61
|
+
const { options } = React.useContext(LinkingContext);
|
|
62
|
+
const linkTo = useLinkTo<ParamList>();
|
|
63
|
+
|
|
64
|
+
const onPress = (
|
|
65
|
+
e?: React.MouseEvent<HTMLAnchorElement, MouseEvent> | GestureResponderEvent
|
|
66
|
+
) => {
|
|
67
|
+
let shouldHandle = false;
|
|
68
|
+
|
|
69
|
+
if (Platform.OS !== 'web' || !e) {
|
|
70
|
+
shouldHandle = e ? !e.defaultPrevented : true;
|
|
71
|
+
} else if (
|
|
72
|
+
!e.defaultPrevented && // onPress prevented default
|
|
73
|
+
// @ts-expect-error: these properties exist on web, but not in React Native
|
|
74
|
+
!(e.metaKey || e.altKey || e.ctrlKey || e.shiftKey) && // ignore clicks with modifier keys
|
|
75
|
+
// @ts-expect-error: these properties exist on web, but not in React Native
|
|
76
|
+
(e.button == null || e.button === 0) && // ignore everything but left clicks
|
|
77
|
+
// @ts-expect-error: these properties exist on web, but not in React Native
|
|
78
|
+
[undefined, null, '', 'self'].includes(e.currentTarget?.target) // let browser handle "target=_blank" etc.
|
|
79
|
+
) {
|
|
80
|
+
e.preventDefault();
|
|
81
|
+
shouldHandle = true;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
if (shouldHandle) {
|
|
85
|
+
if (action) {
|
|
86
|
+
if (navigation) {
|
|
87
|
+
navigation.dispatch(action);
|
|
88
|
+
} else if (root) {
|
|
89
|
+
root.dispatch(action);
|
|
90
|
+
} else {
|
|
91
|
+
throw new Error(
|
|
92
|
+
"Couldn't find a navigation object. Is your component inside NavigationContainer?"
|
|
93
|
+
);
|
|
94
|
+
}
|
|
95
|
+
} else {
|
|
96
|
+
linkTo(to);
|
|
97
|
+
}
|
|
98
|
+
}
|
|
99
|
+
};
|
|
100
|
+
|
|
101
|
+
const getPathFromStateHelper = options?.getPathFromState ?? getPathFromState;
|
|
102
|
+
|
|
103
|
+
const href =
|
|
104
|
+
typeof to === 'string'
|
|
105
|
+
? to
|
|
106
|
+
: getPathFromStateHelper(
|
|
107
|
+
{
|
|
108
|
+
routes: [
|
|
109
|
+
{
|
|
110
|
+
name: to.screen,
|
|
111
|
+
// @ts-expect-error
|
|
112
|
+
params: to.params,
|
|
113
|
+
// @ts-expect-error
|
|
114
|
+
state: getStateFromParams(to.params),
|
|
115
|
+
},
|
|
116
|
+
],
|
|
117
|
+
},
|
|
118
|
+
options?.config
|
|
119
|
+
);
|
|
120
|
+
|
|
121
|
+
return {
|
|
122
|
+
href,
|
|
123
|
+
accessibilityRole: 'link' as const,
|
|
124
|
+
onPress,
|
|
125
|
+
};
|
|
126
|
+
}
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
import {
|
|
2
|
+
getActionFromState,
|
|
3
|
+
getStateFromPath,
|
|
4
|
+
NavigationContainerRefContext,
|
|
5
|
+
} from '@amazon-devices/react-navigation__core';
|
|
6
|
+
import * as React from 'react';
|
|
7
|
+
|
|
8
|
+
import LinkingContext from './LinkingContext';
|
|
9
|
+
|
|
10
|
+
export type To<
|
|
11
|
+
ParamList extends ReactNavigation.RootParamList = ReactNavigation.RootParamList,
|
|
12
|
+
RouteName extends keyof ParamList = keyof ParamList
|
|
13
|
+
> =
|
|
14
|
+
| string
|
|
15
|
+
| (undefined extends ParamList[RouteName]
|
|
16
|
+
? {
|
|
17
|
+
screen: Extract<RouteName, string>;
|
|
18
|
+
params?: ParamList[RouteName];
|
|
19
|
+
}
|
|
20
|
+
: {
|
|
21
|
+
screen: Extract<RouteName, string>;
|
|
22
|
+
params: ParamList[RouteName];
|
|
23
|
+
});
|
|
24
|
+
|
|
25
|
+
export default function useLinkTo<
|
|
26
|
+
ParamList extends ReactNavigation.RootParamList
|
|
27
|
+
>() {
|
|
28
|
+
const navigation = React.useContext(NavigationContainerRefContext);
|
|
29
|
+
const linking = React.useContext(LinkingContext);
|
|
30
|
+
|
|
31
|
+
const linkTo = React.useCallback(
|
|
32
|
+
(to: To<ParamList>) => {
|
|
33
|
+
if (navigation === undefined) {
|
|
34
|
+
throw new Error(
|
|
35
|
+
"Couldn't find a navigation object. Is your component inside NavigationContainer?"
|
|
36
|
+
);
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
if (typeof to !== 'string') {
|
|
40
|
+
// @ts-expect-error: This is fine
|
|
41
|
+
navigation.navigate(to.screen, to.params);
|
|
42
|
+
return;
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
if (!to.startsWith('/')) {
|
|
46
|
+
throw new Error(`The path must start with '/' (${to}).`);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
const { options } = linking;
|
|
50
|
+
|
|
51
|
+
const state = options?.getStateFromPath
|
|
52
|
+
? options.getStateFromPath(to, options.config)
|
|
53
|
+
: getStateFromPath(to, options?.config);
|
|
54
|
+
|
|
55
|
+
if (state) {
|
|
56
|
+
const action = getActionFromState(state, options?.config);
|
|
57
|
+
|
|
58
|
+
if (action !== undefined) {
|
|
59
|
+
navigation.dispatch(action);
|
|
60
|
+
} else {
|
|
61
|
+
navigation.reset(state);
|
|
62
|
+
}
|
|
63
|
+
} else {
|
|
64
|
+
throw new Error('Failed to parse the path to a navigation state.');
|
|
65
|
+
}
|
|
66
|
+
},
|
|
67
|
+
[linking, navigation]
|
|
68
|
+
);
|
|
69
|
+
|
|
70
|
+
return linkTo;
|
|
71
|
+
}
|