@react-navigation/core 8.0.0-alpha.24 → 8.0.0-alpha.26
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/lib/module/BaseNavigationContainer.js +5 -2
- package/lib/module/BaseNavigationContainer.js.map +1 -1
- package/lib/module/DataLoading.js +102 -0
- package/lib/module/DataLoading.js.map +1 -0
- package/lib/module/NavigationIndependentTree.js +7 -6
- package/lib/module/NavigationIndependentTree.js.map +1 -1
- package/lib/module/NavigationProvider.js +12 -12
- package/lib/module/NavigationProvider.js.map +1 -1
- package/lib/module/PreventRemoveContext.js.map +1 -1
- package/lib/module/PreventRemoveProvider.js +34 -24
- package/lib/module/PreventRemoveProvider.js.map +1 -1
- package/lib/module/StaticNavigation.js +14 -6
- package/lib/module/StaticNavigation.js.map +1 -1
- package/lib/module/StaticTreeContext.js +5 -0
- package/lib/module/StaticTreeContext.js.map +1 -0
- package/lib/module/checkSerializable.js +7 -9
- package/lib/module/checkSerializable.js.map +1 -1
- package/lib/module/createNavigationContainerRef.js +6 -8
- package/lib/module/createNavigationContainerRef.js.map +1 -1
- package/lib/module/createNavigatorFactory.js.map +1 -1
- package/lib/module/getActionFromState.js +11 -11
- package/lib/module/getActionFromState.js.map +1 -1
- package/lib/module/getPathFromState.js +38 -39
- package/lib/module/getPathFromState.js.map +1 -1
- package/lib/module/getPatternParts.js +2 -2
- package/lib/module/getPatternParts.js.map +1 -1
- package/lib/module/getStateFromPath.js +72 -45
- package/lib/module/getStateFromPath.js.map +1 -1
- package/lib/module/index.js +1 -0
- package/lib/module/index.js.map +1 -1
- package/lib/module/types.js.map +1 -1
- package/lib/module/useEventEmitter.js +1 -1
- package/lib/module/useEventEmitter.js.map +1 -1
- package/lib/module/useKeyedChildListeners.js +4 -2
- package/lib/module/useKeyedChildListeners.js.map +1 -1
- package/lib/module/useNavigation.js +2 -15
- package/lib/module/useNavigation.js.map +1 -1
- package/lib/module/useNavigationBuilder.js +4 -14
- package/lib/module/useNavigationBuilder.js.map +1 -1
- package/lib/module/useNavigationCache.js +19 -14
- package/lib/module/useNavigationCache.js.map +1 -1
- package/lib/module/useNavigationHelpers.js +27 -9
- package/lib/module/useNavigationHelpers.js.map +1 -1
- package/lib/module/useNavigationState.js +69 -36
- package/lib/module/useNavigationState.js.map +1 -1
- package/lib/module/useOnAction.js +21 -2
- package/lib/module/useOnAction.js.map +1 -1
- package/lib/module/useOptionsGetters.js +3 -1
- package/lib/module/useOptionsGetters.js.map +1 -1
- package/lib/module/usePreventRemove.js +9 -2
- package/lib/module/usePreventRemove.js.map +1 -1
- package/lib/module/useRouteCache.js +14 -7
- package/lib/module/useRouteCache.js.map +1 -1
- package/lib/module/useScheduleUpdate.js +8 -8
- package/lib/module/useScheduleUpdate.js.map +1 -1
- package/lib/module/useSyncState.js +4 -1
- package/lib/module/useSyncState.js.map +1 -1
- package/lib/module/validatePathConfig.js.map +1 -1
- package/lib/typescript/src/BaseNavigationContainer.d.ts.map +1 -1
- package/lib/typescript/src/DataLoading.d.ts +20 -0
- package/lib/typescript/src/DataLoading.d.ts.map +1 -0
- package/lib/typescript/src/NavigationProvider.d.ts +0 -1
- package/lib/typescript/src/NavigationProvider.d.ts.map +1 -1
- package/lib/typescript/src/PreventRemoveContext.d.ts +1 -0
- package/lib/typescript/src/PreventRemoveContext.d.ts.map +1 -1
- package/lib/typescript/src/PreventRemoveProvider.d.ts.map +1 -1
- package/lib/typescript/src/StaticNavigation.d.ts +65 -39
- package/lib/typescript/src/StaticNavigation.d.ts.map +1 -1
- package/lib/typescript/src/StaticTreeContext.d.ts +4 -0
- package/lib/typescript/src/StaticTreeContext.d.ts.map +1 -0
- package/lib/typescript/src/checkSerializable.d.ts +4 -2
- package/lib/typescript/src/checkSerializable.d.ts.map +1 -1
- package/lib/typescript/src/createNavigationContainerRef.d.ts.map +1 -1
- package/lib/typescript/src/createNavigatorFactory.d.ts +9 -5
- package/lib/typescript/src/createNavigatorFactory.d.ts.map +1 -1
- package/lib/typescript/src/getActionFromState.d.ts.map +1 -1
- package/lib/typescript/src/getPathFromState.d.ts.map +1 -1
- package/lib/typescript/src/getStateFromPath.d.ts.map +1 -1
- package/lib/typescript/src/index.d.ts +2 -1
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/types.d.ts +27 -18
- package/lib/typescript/src/types.d.ts.map +1 -1
- package/lib/typescript/src/useKeyedChildListeners.d.ts.map +1 -1
- package/lib/typescript/src/useNavigation.d.ts.map +1 -1
- package/lib/typescript/src/useNavigationBuilder.d.ts +1 -1
- package/lib/typescript/src/useNavigationBuilder.d.ts.map +1 -1
- package/lib/typescript/src/useNavigationCache.d.ts.map +1 -1
- package/lib/typescript/src/useNavigationHelpers.d.ts +3 -4
- package/lib/typescript/src/useNavigationHelpers.d.ts.map +1 -1
- package/lib/typescript/src/useNavigationState.d.ts +11 -1
- package/lib/typescript/src/useNavigationState.d.ts.map +1 -1
- package/lib/typescript/src/useOnAction.d.ts.map +1 -1
- package/lib/typescript/src/useOptionsGetters.d.ts.map +1 -1
- package/lib/typescript/src/usePreventRemove.d.ts.map +1 -1
- package/lib/typescript/src/usePreventRemoveContext.d.ts +1 -0
- package/lib/typescript/src/usePreventRemoveContext.d.ts.map +1 -1
- package/lib/typescript/src/useRouteCache.d.ts.map +1 -1
- package/lib/typescript/src/useScheduleUpdate.d.ts +5 -4
- package/lib/typescript/src/useScheduleUpdate.d.ts.map +1 -1
- package/lib/typescript/src/useSyncState.d.ts.map +1 -1
- package/lib/typescript/src/utilities.d.ts +17 -0
- package/lib/typescript/src/utilities.d.ts.map +1 -1
- package/lib/typescript/src/validatePathConfig.d.ts.map +1 -1
- package/package.json +3 -5
- package/src/BaseNavigationContainer.tsx +9 -2
- package/src/DataLoading.tsx +139 -0
- package/src/NavigationIndependentTree.tsx +11 -11
- package/src/NavigationProvider.tsx +13 -16
- package/src/PreventRemoveContext.tsx +1 -0
- package/src/PreventRemoveProvider.tsx +48 -43
- package/src/StaticNavigation.tsx +157 -93
- package/src/StaticTreeContext.tsx +7 -0
- package/src/checkSerializable.tsx +20 -14
- package/src/createNavigationContainerRef.tsx +12 -9
- package/src/createNavigatorFactory.tsx +16 -28
- package/src/getActionFromState.tsx +18 -16
- package/src/getPathFromState.tsx +69 -65
- package/src/getPatternParts.tsx +2 -2
- package/src/getStateFromPath.tsx +107 -66
- package/src/index.tsx +2 -0
- package/src/types.tsx +74 -55
- package/src/useEventEmitter.tsx +1 -1
- package/src/useKeyedChildListeners.tsx +4 -2
- package/src/useNavigation.tsx +2 -21
- package/src/useNavigationBuilder.tsx +6 -16
- package/src/useNavigationCache.tsx +26 -19
- package/src/useNavigationHelpers.tsx +26 -9
- package/src/useNavigationState.tsx +90 -60
- package/src/useOnAction.tsx +49 -1
- package/src/useOptionsGetters.tsx +4 -1
- package/src/usePreventRemove.tsx +11 -2
- package/src/useRouteCache.tsx +19 -11
- package/src/useScheduleUpdate.tsx +8 -7
- package/src/useSyncState.tsx +5 -1
- package/src/utilities.tsx +28 -0
- package/src/validatePathConfig.tsx +1 -0
|
@@ -5,9 +5,9 @@ import {
|
|
|
5
5
|
NamedRouteContextListContext,
|
|
6
6
|
NavigationContext,
|
|
7
7
|
NavigationRouteContext,
|
|
8
|
-
NavigationRouteNameContext,
|
|
9
8
|
} from './NavigationProvider';
|
|
10
9
|
import { IsFocusedContext } from './useIsFocused';
|
|
10
|
+
import { NamedNavigationStateListenerListContext } from './useNavigationState';
|
|
11
11
|
|
|
12
12
|
/**
|
|
13
13
|
* Component to make the child navigation container independent of parent containers.
|
|
@@ -19,18 +19,18 @@ export function NavigationIndependentTree({
|
|
|
19
19
|
}) {
|
|
20
20
|
return (
|
|
21
21
|
// We need to clear any existing contexts for nested independent container to work correctly
|
|
22
|
-
<
|
|
23
|
-
<
|
|
24
|
-
<
|
|
25
|
-
<
|
|
26
|
-
<
|
|
22
|
+
<NamedNavigationStateListenerListContext.Provider value={undefined}>
|
|
23
|
+
<NamedRouteContextListContext.Provider value={undefined}>
|
|
24
|
+
<NavigationRouteContext.Provider value={undefined}>
|
|
25
|
+
<NavigationContext.Provider value={undefined}>
|
|
26
|
+
<IsFocusedContext.Provider value={undefined}>
|
|
27
27
|
<NavigationIndependentTreeContext.Provider value={true}>
|
|
28
28
|
{children}
|
|
29
29
|
</NavigationIndependentTreeContext.Provider>
|
|
30
|
-
</
|
|
31
|
-
</
|
|
32
|
-
</
|
|
33
|
-
</
|
|
34
|
-
</
|
|
30
|
+
</IsFocusedContext.Provider>
|
|
31
|
+
</NavigationContext.Provider>
|
|
32
|
+
</NavigationRouteContext.Provider>
|
|
33
|
+
</NamedRouteContextListContext.Provider>
|
|
34
|
+
</NamedNavigationStateListenerListContext.Provider>
|
|
35
35
|
);
|
|
36
36
|
}
|
|
@@ -4,6 +4,7 @@ import * as React from 'react';
|
|
|
4
4
|
import type { NavigationProp } from './types';
|
|
5
5
|
import { FocusedRouteKeyContext, IsFocusedContext } from './useIsFocused';
|
|
6
6
|
import { useLazyValue } from './useLazyValue';
|
|
7
|
+
import { NamedNavigationStateListenerProvider } from './useNavigationState';
|
|
7
8
|
|
|
8
9
|
/**
|
|
9
10
|
* Context which holds the route prop for a screen.
|
|
@@ -19,10 +20,6 @@ export const NavigationContext = React.createContext<
|
|
|
19
20
|
NavigationProp<ParamListBase> | undefined
|
|
20
21
|
>(undefined);
|
|
21
22
|
|
|
22
|
-
export const NavigationRouteNameContext = React.createContext<
|
|
23
|
-
string | undefined
|
|
24
|
-
>(undefined);
|
|
25
|
-
|
|
26
23
|
type Props = {
|
|
27
24
|
route: Route<string>;
|
|
28
25
|
navigation: NavigationProp<ParamListBase>;
|
|
@@ -61,18 +58,18 @@ export function NavigationProvider({ route, navigation, children }: Props) {
|
|
|
61
58
|
: false;
|
|
62
59
|
|
|
63
60
|
return (
|
|
64
|
-
<
|
|
65
|
-
<
|
|
66
|
-
<
|
|
67
|
-
<
|
|
68
|
-
<
|
|
69
|
-
<
|
|
61
|
+
<NamedNavigationStateListenerProvider name={route.name}>
|
|
62
|
+
<NamedRouteContextListContext.Provider value={NamedRouteContextList}>
|
|
63
|
+
<NamedRouteContext.Provider value={route}>
|
|
64
|
+
<NavigationRouteContext.Provider value={route}>
|
|
65
|
+
<NavigationContext.Provider value={navigation}>
|
|
66
|
+
<IsFocusedContext.Provider value={isFocused}>
|
|
70
67
|
{children}
|
|
71
|
-
</
|
|
72
|
-
</
|
|
73
|
-
</
|
|
74
|
-
</
|
|
75
|
-
</
|
|
76
|
-
</
|
|
68
|
+
</IsFocusedContext.Provider>
|
|
69
|
+
</NavigationContext.Provider>
|
|
70
|
+
</NavigationRouteContext.Provider>
|
|
71
|
+
</NamedRouteContext.Provider>
|
|
72
|
+
</NamedRouteContextListContext.Provider>
|
|
73
|
+
</NamedNavigationStateListenerProvider>
|
|
77
74
|
);
|
|
78
75
|
}
|
|
@@ -13,13 +13,7 @@ type Props = {
|
|
|
13
13
|
children: React.ReactNode;
|
|
14
14
|
};
|
|
15
15
|
|
|
16
|
-
type PreventedRoutesMap = Map<
|
|
17
|
-
string,
|
|
18
|
-
{
|
|
19
|
-
routeKey: string;
|
|
20
|
-
preventRemove: boolean;
|
|
21
|
-
}
|
|
22
|
-
>;
|
|
16
|
+
type PreventedRoutesMap = Map<string, string>;
|
|
23
17
|
|
|
24
18
|
/**
|
|
25
19
|
* Util function to transform map of prevented routes to a simpler object.
|
|
@@ -27,17 +21,11 @@ type PreventedRoutesMap = Map<
|
|
|
27
21
|
const transformPreventedRoutes = (
|
|
28
22
|
preventedRoutesMap: PreventedRoutesMap
|
|
29
23
|
): PreventedRoutes => {
|
|
30
|
-
const
|
|
24
|
+
const preventedRoutes: PreventedRoutes = {};
|
|
31
25
|
|
|
32
|
-
const
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
preventRemove: acc[routeKey]?.preventRemove || preventRemove,
|
|
36
|
-
};
|
|
37
|
-
return acc;
|
|
38
|
-
},
|
|
39
|
-
{}
|
|
40
|
-
);
|
|
26
|
+
for (const routeKey of preventedRoutesMap.values()) {
|
|
27
|
+
preventedRoutes[routeKey] = { preventRemove: true };
|
|
28
|
+
}
|
|
41
29
|
|
|
42
30
|
return preventedRoutes;
|
|
43
31
|
};
|
|
@@ -50,12 +38,15 @@ export function PreventRemoveProvider({ children }: Props) {
|
|
|
50
38
|
const [preventedRoutesMap, setPreventedRoutesMap] =
|
|
51
39
|
React.useState<PreventedRoutesMap>(() => new Map());
|
|
52
40
|
|
|
41
|
+
const registry = React.useRef<PreventedRoutesMap>(new Map());
|
|
42
|
+
|
|
53
43
|
const navigation = React.use(NavigationHelpersContext);
|
|
54
44
|
const route = React.use(NavigationRouteContext);
|
|
55
45
|
|
|
56
46
|
const preventRemoveContextValue = React.use(PreventRemoveContext);
|
|
57
47
|
// take `setPreventRemove` from parent context - if exist it means we're in a nested context
|
|
58
48
|
const setParentPrevented = preventRemoveContextValue?.setPreventRemove;
|
|
49
|
+
const notifyParentPrevented = preventRemoveContextValue?.notifyPreventRemove;
|
|
59
50
|
|
|
60
51
|
const setPreventRemove = useLatestCallback(
|
|
61
52
|
(id: string, routeKey: string, preventRemove: boolean): void => {
|
|
@@ -71,36 +62,49 @@ export function PreventRemoveProvider({ children }: Props) {
|
|
|
71
62
|
);
|
|
72
63
|
}
|
|
73
64
|
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
) {
|
|
80
|
-
return prevPrevented;
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
const nextPrevented = new Map(prevPrevented);
|
|
84
|
-
|
|
85
|
-
if (preventRemove) {
|
|
86
|
-
nextPrevented.set(id, {
|
|
87
|
-
routeKey,
|
|
88
|
-
preventRemove,
|
|
89
|
-
});
|
|
90
|
-
} else {
|
|
91
|
-
nextPrevented.delete(id);
|
|
92
|
-
}
|
|
93
|
-
|
|
94
|
-
return nextPrevented;
|
|
95
|
-
});
|
|
65
|
+
if (preventRemove) {
|
|
66
|
+
registry.current.set(id, routeKey);
|
|
67
|
+
} else {
|
|
68
|
+
registry.current.delete(id);
|
|
69
|
+
}
|
|
96
70
|
}
|
|
97
71
|
);
|
|
98
72
|
|
|
99
|
-
const
|
|
100
|
-
|
|
101
|
-
|
|
73
|
+
const notifyPreventRemove = useLatestCallback(() => {
|
|
74
|
+
// eslint-disable-next-line @eslint-react/hooks-extra/no-direct-set-state-in-use-effect
|
|
75
|
+
setPreventedRoutesMap((prevPrevented) => {
|
|
76
|
+
const nextPrevented = registry.current;
|
|
102
77
|
|
|
78
|
+
const hasChanged =
|
|
79
|
+
prevPrevented.size !== nextPrevented.size ||
|
|
80
|
+
[...nextPrevented].some(
|
|
81
|
+
([id, routeKey]) => prevPrevented.get(id) !== routeKey
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
// values haven't changed - do nothing
|
|
85
|
+
if (!hasChanged) {
|
|
86
|
+
return prevPrevented;
|
|
87
|
+
}
|
|
88
|
+
|
|
89
|
+
return new Map(nextPrevented);
|
|
90
|
+
});
|
|
91
|
+
});
|
|
92
|
+
|
|
93
|
+
// Sync the state on every commit in case the registry was changed by a screen
|
|
94
|
+
// unmounting while hidden with `<Activity>`, where no passive effects run
|
|
95
|
+
// Also notify the parent so nested prevention propagates upwards
|
|
103
96
|
React.useEffect(() => {
|
|
97
|
+
notifyPreventRemove();
|
|
98
|
+
notifyParentPrevented?.();
|
|
99
|
+
|
|
100
|
+
return () => {
|
|
101
|
+
notifyParentPrevented?.();
|
|
102
|
+
};
|
|
103
|
+
});
|
|
104
|
+
|
|
105
|
+
const isPrevented = preventedRoutesMap.size > 0;
|
|
106
|
+
|
|
107
|
+
React.useInsertionEffect(() => {
|
|
104
108
|
if (route?.key !== undefined && setParentPrevented !== undefined) {
|
|
105
109
|
// when route is defined (and setParentPrevented) it means we're in a nested stack
|
|
106
110
|
// route.key then will be the route key of parent
|
|
@@ -116,9 +120,10 @@ export function PreventRemoveProvider({ children }: Props) {
|
|
|
116
120
|
const value = React.useMemo(
|
|
117
121
|
() => ({
|
|
118
122
|
setPreventRemove,
|
|
123
|
+
notifyPreventRemove,
|
|
119
124
|
preventedRoutes: transformPreventedRoutes(preventedRoutesMap),
|
|
120
125
|
}),
|
|
121
|
-
[setPreventRemove, preventedRoutesMap]
|
|
126
|
+
[setPreventRemove, notifyPreventRemove, preventedRoutesMap]
|
|
122
127
|
);
|
|
123
128
|
|
|
124
129
|
return (
|
package/src/StaticNavigation.tsx
CHANGED
|
@@ -1,4 +1,8 @@
|
|
|
1
|
-
import type {
|
|
1
|
+
import type {
|
|
2
|
+
NavigationState,
|
|
3
|
+
ParamListBase,
|
|
4
|
+
Route,
|
|
5
|
+
} from '@react-navigation/routers';
|
|
2
6
|
import * as React from 'react';
|
|
3
7
|
import { isValidElementType } from 'react-is';
|
|
4
8
|
|
|
@@ -7,10 +11,11 @@ import {
|
|
|
7
11
|
getPatternParts,
|
|
8
12
|
type PatternPart,
|
|
9
13
|
} from './getPatternParts';
|
|
14
|
+
import { StaticTreeContext } from './StaticTreeContext';
|
|
10
15
|
import type {
|
|
11
|
-
DefaultNavigatorOptions,
|
|
12
16
|
EventMapBase,
|
|
13
17
|
NavigationListBase,
|
|
18
|
+
NavigatorProps,
|
|
14
19
|
NavigatorScreenParams,
|
|
15
20
|
NavigatorTypeBagBase,
|
|
16
21
|
NavigatorTypeBagFor,
|
|
@@ -27,6 +32,8 @@ import type {
|
|
|
27
32
|
HasArguments,
|
|
28
33
|
InferParamsFromLinking,
|
|
29
34
|
KeysOf,
|
|
35
|
+
NoExcessObject,
|
|
36
|
+
NotUndefinedObject,
|
|
30
37
|
StandardSchemaV1,
|
|
31
38
|
UnionToIntersection,
|
|
32
39
|
ValidPathPattern,
|
|
@@ -105,7 +112,13 @@ type ShouldInferFromLinking<Linking> = Linking extends {
|
|
|
105
112
|
type ParamsForConfig<Linking, Screen, Params = ParamsForScreen<Screen>> =
|
|
106
113
|
ShouldInferFromLinking<Linking> extends true
|
|
107
114
|
? [Screen] extends [{ config: any }]
|
|
108
|
-
?
|
|
115
|
+
? undefined extends Params
|
|
116
|
+
? FlatType<InferParamsFromLinking<Linking>> & Params
|
|
117
|
+
: // Optional linking params make the whole route params type optional when intersected.
|
|
118
|
+
// e.g. `({...} | undefined) & NavigatorScreenParams<{...}>` adds `| undefined` to the whole type.
|
|
119
|
+
// But if nested navigator had required params, it should still be required.
|
|
120
|
+
// So we remove `| undefined` from linking params before intersecting with nested navigator params.
|
|
121
|
+
FlatType<NotUndefinedObject<InferParamsFromLinking<Linking>>> & Params
|
|
109
122
|
: undefined extends Params
|
|
110
123
|
? FlatType<InferParamsFromLinking<Linking>>
|
|
111
124
|
: FlatType<InferParamsFromLinking<Linking> & Params>
|
|
@@ -125,15 +138,7 @@ type ParamListForScreens<Screens> = {
|
|
|
125
138
|
: ParamsForScreenEntry<Screens[Key]>;
|
|
126
139
|
};
|
|
127
140
|
|
|
128
|
-
type ParamListForGroups<
|
|
129
|
-
Groups extends
|
|
130
|
-
| Readonly<{
|
|
131
|
-
[key: string]: {
|
|
132
|
-
screens: {};
|
|
133
|
-
};
|
|
134
|
-
}>
|
|
135
|
-
| undefined,
|
|
136
|
-
> = Groups extends {
|
|
141
|
+
type ParamListForGroups<Groups> = Groups extends {
|
|
137
142
|
[key: string]: {
|
|
138
143
|
screens: infer Screens;
|
|
139
144
|
};
|
|
@@ -141,27 +146,20 @@ type ParamListForGroups<
|
|
|
141
146
|
? ParamListForScreens<UnionToIntersection<Screens>>
|
|
142
147
|
: {};
|
|
143
148
|
|
|
144
|
-
type
|
|
145
|
-
|
|
146
|
-
name: string;
|
|
147
|
-
path?: string | undefined;
|
|
148
|
-
history?: { type: 'params'; params: object }[] | undefined;
|
|
149
|
-
};
|
|
150
|
-
|
|
151
|
-
type RouteType<Params, P = AnyToUnknown<Params>> = Readonly<
|
|
152
|
-
RouteTypeBase &
|
|
149
|
+
type StaticRoute<Params, P = AnyToUnknown<Params>> = Readonly<
|
|
150
|
+
Omit<Route<string>, 'params'> &
|
|
153
151
|
(undefined extends Params
|
|
154
152
|
? {
|
|
155
153
|
/**
|
|
156
154
|
* Params for this route
|
|
157
155
|
*/
|
|
158
|
-
params?: P;
|
|
156
|
+
params?: P extends object ? Readonly<P> : P;
|
|
159
157
|
}
|
|
160
158
|
: {
|
|
161
159
|
/**
|
|
162
160
|
* Params for this route
|
|
163
161
|
*/
|
|
164
|
-
params: P
|
|
162
|
+
params: Readonly<P>;
|
|
165
163
|
})
|
|
166
164
|
>;
|
|
167
165
|
|
|
@@ -222,23 +220,25 @@ type StaticScreenConfigLinkingAlias = {
|
|
|
222
220
|
shared?: boolean;
|
|
223
221
|
};
|
|
224
222
|
|
|
223
|
+
type StaticScreenConfigLinkingExtras = {
|
|
224
|
+
/**
|
|
225
|
+
* Additional path alias that will be matched to the same screen.
|
|
226
|
+
*/
|
|
227
|
+
alias?: (string | StaticScreenConfigLinkingAlias)[];
|
|
228
|
+
/**
|
|
229
|
+
* Name of the initial route to use for the nested navigator when the path matches.
|
|
230
|
+
*/
|
|
231
|
+
initialRouteName?: string | undefined;
|
|
232
|
+
/**
|
|
233
|
+
* Path configuration for child screens in the nested navigator.
|
|
234
|
+
* Only supported when the screen renders a navigator with dynamic API.
|
|
235
|
+
*/
|
|
236
|
+
screens?: PathConfigMap<ParamListBase> | undefined;
|
|
237
|
+
};
|
|
238
|
+
|
|
225
239
|
export type StaticScreenConfigLinking =
|
|
226
240
|
| string
|
|
227
|
-
| (StaticScreenConfigLinkingAlias &
|
|
228
|
-
/**
|
|
229
|
-
* Additional path alias that will be matched to the same screen.
|
|
230
|
-
*/
|
|
231
|
-
alias?: (string | StaticScreenConfigLinkingAlias)[];
|
|
232
|
-
/**
|
|
233
|
-
* Name of the initial route to use for the nested navigator when the path matches.
|
|
234
|
-
*/
|
|
235
|
-
initialRouteName?: string | undefined;
|
|
236
|
-
/**
|
|
237
|
-
* Path configuration for child screens in the nested navigator.
|
|
238
|
-
* Only supported when the screen renders a navigator with dynamic API.
|
|
239
|
-
*/
|
|
240
|
-
screens?: PathConfigMap<ParamListBase> | undefined;
|
|
241
|
-
})
|
|
241
|
+
| (StaticScreenConfigLinkingAlias & StaticScreenConfigLinkingExtras)
|
|
242
242
|
| null
|
|
243
243
|
| undefined;
|
|
244
244
|
|
|
@@ -288,7 +288,7 @@ export type StaticScreenConfig<
|
|
|
288
288
|
options?:
|
|
289
289
|
| ScreenOptions
|
|
290
290
|
| ((props: {
|
|
291
|
-
route:
|
|
291
|
+
route: StaticRoute<Params>;
|
|
292
292
|
navigation: Navigation;
|
|
293
293
|
theme: Theme;
|
|
294
294
|
}) => ScreenOptions);
|
|
@@ -308,7 +308,7 @@ export type StaticScreenConfig<
|
|
|
308
308
|
listeners?:
|
|
309
309
|
| ScreenListeners<State, EventMap>
|
|
310
310
|
| ((props: {
|
|
311
|
-
route:
|
|
311
|
+
route: StaticRoute<Params>;
|
|
312
312
|
navigation: Navigation;
|
|
313
313
|
}) => ScreenListeners<State, EventMap>);
|
|
314
314
|
|
|
@@ -328,7 +328,7 @@ export type StaticScreenConfig<
|
|
|
328
328
|
*
|
|
329
329
|
*/
|
|
330
330
|
layout?: (props: {
|
|
331
|
-
route:
|
|
331
|
+
route: StaticRoute<Params>;
|
|
332
332
|
options: ScreenOptions;
|
|
333
333
|
navigation: Navigation;
|
|
334
334
|
theme: Theme;
|
|
@@ -355,7 +355,9 @@ export type StaticScreenConfig<
|
|
|
355
355
|
* getId: ({ params }) => params?.userId,
|
|
356
356
|
* ```
|
|
357
357
|
*/
|
|
358
|
-
getId?: (props: {
|
|
358
|
+
getId?: (props: {
|
|
359
|
+
params: AnyToUnknown<Params extends object ? Readonly<Params> : Params>;
|
|
360
|
+
}) => string | undefined;
|
|
359
361
|
|
|
360
362
|
/**
|
|
361
363
|
* Linking config for the screen.
|
|
@@ -377,11 +379,27 @@ export type StaticScreenConfig<
|
|
|
377
379
|
* Optional key for this screen.
|
|
378
380
|
*/
|
|
379
381
|
navigationKey?: string;
|
|
382
|
+
|
|
383
|
+
/**
|
|
384
|
+
* Loader function to start loading data when the screen is navigated to.
|
|
385
|
+
*
|
|
386
|
+
* @example
|
|
387
|
+
* ```js
|
|
388
|
+
* UNSTABLE_loader: ({ params }) => loadProfile(params.id),
|
|
389
|
+
* ```
|
|
390
|
+
*/
|
|
391
|
+
UNSTABLE_loader?: (options: {
|
|
392
|
+
name: string;
|
|
393
|
+
params: AnyToUnknown<Params>;
|
|
394
|
+
}) => Promise<void>;
|
|
380
395
|
};
|
|
381
396
|
|
|
382
397
|
export type StaticScreenFactory<in out Bag extends NavigatorTypeBagBase> = <
|
|
383
398
|
const Linking extends StaticScreenConfigLinking,
|
|
384
399
|
const Screen extends StaticScreenConfigScreen,
|
|
400
|
+
const ProvidedOptions extends
|
|
401
|
+
| Bag['ScreenOptions']
|
|
402
|
+
| ((...args: never[]) => unknown) = Bag['ScreenOptions'],
|
|
385
403
|
>(
|
|
386
404
|
config: StaticScreenConfig<
|
|
387
405
|
Linking,
|
|
@@ -390,7 +408,10 @@ export type StaticScreenFactory<in out Bag extends NavigatorTypeBagBase> = <
|
|
|
390
408
|
Bag['ScreenOptions'],
|
|
391
409
|
Bag['EventMap'],
|
|
392
410
|
Bag['NavigationList'][keyof Bag['ParamList']]
|
|
393
|
-
>
|
|
411
|
+
> & {
|
|
412
|
+
options?: ProvidedOptions &
|
|
413
|
+
NoExcessOptions<ProvidedOptions, Bag['ScreenOptions']>;
|
|
414
|
+
}
|
|
394
415
|
) => StaticScreenConfig<
|
|
395
416
|
Linking,
|
|
396
417
|
Screen,
|
|
@@ -456,51 +477,33 @@ type StaticConfigGroup<
|
|
|
456
477
|
>;
|
|
457
478
|
};
|
|
458
479
|
|
|
459
|
-
export type StaticConfig<
|
|
460
|
-
|
|
480
|
+
export type StaticConfig<
|
|
481
|
+
Bag extends NavigatorTypeBagBase,
|
|
482
|
+
Screens = StaticConfigScreens<
|
|
461
483
|
Bag['ParamList'],
|
|
462
484
|
Bag['State'],
|
|
463
485
|
Bag['ScreenOptions'],
|
|
464
486
|
Bag['EventMap'],
|
|
465
|
-
Bag['NavigationList']
|
|
466
|
-
Bag['Navigator']
|
|
467
|
-
>;
|
|
468
|
-
|
|
469
|
-
type StaticConfigInternal<
|
|
470
|
-
ParamList extends ParamListBase,
|
|
471
|
-
State extends NavigationState,
|
|
472
|
-
ScreenOptions extends {},
|
|
473
|
-
EventMap extends EventMapBase,
|
|
474
|
-
NavigationList extends NavigationListBase<ParamList>,
|
|
475
|
-
Navigator extends React.ComponentType<any>,
|
|
476
|
-
Screens = StaticConfigScreens<
|
|
477
|
-
ParamList,
|
|
478
|
-
State,
|
|
479
|
-
ScreenOptions,
|
|
480
|
-
EventMap,
|
|
481
|
-
NavigationList
|
|
487
|
+
Bag['NavigationList']
|
|
482
488
|
>,
|
|
483
489
|
Groups = {
|
|
484
490
|
[key: string]: StaticConfigGroup<
|
|
485
|
-
ParamList,
|
|
486
|
-
State,
|
|
487
|
-
ScreenOptions,
|
|
488
|
-
EventMap,
|
|
489
|
-
NavigationList
|
|
491
|
+
Bag['ParamList'],
|
|
492
|
+
Bag['State'],
|
|
493
|
+
Bag['ScreenOptions'],
|
|
494
|
+
Bag['EventMap'],
|
|
495
|
+
Bag['NavigationList']
|
|
490
496
|
>;
|
|
491
497
|
},
|
|
492
498
|
> = Omit<
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
EventMap,
|
|
502
|
-
NavigationList[keyof ParamList]
|
|
503
|
-
>,
|
|
499
|
+
NavigatorProps<
|
|
500
|
+
Bag['ParamList'],
|
|
501
|
+
Bag['State'],
|
|
502
|
+
Bag['ScreenOptions'],
|
|
503
|
+
Bag['EventMap'],
|
|
504
|
+
Bag['NavigationList'][keyof Bag['ParamList']],
|
|
505
|
+
Bag['Navigator']
|
|
506
|
+
>,
|
|
504
507
|
'screens' | 'children'
|
|
505
508
|
> &
|
|
506
509
|
(
|
|
@@ -526,6 +529,67 @@ type StaticConfigInternal<
|
|
|
526
529
|
}
|
|
527
530
|
);
|
|
528
531
|
|
|
532
|
+
type NoExcessOptions<Provided, Allowed extends {}> = Provided extends (
|
|
533
|
+
...args: never[]
|
|
534
|
+
) => infer Return
|
|
535
|
+
? (...args: never[]) => Allowed & NoExcessObject<Return, Allowed>
|
|
536
|
+
: NoExcessObject<Provided, Allowed>;
|
|
537
|
+
|
|
538
|
+
type NoExcessScreen<Screen, ScreenOptions extends {}> = Screen extends {
|
|
539
|
+
screen: unknown;
|
|
540
|
+
options: unknown;
|
|
541
|
+
}
|
|
542
|
+
? { options: NoExcessOptions<Screen['options'], ScreenOptions> }
|
|
543
|
+
: unknown;
|
|
544
|
+
|
|
545
|
+
type NoExcessScreens<Screens, ScreenOptions extends {}> = {
|
|
546
|
+
[RouteName in keyof Screens]: NoExcessScreen<
|
|
547
|
+
Screens[RouteName],
|
|
548
|
+
ScreenOptions
|
|
549
|
+
>;
|
|
550
|
+
};
|
|
551
|
+
|
|
552
|
+
type NoExcessGroups<
|
|
553
|
+
Groups,
|
|
554
|
+
Bag extends NavigatorTypeBagBase,
|
|
555
|
+
ScreenOptions extends {},
|
|
556
|
+
> = {
|
|
557
|
+
[GroupName in keyof Groups]: NoExcessObject<
|
|
558
|
+
Groups[GroupName],
|
|
559
|
+
StaticConfigGroup<
|
|
560
|
+
ParamListBase,
|
|
561
|
+
NavigationState,
|
|
562
|
+
{},
|
|
563
|
+
EventMapBase,
|
|
564
|
+
NavigationListBase<ParamListBase>
|
|
565
|
+
>
|
|
566
|
+
> &
|
|
567
|
+
NoExcessStaticConfig<Groups[GroupName], Bag, ScreenOptions>;
|
|
568
|
+
};
|
|
569
|
+
|
|
570
|
+
// Each property is probed with `Config extends { key: infer X }` and the results are intersected.
|
|
571
|
+
// These conditionals stay deferred while the config is inferred, so they don't interfere with the inference.
|
|
572
|
+
// Indexed access (`Config['screens']`) or a mapped type over the whole config breaks the param list inference.
|
|
573
|
+
export type NoExcessStaticConfig<
|
|
574
|
+
Config,
|
|
575
|
+
Bag extends NavigatorTypeBagBase,
|
|
576
|
+
ScreenOptions extends {} = Bag['ScreenOptions'],
|
|
577
|
+
> = (Config extends { screenOptions: infer ProvidedOptions }
|
|
578
|
+
? {
|
|
579
|
+
screenOptions: NoExcessOptions<ProvidedOptions, ScreenOptions>;
|
|
580
|
+
}
|
|
581
|
+
: unknown) &
|
|
582
|
+
(Config extends { screens: infer Screens }
|
|
583
|
+
? {
|
|
584
|
+
screens: NoExcessScreens<Screens, ScreenOptions>;
|
|
585
|
+
}
|
|
586
|
+
: unknown) &
|
|
587
|
+
(Config extends { groups: infer Groups }
|
|
588
|
+
? {
|
|
589
|
+
groups: NoExcessGroups<Groups, Bag, ScreenOptions>;
|
|
590
|
+
}
|
|
591
|
+
: unknown);
|
|
592
|
+
|
|
529
593
|
/**
|
|
530
594
|
* Props for a screen component which is rendered by a static navigator.
|
|
531
595
|
* Takes the route params as a generic argument.
|
|
@@ -534,7 +598,7 @@ export type StaticScreenProps<
|
|
|
534
598
|
in out T extends Record<string, unknown> | undefined,
|
|
535
599
|
> = {
|
|
536
600
|
route: {
|
|
537
|
-
params: T;
|
|
601
|
+
readonly params: T;
|
|
538
602
|
};
|
|
539
603
|
};
|
|
540
604
|
|
|
@@ -724,14 +788,16 @@ export function createComponentForStaticConfig<
|
|
|
724
788
|
: { ...rest.screenListeners, ...props.screenListeners };
|
|
725
789
|
|
|
726
790
|
return (
|
|
727
|
-
<
|
|
728
|
-
|
|
729
|
-
|
|
730
|
-
|
|
731
|
-
|
|
732
|
-
|
|
733
|
-
|
|
734
|
-
|
|
791
|
+
<StaticTreeContext.Provider value={tree}>
|
|
792
|
+
<Navigator
|
|
793
|
+
{...rest}
|
|
794
|
+
{...props}
|
|
795
|
+
screenOptions={screenOptions}
|
|
796
|
+
screenListeners={screenListeners}
|
|
797
|
+
>
|
|
798
|
+
{children}
|
|
799
|
+
</Navigator>
|
|
800
|
+
</StaticTreeContext.Provider>
|
|
735
801
|
);
|
|
736
802
|
};
|
|
737
803
|
|
|
@@ -740,7 +806,7 @@ export function createComponentForStaticConfig<
|
|
|
740
806
|
return NavigatorComponent;
|
|
741
807
|
}
|
|
742
808
|
|
|
743
|
-
type TreeForPathConfig = {
|
|
809
|
+
export type TreeForPathConfig = {
|
|
744
810
|
config: ConfigForPathConfig;
|
|
745
811
|
};
|
|
746
812
|
|
|
@@ -752,11 +818,7 @@ type ConfigForPathConfig = {
|
|
|
752
818
|
|
|
753
819
|
type LinkingForPathConfig =
|
|
754
820
|
| string
|
|
755
|
-
| (Partial<StaticScreenConfigLinkingAlias> &
|
|
756
|
-
alias?: (string | StaticScreenConfigLinkingAlias)[];
|
|
757
|
-
initialRouteName?: string | undefined;
|
|
758
|
-
screens?: PathConfigMap<ParamListBase> | undefined;
|
|
759
|
-
})
|
|
821
|
+
| (Partial<StaticScreenConfigLinkingAlias> & StaticScreenConfigLinkingExtras)
|
|
760
822
|
| null
|
|
761
823
|
| undefined;
|
|
762
824
|
|
|
@@ -766,7 +828,9 @@ type ScreenForPathConfig =
|
|
|
766
828
|
| ScreenValueForPathConfig
|
|
767
829
|
| {
|
|
768
830
|
screen: ScreenValueForPathConfig;
|
|
831
|
+
initialParams?: object;
|
|
769
832
|
linking?: LinkingForPathConfig;
|
|
833
|
+
UNSTABLE_loader?: unknown;
|
|
770
834
|
};
|
|
771
835
|
|
|
772
836
|
type PathConfigMapForStaticNavigation = Record<
|