expo-router 2.0.0 → 3.0.0
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/README.md +1 -1
- package/{_ctx.android.tsx → _ctx.android.js} +1 -2
- package/_ctx.d.ts +3 -0
- package/{_ctx.ios.tsx → _ctx.ios.js} +1 -2
- package/_ctx.js +1 -0
- package/{_ctx.web.tsx → _ctx.web.js} +1 -2
- package/_error.js +2 -4
- package/app.plugin.js +1 -1
- package/babel.js +44 -55
- package/build/ExpoRoot.d.ts +2 -2
- package/build/ExpoRoot.d.ts.map +1 -1
- package/build/ExpoRoot.js +79 -0
- package/build/ExpoRoot.js.map +1 -0
- package/build/LocationProvider.d.ts +2 -2
- package/build/LocationProvider.d.ts.map +1 -1
- package/build/LocationProvider.js +30 -0
- package/build/LocationProvider.js.map +1 -0
- package/build/Route.d.ts +3 -3
- package/build/Route.d.ts.map +1 -1
- package/build/Route.js +68 -0
- package/build/Route.js.map +1 -0
- package/build/exports.d.ts +12 -12
- package/build/exports.js +17 -0
- package/build/exports.js.map +1 -0
- package/build/fork/NavigationContainer.d.ts +1 -1
- package/build/fork/NavigationContainer.js +4 -0
- package/build/fork/NavigationContainer.js.map +1 -0
- package/build/fork/NavigationContainer.native.d.ts +3 -3
- package/build/fork/NavigationContainer.native.d.ts.map +1 -1
- package/build/fork/NavigationContainer.native.js +81 -0
- package/build/fork/NavigationContainer.native.js.map +1 -0
- package/build/fork/expo/createRoot.d.ts +1 -1
- package/build/fork/expo/createRoot.js +2 -0
- package/build/fork/expo/createRoot.js.map +1 -0
- package/{src/fork/expo/createRoot.native.tsx → build/fork/expo/createRoot.native.js} +3 -2
- package/build/fork/expo/createRoot.native.js.map +1 -0
- package/build/fork/expo/registerRootComponent.d.ts +3 -3
- package/build/fork/expo/registerRootComponent.js +51 -0
- package/build/fork/expo/registerRootComponent.js.map +1 -0
- package/build/fork/extractPathFromURL.d.ts.map +1 -1
- package/build/fork/extractPathFromURL.js +76 -0
- package/build/fork/extractPathFromURL.js.map +1 -0
- package/build/fork/findFocusedRoute.d.ts +1 -1
- package/build/fork/findFocusedRoute.js +10 -0
- package/build/fork/findFocusedRoute.js.map +1 -0
- package/build/fork/getPathFromState.d.ts +3 -3
- package/build/fork/getPathFromState.d.ts.map +1 -1
- package/build/fork/getPathFromState.js +419 -0
- package/build/fork/getPathFromState.js.map +1 -0
- package/build/fork/getStateFromPath.d.ts +3 -3
- package/build/fork/getStateFromPath.d.ts.map +1 -1
- package/build/fork/getStateFromPath.js +503 -0
- package/build/fork/getStateFromPath.js.map +1 -0
- package/build/fork/useLinking.d.ts.map +1 -1
- package/build/fork/useLinking.js +3 -0
- package/build/fork/useLinking.js.map +1 -0
- package/build/fork/useLinking.native.d.ts +3 -3
- package/build/fork/useLinking.native.d.ts.map +1 -1
- package/build/fork/useLinking.native.js +154 -0
- package/build/fork/useLinking.native.js.map +1 -0
- package/build/fork/validatePathConfig.d.ts.map +1 -1
- package/build/fork/validatePathConfig.js +19 -0
- package/build/fork/validatePathConfig.js.map +1 -0
- package/build/getDevServer/index.js +30 -0
- package/build/getDevServer/index.js.map +1 -0
- package/build/getDevServer/index.native.js +2 -0
- package/build/getDevServer/index.native.js.map +1 -0
- package/build/getLinkingConfig.d.ts +4 -4
- package/build/getLinkingConfig.d.ts.map +1 -1
- package/build/getLinkingConfig.js +43 -0
- package/build/getLinkingConfig.js.map +1 -0
- package/build/getReactNavigationConfig.d.ts +1 -1
- package/build/getReactNavigationConfig.d.ts.map +1 -1
- package/build/getReactNavigationConfig.js +69 -0
- package/build/getReactNavigationConfig.js.map +1 -0
- package/build/getRoutes.d.ts +4 -4
- package/build/getRoutes.d.ts.map +1 -1
- package/build/getRoutes.js +378 -0
- package/build/getRoutes.js.map +1 -0
- package/build/global-state/router-store.d.ts +15 -16
- package/build/global-state/router-store.d.ts.map +1 -1
- package/build/global-state/router-store.js +179 -0
- package/build/global-state/router-store.js.map +1 -0
- package/build/global-state/routing.d.ts +6 -6
- package/build/global-state/routing.d.ts.map +1 -1
- package/build/global-state/routing.js +149 -0
- package/build/global-state/routing.js.map +1 -0
- package/build/global-state/sort-routes.d.ts +1 -1
- package/build/global-state/sort-routes.d.ts.map +1 -1
- package/build/global-state/sort-routes.js +8 -0
- package/build/global-state/sort-routes.js.map +1 -0
- package/build/head/ExpoHead.android.d.ts +10 -0
- package/build/head/ExpoHead.android.d.ts.map +1 -0
- package/build/head/ExpoHead.android.js +6 -0
- package/build/head/ExpoHead.android.js.map +1 -0
- package/build/head/ExpoHead.d.ts +8 -0
- package/build/head/ExpoHead.d.ts.map +1 -0
- package/build/head/ExpoHead.ios.d.ts +7 -0
- package/build/head/ExpoHead.ios.d.ts.map +1 -0
- package/build/head/ExpoHead.ios.js +242 -0
- package/build/head/ExpoHead.ios.js.map +1 -0
- package/build/head/ExpoHead.js +7 -0
- package/build/head/ExpoHead.js.map +1 -0
- package/build/head/ExpoHeadModule.d.ts +33 -0
- package/build/head/ExpoHeadModule.d.ts.map +1 -0
- package/build/head/ExpoHeadModule.js +4 -0
- package/build/head/ExpoHeadModule.js.map +1 -0
- package/build/head/ExpoHeadModule.native.d.ts +3 -0
- package/build/head/ExpoHeadModule.native.d.ts.map +1 -0
- package/build/head/ExpoHeadModule.native.js +10 -0
- package/build/head/ExpoHeadModule.native.js.map +1 -0
- package/build/head/index.d.ts +2 -0
- package/build/head/index.d.ts.map +1 -0
- package/build/head/index.js +2 -0
- package/build/head/index.js.map +1 -0
- package/build/head/url.d.ts +2 -0
- package/build/head/url.d.ts.map +1 -0
- package/build/head/url.js +64 -0
- package/build/head/url.js.map +1 -0
- package/build/hooks.d.ts +1 -1
- package/build/hooks.d.ts.map +1 -1
- package/{src/hooks.ts → build/hooks.js} +34 -66
- package/build/hooks.js.map +1 -0
- package/build/imperative-api.d.ts +1 -1
- package/build/imperative-api.js +9 -0
- package/build/imperative-api.js.map +1 -0
- package/{src/import-mode/index.android.ts → build/import-mode/index.android.js} +1 -0
- package/build/import-mode/index.android.js.map +1 -0
- package/{src/import-mode/index.ios.ts → build/import-mode/index.ios.js} +1 -0
- package/build/import-mode/index.ios.js.map +1 -0
- package/build/import-mode/index.js +2 -0
- package/build/import-mode/index.js.map +1 -0
- package/{src/import-mode/index.web.ts → build/import-mode/index.web.js} +1 -0
- package/build/import-mode/index.web.js.map +1 -0
- package/build/index.d.ts +3 -3
- package/build/index.js +4 -0
- package/build/index.js.map +1 -0
- package/build/layouts/Drawer.d.ts +1 -1
- package/build/layouts/Drawer.d.ts.map +1 -1
- package/build/layouts/Drawer.js +6 -0
- package/build/layouts/Drawer.js.map +1 -0
- package/build/layouts/Stack.d.ts +1 -1
- package/build/layouts/Stack.d.ts.map +1 -1
- package/build/layouts/Stack.js +6 -0
- package/build/layouts/Stack.js.map +1 -0
- package/build/layouts/Tabs.d.ts +4 -4
- package/build/layouts/Tabs.d.ts.map +1 -1
- package/build/layouts/Tabs.js +34 -0
- package/build/layouts/Tabs.js.map +1 -0
- package/build/layouts/withLayoutContext.d.ts +4 -4
- package/build/layouts/withLayoutContext.d.ts.map +1 -1
- package/build/layouts/withLayoutContext.js +65 -0
- package/build/layouts/withLayoutContext.js.map +1 -0
- package/build/link/Link.d.ts +5 -5
- package/build/link/Link.d.ts.map +1 -1
- package/build/link/Link.js +63 -0
- package/build/link/Link.js.map +1 -0
- package/build/link/href.d.ts.map +1 -1
- package/build/link/href.js +46 -0
- package/build/link/href.js.map +1 -0
- package/build/link/linking.d.ts +2 -2
- package/build/link/linking.d.ts.map +1 -1
- package/build/link/linking.js +86 -0
- package/build/link/linking.js.map +1 -0
- package/build/link/path.d.ts.map +1 -1
- package/build/link/path.js +143 -0
- package/build/link/path.js.map +1 -0
- package/build/link/stateOperations.d.ts +3 -3
- package/build/link/stateOperations.js +91 -0
- package/build/link/stateOperations.js.map +1 -0
- package/build/link/useLinkToPathProps.d.ts +2 -2
- package/build/link/useLinkToPathProps.d.ts.map +1 -1
- package/build/link/useLinkToPathProps.js +45 -0
- package/build/link/useLinkToPathProps.js.map +1 -0
- package/build/link/useLoadedNavigation.d.ts +1 -1
- package/build/link/useLoadedNavigation.js +46 -0
- package/build/link/useLoadedNavigation.js.map +1 -0
- package/build/loadStaticParamsAsync.d.ts +1 -1
- package/build/loadStaticParamsAsync.d.ts.map +1 -1
- package/build/loadStaticParamsAsync.js +117 -0
- package/build/loadStaticParamsAsync.js.map +1 -0
- package/build/matchers.js +49 -0
- package/build/matchers.js.map +1 -0
- package/build/onboard/Tutorial.d.ts.map +1 -1
- package/build/onboard/Tutorial.js +155 -0
- package/build/onboard/Tutorial.js.map +1 -0
- package/{src/onboard/createEntryFile.ts → build/onboard/createEntryFile.js} +19 -22
- package/build/onboard/createEntryFile.js.map +1 -0
- package/build/primitives.js +5 -0
- package/build/primitives.js.map +1 -0
- package/build/qualified-entry.d.ts +3 -0
- package/build/qualified-entry.d.ts.map +1 -0
- package/{_app.tsx → build/qualified-entry.js} +7 -10
- package/build/qualified-entry.js.map +1 -0
- package/build/renderRootComponent.d.ts +1 -1
- package/build/renderRootComponent.d.ts.map +1 -1
- package/build/renderRootComponent.js +72 -0
- package/build/renderRootComponent.js.map +1 -0
- package/build/static/getRootComponent.d.ts.map +1 -1
- package/build/static/getRootComponent.js +22 -0
- package/build/static/getRootComponent.js.map +1 -0
- package/build/static/html.d.ts +1 -1
- package/build/static/html.js +25 -0
- package/build/static/html.js.map +1 -0
- package/build/static/renderStaticContent.d.ts +6 -1
- package/build/static/renderStaticContent.d.ts.map +1 -1
- package/build/static/renderStaticContent.js +85 -0
- package/build/static/renderStaticContent.js.map +1 -0
- package/build/testing-library/context-stubs.d.ts +1 -1
- package/build/testing-library/context-stubs.d.ts.map +1 -1
- package/build/testing-library/context-stubs.js +30 -0
- package/build/testing-library/context-stubs.js.map +1 -0
- package/build/testing-library/expect.js +14 -0
- package/build/testing-library/expect.js.map +1 -0
- package/build/testing-library/index.d.ts +4 -4
- package/build/testing-library/index.d.ts.map +1 -1
- package/build/testing-library/index.js +57 -0
- package/build/testing-library/index.js.map +1 -0
- package/build/testing-library/mocks.d.ts +1 -1
- package/build/testing-library/mocks.js +33 -0
- package/build/testing-library/mocks.js.map +1 -0
- package/build/testing-library/require-context-ponyfill.d.ts +1 -1
- package/build/testing-library/require-context-ponyfill.js +29 -0
- package/build/testing-library/require-context-ponyfill.js.map +1 -0
- package/build/types.d.ts +1 -1
- package/build/types.d.ts.map +1 -1
- package/build/types.js +2 -0
- package/build/types.js.map +1 -0
- package/build/useDeprecated.d.ts +3 -0
- package/build/useDeprecated.d.ts.map +1 -0
- package/build/useDeprecated.js +23 -0
- package/build/useDeprecated.js.map +1 -0
- package/build/useFocusEffect.d.ts.map +1 -1
- package/build/useFocusEffect.js +98 -0
- package/build/useFocusEffect.js.map +1 -0
- package/build/useNavigation.d.ts +1 -1
- package/build/useNavigation.d.ts.map +1 -1
- package/build/useNavigation.js +63 -0
- package/build/useNavigation.js.map +1 -0
- package/build/useScreens.d.ts +4 -4
- package/build/useScreens.d.ts.map +1 -1
- package/build/useScreens.js +183 -0
- package/build/useScreens.js.map +1 -0
- package/build/utils/mockState.d.ts +1 -1
- package/build/utils/mockState.d.ts.map +1 -1
- package/build/utils/mockState.js +24 -0
- package/build/utils/mockState.js.map +1 -0
- package/{src/utils/url.ts → build/utils/url.js} +3 -2
- package/build/utils/url.js.map +1 -0
- package/build/views/EmptyRoute.js +9 -0
- package/build/views/EmptyRoute.js.map +1 -0
- package/build/views/ErrorBoundary.d.ts +1 -1
- package/build/views/ErrorBoundary.d.ts.map +1 -1
- package/build/views/ErrorBoundary.js +124 -0
- package/build/views/ErrorBoundary.js.map +1 -0
- package/build/views/Navigator.d.ts +11 -11
- package/build/views/Navigator.d.ts.map +1 -1
- package/build/views/Navigator.js +87 -0
- package/build/views/Navigator.js.map +1 -0
- package/build/views/Screen.d.ts.map +1 -1
- package/build/views/Screen.js +30 -0
- package/build/views/Screen.js.map +1 -0
- package/build/views/Sitemap.d.ts +1 -1
- package/build/views/Sitemap.d.ts.map +1 -1
- package/build/views/Sitemap.js +156 -0
- package/build/views/Sitemap.js.map +1 -0
- package/build/views/Splash.d.ts.map +1 -1
- package/build/views/Splash.js +109 -0
- package/build/views/Splash.js.map +1 -0
- package/build/views/SuspenseFallback.d.ts +1 -1
- package/build/views/SuspenseFallback.js +7 -0
- package/build/views/SuspenseFallback.js.map +1 -0
- package/build/views/Toast.d.ts +1 -1
- package/build/views/Toast.d.ts.map +1 -1
- package/build/views/Toast.js +73 -0
- package/build/views/Toast.js.map +1 -0
- package/build/views/Try.d.ts +1 -1
- package/build/views/Try.js +27 -0
- package/build/views/Try.js.map +1 -0
- package/build/views/Unmatched.d.ts.map +1 -1
- package/build/views/Unmatched.js +72 -0
- package/build/views/Unmatched.js.map +1 -0
- package/drawer.d.ts +2 -0
- package/drawer.js +1 -0
- package/entry.js +4 -5
- package/expo-module.config.json +8 -0
- package/head.d.ts +1 -0
- package/head.js +1 -0
- package/html.js +1 -0
- package/ios/ExpoHead.podspec +32 -0
- package/ios/ExpoHeadAppDelegateSubscriber.swift +94 -0
- package/ios/ExpoHeadModule.swift +186 -0
- package/node/getExpoConstantsManifest.js +22 -38
- package/node/render.js +1 -1
- package/package.json +42 -39
- package/plugin/build/index.d.ts +1 -1
- package/plugin/build/index.js +4 -2
- package/plugin/jest.config.js +1 -0
- package/stack.d.ts +2 -0
- package/stack.js +1 -0
- package/tabs.d.ts +2 -0
- package/tabs.js +1 -0
- package/testing-library.d.ts +1 -0
- package/testing-library.js +1 -0
- package/types/expect.d.ts +1 -1
- package/types/global.d.ts +7 -7
- package/types/metro-require.d.ts +1 -1
- package/types/react-native-web.d.ts +16 -20
- package/_ctx.tsx +0 -5
- package/_entry.tsx +0 -33
- package/_html-ctx.tsx +0 -9
- package/drawer.ts +0 -2
- package/head.ts +0 -6
- package/html.ts +0 -1
- package/plugin/src/index.ts +0 -54
- package/src/ExpoRoot.tsx +0 -116
- package/src/LocationProvider.tsx +0 -52
- package/src/Route.tsx +0 -120
- package/src/exports.ts +0 -34
- package/src/fork/NavigationContainer.native.tsx +0 -159
- package/src/fork/NavigationContainer.tsx +0 -4
- package/src/fork/expo/createRoot.tsx +0 -1
- package/src/fork/expo/registerRootComponent.tsx +0 -77
- package/src/fork/extractPathFromURL.ts +0 -103
- package/src/fork/findFocusedRoute.tsx +0 -15
- package/src/fork/getPathFromState.ts +0 -647
- package/src/fork/getStateFromPath.ts +0 -776
- package/src/fork/useLinking.native.ts +0 -224
- package/src/fork/useLinking.ts +0 -4
- package/src/fork/validatePathConfig.ts +0 -32
- package/src/getDevServer/index.native.ts +0 -1
- package/src/getDevServer/index.ts +0 -37
- package/src/getLinkingConfig.ts +0 -69
- package/src/getReactNavigationConfig.ts +0 -103
- package/src/getRoutes.ts +0 -520
- package/src/global-state/router-store.tsx +0 -256
- package/src/global-state/routing.ts +0 -213
- package/src/global-state/sort-routes.ts +0 -12
- package/src/imperative-api.ts +0 -10
- package/src/import-mode/index.ts +0 -1
- package/src/index.tsx +0 -3
- package/src/layouts/Drawer.tsx +0 -15
- package/src/layouts/Stack.tsx +0 -15
- package/src/layouts/Tabs.tsx +0 -61
- package/src/layouts/withLayoutContext.tsx +0 -114
- package/src/link/Link.tsx +0 -104
- package/src/link/href.ts +0 -60
- package/src/link/linking.ts +0 -106
- package/src/link/path.ts +0 -141
- package/src/link/stateOperations.ts +0 -152
- package/src/link/useLinkToPathProps.tsx +0 -60
- package/src/link/useLoadedNavigation.ts +0 -60
- package/src/loadStaticParamsAsync.ts +0 -196
- package/src/matchers.tsx +0 -56
- package/src/onboard/Tutorial.tsx +0 -202
- package/src/primitives.tsx +0 -5
- package/src/renderRootComponent.tsx +0 -87
- package/src/static/getRootComponent.ts +0 -28
- package/src/static/html.tsx +0 -38
- package/src/static/renderStaticContent.tsx +0 -103
- package/src/testing-library/context-stubs.ts +0 -52
- package/src/testing-library/expect.ts +0 -15
- package/src/testing-library/index.tsx +0 -103
- package/src/testing-library/mocks.ts +0 -39
- package/src/testing-library/require-context-ponyfill.ts +0 -44
- package/src/ts-declarations.d.ts +0 -1
- package/src/types.ts +0 -30
- package/src/useFocusEffect.tsx +0 -121
- package/src/useNavigation.ts +0 -84
- package/src/useScreens.tsx +0 -297
- package/src/utils/mockState.ts +0 -31
- package/src/views/EmptyRoute.tsx +0 -16
- package/src/views/ErrorBoundary.tsx +0 -175
- package/src/views/Navigator.tsx +0 -164
- package/src/views/Screen.tsx +0 -51
- package/src/views/Sitemap.tsx +0 -270
- package/src/views/Splash.tsx +0 -125
- package/src/views/SuspenseFallback.tsx +0 -12
- package/src/views/Toast.tsx +0 -102
- package/src/views/Try.tsx +0 -46
- package/src/views/Unmatched.tsx +0 -105
- package/stack.ts +0 -2
- package/tabs.ts +0 -2
|
@@ -0,0 +1,419 @@
|
|
|
1
|
+
import { validatePathConfig } from '@react-navigation/core';
|
|
2
|
+
import * as queryString from 'query-string';
|
|
3
|
+
import { matchDeepDynamicRouteName, matchDynamicName, matchGroupName } from '../matchers';
|
|
4
|
+
const DEFAULT_SCREENS = {};
|
|
5
|
+
const getActiveRoute = (state) => {
|
|
6
|
+
const route = typeof state.index === 'number'
|
|
7
|
+
? state.routes[state.index]
|
|
8
|
+
: state.routes[state.routes.length - 1];
|
|
9
|
+
if (route.state) {
|
|
10
|
+
return getActiveRoute(route.state);
|
|
11
|
+
}
|
|
12
|
+
if (route && isInvalidParams(route.params)) {
|
|
13
|
+
return getActiveRoute(createFakeState(route.params));
|
|
14
|
+
}
|
|
15
|
+
return route;
|
|
16
|
+
};
|
|
17
|
+
function createFakeState(params) {
|
|
18
|
+
return {
|
|
19
|
+
stale: false,
|
|
20
|
+
type: 'UNKNOWN',
|
|
21
|
+
key: 'UNKNOWN',
|
|
22
|
+
index: 0,
|
|
23
|
+
routeNames: [],
|
|
24
|
+
routes: [
|
|
25
|
+
{
|
|
26
|
+
key: 'UNKNOWN',
|
|
27
|
+
name: params.screen,
|
|
28
|
+
params: params.params,
|
|
29
|
+
path: params.path,
|
|
30
|
+
},
|
|
31
|
+
],
|
|
32
|
+
};
|
|
33
|
+
}
|
|
34
|
+
function segmentMatchesConvention(segment) {
|
|
35
|
+
return (segment === 'index' ||
|
|
36
|
+
matchDynamicName(segment) != null ||
|
|
37
|
+
matchGroupName(segment) != null ||
|
|
38
|
+
matchDeepDynamicRouteName(segment) != null);
|
|
39
|
+
}
|
|
40
|
+
function encodeURIComponentPreservingBrackets(str) {
|
|
41
|
+
return encodeURIComponent(str).replace(/%5B/g, '[').replace(/%5D/g, ']');
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Utility to serialize a navigation state object to a path string.
|
|
45
|
+
*
|
|
46
|
+
* @example
|
|
47
|
+
* ```js
|
|
48
|
+
* getPathFromState(
|
|
49
|
+
* {
|
|
50
|
+
* routes: [
|
|
51
|
+
* {
|
|
52
|
+
* name: 'Chat',
|
|
53
|
+
* params: { author: 'Jane', id: 42 },
|
|
54
|
+
* },
|
|
55
|
+
* ],
|
|
56
|
+
* },
|
|
57
|
+
* {
|
|
58
|
+
* screens: {
|
|
59
|
+
* Chat: {
|
|
60
|
+
* path: 'chat/:author/:id',
|
|
61
|
+
* stringify: { author: author => author.toLowerCase() }
|
|
62
|
+
* }
|
|
63
|
+
* }
|
|
64
|
+
* }
|
|
65
|
+
* )
|
|
66
|
+
* ```
|
|
67
|
+
*
|
|
68
|
+
* @param state Navigation state to serialize.
|
|
69
|
+
* @param options Extra options to fine-tune how to serialize the path.
|
|
70
|
+
* @returns Path representing the state, e.g. /foo/bar?count=42.
|
|
71
|
+
*/
|
|
72
|
+
export default function getPathFromState(state, _options) {
|
|
73
|
+
return getPathDataFromState(state, _options).path;
|
|
74
|
+
}
|
|
75
|
+
export function getPathDataFromState(state, _options = { screens: DEFAULT_SCREENS }) {
|
|
76
|
+
if (state == null) {
|
|
77
|
+
throw Error("Got 'undefined' for the navigation state. You must pass a valid state object.");
|
|
78
|
+
}
|
|
79
|
+
const { preserveGroups, preserveDynamicRoutes, ...options } = _options;
|
|
80
|
+
validatePathConfig(options);
|
|
81
|
+
// Expo Router disallows usage without a linking config.
|
|
82
|
+
if (Object.is(options.screens, DEFAULT_SCREENS)) {
|
|
83
|
+
throw Error("You must pass a 'screens' object to 'getPathFromState' to generate a path.");
|
|
84
|
+
}
|
|
85
|
+
return getPathFromResolvedState(state,
|
|
86
|
+
// Create a normalized configs object which will be easier to use
|
|
87
|
+
createNormalizedConfigs(options.screens), { preserveGroups, preserveDynamicRoutes });
|
|
88
|
+
}
|
|
89
|
+
function processParamsWithUserSettings(configItem, params) {
|
|
90
|
+
const stringify = configItem?.stringify;
|
|
91
|
+
return Object.fromEntries(Object.entries(params).map(([key, value]) => [
|
|
92
|
+
key,
|
|
93
|
+
// TODO: Strip nullish values here.
|
|
94
|
+
stringify?.[key]
|
|
95
|
+
? stringify[key](value)
|
|
96
|
+
: // Preserve rest params
|
|
97
|
+
Array.isArray(value)
|
|
98
|
+
? value
|
|
99
|
+
: String(value),
|
|
100
|
+
]));
|
|
101
|
+
}
|
|
102
|
+
export function deepEqual(a, b) {
|
|
103
|
+
if (a === b) {
|
|
104
|
+
return true;
|
|
105
|
+
}
|
|
106
|
+
if (Array.isArray(a) && Array.isArray(b)) {
|
|
107
|
+
if (a.length !== b.length) {
|
|
108
|
+
return false;
|
|
109
|
+
}
|
|
110
|
+
for (let i = 0; i < a.length; i++) {
|
|
111
|
+
if (!deepEqual(a[i], b[i])) {
|
|
112
|
+
return false;
|
|
113
|
+
}
|
|
114
|
+
}
|
|
115
|
+
return true;
|
|
116
|
+
}
|
|
117
|
+
if (typeof a === 'object' && typeof b === 'object') {
|
|
118
|
+
const keysA = Object.keys(a);
|
|
119
|
+
const keysB = Object.keys(b);
|
|
120
|
+
if (keysA.length !== keysB.length) {
|
|
121
|
+
return false;
|
|
122
|
+
}
|
|
123
|
+
for (const key of keysA) {
|
|
124
|
+
if (!deepEqual(a[key], b[key])) {
|
|
125
|
+
return false;
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
return true;
|
|
129
|
+
}
|
|
130
|
+
return false;
|
|
131
|
+
}
|
|
132
|
+
function walkConfigItems(route, focusedRoute, configs, { preserveDynamicRoutes, }) {
|
|
133
|
+
// NOTE(EvanBacon): Fill in current route using state that was passed as params.
|
|
134
|
+
if (!route.state && isInvalidParams(route.params)) {
|
|
135
|
+
route.state = createFakeState(route.params);
|
|
136
|
+
}
|
|
137
|
+
let pattern = null;
|
|
138
|
+
let focusedParams;
|
|
139
|
+
const collectedParams = {};
|
|
140
|
+
while (route.name in configs) {
|
|
141
|
+
const configItem = configs[route.name];
|
|
142
|
+
const inputPattern = configItem.pattern;
|
|
143
|
+
if (inputPattern == null) {
|
|
144
|
+
// This should never happen in Expo Router.
|
|
145
|
+
throw new Error('Unexpected: No pattern found for route ' + route.name);
|
|
146
|
+
}
|
|
147
|
+
pattern = inputPattern;
|
|
148
|
+
if (route.params) {
|
|
149
|
+
const params = processParamsWithUserSettings(configItem, route.params);
|
|
150
|
+
// TODO: Does this need to be a null check?
|
|
151
|
+
if (pattern) {
|
|
152
|
+
Object.assign(collectedParams, params);
|
|
153
|
+
}
|
|
154
|
+
if (deepEqual(focusedRoute, route)) {
|
|
155
|
+
if (preserveDynamicRoutes) {
|
|
156
|
+
focusedParams = params;
|
|
157
|
+
}
|
|
158
|
+
else {
|
|
159
|
+
// If this is the focused route, keep the params for later use
|
|
160
|
+
// We save it here since it's been stringified already
|
|
161
|
+
focusedParams = getParamsWithConventionsCollapsed({
|
|
162
|
+
params,
|
|
163
|
+
pattern,
|
|
164
|
+
routeName: route.name,
|
|
165
|
+
});
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
if (!route.state && isInvalidParams(route.params)) {
|
|
170
|
+
route.state = createFakeState(route.params);
|
|
171
|
+
}
|
|
172
|
+
// If there is no `screens` property or no nested state, we return pattern
|
|
173
|
+
if (!configItem.screens || route.state === undefined) {
|
|
174
|
+
if (configItem.initialRouteName &&
|
|
175
|
+
configItem.screens &&
|
|
176
|
+
configItem.initialRouteName in configItem.screens &&
|
|
177
|
+
configItem.screens[configItem.initialRouteName]?.pattern) {
|
|
178
|
+
const initialRouteConfig = configItem.screens[configItem.initialRouteName];
|
|
179
|
+
// NOTE(EvanBacon): Big hack to support initial route changes in tab bars.
|
|
180
|
+
pattern = initialRouteConfig.pattern;
|
|
181
|
+
if (focusedParams) {
|
|
182
|
+
if (!preserveDynamicRoutes) {
|
|
183
|
+
// If this is the focused route, keep the params for later use
|
|
184
|
+
// We save it here since it's been stringified already
|
|
185
|
+
focusedParams = getParamsWithConventionsCollapsed({
|
|
186
|
+
params: focusedParams,
|
|
187
|
+
pattern,
|
|
188
|
+
routeName: route.name,
|
|
189
|
+
});
|
|
190
|
+
}
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
break;
|
|
194
|
+
}
|
|
195
|
+
const index = route.state.index ?? route.state.routes.length - 1;
|
|
196
|
+
const nextRoute = route.state.routes[index];
|
|
197
|
+
const nestedScreens = configItem.screens;
|
|
198
|
+
// if there is config for next route name, we go deeper
|
|
199
|
+
if (nestedScreens && nextRoute.name in nestedScreens) {
|
|
200
|
+
route = nextRoute;
|
|
201
|
+
configs = nestedScreens;
|
|
202
|
+
}
|
|
203
|
+
else {
|
|
204
|
+
// If not, there is no sense in going deeper in config
|
|
205
|
+
break;
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
if (pattern == null) {
|
|
209
|
+
throw new Error(`No pattern found for route "${route.name}". Options are: ${Object.keys(configs).join(', ')}.`);
|
|
210
|
+
}
|
|
211
|
+
if (pattern && !focusedParams && focusedRoute.params) {
|
|
212
|
+
if (preserveDynamicRoutes) {
|
|
213
|
+
focusedParams = focusedRoute.params;
|
|
214
|
+
}
|
|
215
|
+
else {
|
|
216
|
+
// If this is the focused route, keep the params for later use
|
|
217
|
+
// We save it here since it's been stringified already
|
|
218
|
+
focusedParams = getParamsWithConventionsCollapsed({
|
|
219
|
+
params: focusedRoute.params,
|
|
220
|
+
pattern,
|
|
221
|
+
routeName: route.name,
|
|
222
|
+
});
|
|
223
|
+
}
|
|
224
|
+
Object.assign(focusedParams, collectedParams);
|
|
225
|
+
}
|
|
226
|
+
return {
|
|
227
|
+
pattern,
|
|
228
|
+
nextRoute: route,
|
|
229
|
+
focusedParams,
|
|
230
|
+
params: collectedParams,
|
|
231
|
+
};
|
|
232
|
+
}
|
|
233
|
+
function getPathFromResolvedState(state, configs, { preserveGroups, preserveDynamicRoutes, }) {
|
|
234
|
+
let path = '';
|
|
235
|
+
let current = state;
|
|
236
|
+
const allParams = {};
|
|
237
|
+
while (current) {
|
|
238
|
+
path += '/';
|
|
239
|
+
const route = current.routes[current.index ?? 0];
|
|
240
|
+
// NOTE(EvanBacon): Fill in current route using state that was passed as params.
|
|
241
|
+
// if (isInvalidParams(route.params)) {
|
|
242
|
+
if (!route.state && isInvalidParams(route.params)) {
|
|
243
|
+
route.state = createFakeState(route.params);
|
|
244
|
+
}
|
|
245
|
+
const { pattern, params, nextRoute, focusedParams } = walkConfigItems(route, getActiveRoute(current), { ...configs }, { preserveDynamicRoutes });
|
|
246
|
+
Object.assign(allParams, params);
|
|
247
|
+
path += getPathWithConventionsCollapsed({
|
|
248
|
+
pattern,
|
|
249
|
+
routePath: nextRoute.path,
|
|
250
|
+
params: allParams,
|
|
251
|
+
initialRouteName: configs[nextRoute.name]?.initialRouteName,
|
|
252
|
+
preserveGroups,
|
|
253
|
+
preserveDynamicRoutes,
|
|
254
|
+
});
|
|
255
|
+
if (nextRoute.state &&
|
|
256
|
+
// NOTE(EvanBacon): The upstream implementation allows for sending in synthetic states (states that weren't generated by `getStateFromPath`)
|
|
257
|
+
// and any invalid routes will simply be ignored.
|
|
258
|
+
// Because of this, we need to check if the next route is valid before continuing, otherwise our more strict
|
|
259
|
+
// implementation will throw an error.
|
|
260
|
+
configs[nextRoute.state.routes?.[nextRoute.state?.index ?? 0]?.name]) {
|
|
261
|
+
// Continue looping with the next state if available.
|
|
262
|
+
current = nextRoute.state;
|
|
263
|
+
}
|
|
264
|
+
else {
|
|
265
|
+
// Finished crawling state.
|
|
266
|
+
// Check for query params before exiting.
|
|
267
|
+
if (focusedParams) {
|
|
268
|
+
for (const param in focusedParams) {
|
|
269
|
+
// TODO: This is not good. We shouldn't squat strings named "undefined".
|
|
270
|
+
if (focusedParams[param] === 'undefined') {
|
|
271
|
+
// eslint-disable-next-line @typescript-eslint/no-dynamic-delete
|
|
272
|
+
delete focusedParams[param];
|
|
273
|
+
}
|
|
274
|
+
}
|
|
275
|
+
const query = queryString.stringify(focusedParams, { sort: false });
|
|
276
|
+
if (query) {
|
|
277
|
+
path += `?${query}`;
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
break;
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
return { path: basicSanitizePath(path), params: decodeParams(allParams) };
|
|
284
|
+
}
|
|
285
|
+
function decodeParams(params) {
|
|
286
|
+
const parsed = {};
|
|
287
|
+
for (const [key, value] of Object.entries(params)) {
|
|
288
|
+
parsed[key] = decodeURIComponent(value);
|
|
289
|
+
}
|
|
290
|
+
return parsed;
|
|
291
|
+
}
|
|
292
|
+
function getPathWithConventionsCollapsed({ pattern, routePath, params, preserveGroups, preserveDynamicRoutes, initialRouteName, }) {
|
|
293
|
+
const segments = pattern.split('/');
|
|
294
|
+
return segments
|
|
295
|
+
.map((p, i) => {
|
|
296
|
+
const name = getParamName(p);
|
|
297
|
+
// We don't know what to show for wildcard patterns
|
|
298
|
+
// Showing the route name seems ok, though whatever we show here will be incorrect
|
|
299
|
+
// Since the page doesn't actually exist
|
|
300
|
+
if (p.startsWith('*')) {
|
|
301
|
+
if (preserveDynamicRoutes) {
|
|
302
|
+
return `[...${name}]`;
|
|
303
|
+
}
|
|
304
|
+
if (params[name]) {
|
|
305
|
+
return params[name].join('/');
|
|
306
|
+
}
|
|
307
|
+
if (i === 0) {
|
|
308
|
+
// This can occur when a wildcard matches all routes and the given path was `/`.
|
|
309
|
+
return routePath;
|
|
310
|
+
}
|
|
311
|
+
// remove existing segments from route.path and return it
|
|
312
|
+
// this is used for nested wildcard routes. Without this, the path would add
|
|
313
|
+
// all nested segments to the beginning of the wildcard route.
|
|
314
|
+
return routePath
|
|
315
|
+
?.split('/')
|
|
316
|
+
.slice(i + 1)
|
|
317
|
+
.join('/');
|
|
318
|
+
}
|
|
319
|
+
// If the path has a pattern for a param, put the param in the path
|
|
320
|
+
if (p.startsWith(':')) {
|
|
321
|
+
if (preserveDynamicRoutes) {
|
|
322
|
+
return `[${name}]`;
|
|
323
|
+
}
|
|
324
|
+
// Optional params without value assigned in route.params should be ignored
|
|
325
|
+
return params[name];
|
|
326
|
+
}
|
|
327
|
+
if (!preserveGroups && matchGroupName(p) != null) {
|
|
328
|
+
// When the last part is a group it could be a shared URL
|
|
329
|
+
// if the route has an initialRouteName defined, then we should
|
|
330
|
+
// use that as the component path as we can assume it will be shown.
|
|
331
|
+
if (segments.length - 1 === i) {
|
|
332
|
+
if (initialRouteName) {
|
|
333
|
+
// Return an empty string if the init route is ambiguous.
|
|
334
|
+
if (segmentMatchesConvention(initialRouteName)) {
|
|
335
|
+
return '';
|
|
336
|
+
}
|
|
337
|
+
return encodeURIComponentPreservingBrackets(initialRouteName);
|
|
338
|
+
}
|
|
339
|
+
}
|
|
340
|
+
return '';
|
|
341
|
+
}
|
|
342
|
+
// Preserve dynamic syntax for rehydration
|
|
343
|
+
return encodeURIComponentPreservingBrackets(p);
|
|
344
|
+
})
|
|
345
|
+
.map((v) => v ?? '')
|
|
346
|
+
.join('/');
|
|
347
|
+
}
|
|
348
|
+
/** Given a set of query params and a pattern with possible conventions, collapse the conventions and return the remaining params. */
|
|
349
|
+
function getParamsWithConventionsCollapsed({ pattern, routeName, params, }) {
|
|
350
|
+
const processedParams = { ...params };
|
|
351
|
+
// Remove the params present in the pattern since we'll only use the rest for query string
|
|
352
|
+
const segments = pattern.split('/');
|
|
353
|
+
// Dynamic Routes
|
|
354
|
+
segments
|
|
355
|
+
.filter((segment) => segment.startsWith(':'))
|
|
356
|
+
.forEach((segment) => {
|
|
357
|
+
const name = getParamName(segment);
|
|
358
|
+
delete processedParams[name];
|
|
359
|
+
});
|
|
360
|
+
// Deep Dynamic Routes
|
|
361
|
+
if (segments.some((segment) => segment.startsWith('*'))) {
|
|
362
|
+
// NOTE(EvanBacon): Drop the param name matching the wildcard route name -- this is specific to Expo Router.
|
|
363
|
+
const name = matchDeepDynamicRouteName(routeName) ?? routeName;
|
|
364
|
+
delete processedParams[name];
|
|
365
|
+
}
|
|
366
|
+
return processedParams;
|
|
367
|
+
}
|
|
368
|
+
// Remove multiple as well as trailing slashes
|
|
369
|
+
function basicSanitizePath(path) {
|
|
370
|
+
// Remove duplicate slashes like `foo//bar` -> `foo/bar`
|
|
371
|
+
const simplifiedPath = path.replace(/\/+/g, '/');
|
|
372
|
+
if (simplifiedPath.length <= 1) {
|
|
373
|
+
return simplifiedPath;
|
|
374
|
+
}
|
|
375
|
+
// Remove trailing slash like `foo/bar/` -> `foo/bar`
|
|
376
|
+
return simplifiedPath.replace(/\/$/, '');
|
|
377
|
+
}
|
|
378
|
+
// TODO: Make StackRouter not do this...
|
|
379
|
+
// Detect if the params came from StackRouter using `params` to pass around internal state.
|
|
380
|
+
function isInvalidParams(params) {
|
|
381
|
+
if (!params) {
|
|
382
|
+
return false;
|
|
383
|
+
}
|
|
384
|
+
if ('params' in params && typeof params.params === 'object' && !!params.params) {
|
|
385
|
+
return true;
|
|
386
|
+
}
|
|
387
|
+
return ('initial' in params &&
|
|
388
|
+
typeof params.initial === 'boolean' &&
|
|
389
|
+
// "path" in params &&
|
|
390
|
+
'screen' in params);
|
|
391
|
+
}
|
|
392
|
+
const getParamName = (pattern) => pattern.replace(/^[:*]/, '').replace(/\?$/, '');
|
|
393
|
+
const joinPaths = (...paths) => []
|
|
394
|
+
.concat(...paths.map((p) => p.split('/')))
|
|
395
|
+
.filter(Boolean)
|
|
396
|
+
.join('/');
|
|
397
|
+
const createConfigItem = (config, parentPattern) => {
|
|
398
|
+
if (typeof config === 'string') {
|
|
399
|
+
// If a string is specified as the value of the key(e.g. Foo: '/path'), use it as the pattern
|
|
400
|
+
const pattern = parentPattern ? joinPaths(parentPattern, config) : config;
|
|
401
|
+
return { pattern };
|
|
402
|
+
}
|
|
403
|
+
if (config.exact && config.path === undefined) {
|
|
404
|
+
throw new Error("A 'path' needs to be specified when specifying 'exact: true'. If you don't want this screen in the URL, specify it as empty string, e.g. `path: ''`.");
|
|
405
|
+
}
|
|
406
|
+
// If an object is specified as the value (e.g. Foo: { ... }),
|
|
407
|
+
// It can have `path` property and `screens` prop which has nested configs
|
|
408
|
+
const pattern = config.exact !== true ? joinPaths(parentPattern || '', config.path || '') : config.path || '';
|
|
409
|
+
const screens = config.screens ? createNormalizedConfigs(config.screens, pattern) : undefined;
|
|
410
|
+
return {
|
|
411
|
+
// Normalize pattern to remove any leading, trailing slashes, duplicate slashes etc.
|
|
412
|
+
pattern: pattern?.split('/').filter(Boolean).join('/'),
|
|
413
|
+
stringify: config.stringify,
|
|
414
|
+
screens,
|
|
415
|
+
initialRouteName: config.initialRouteName,
|
|
416
|
+
};
|
|
417
|
+
};
|
|
418
|
+
const createNormalizedConfigs = (options, pattern) => Object.fromEntries(Object.entries(options).map(([name, c]) => [name, createConfigItem(c, pattern)]));
|
|
419
|
+
//# sourceMappingURL=getPathFromState.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"getPathFromState.js","sourceRoot":"","sources":["../../src/fork/getPathFromState.ts"],"names":[],"mappings":"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","sourcesContent":["import { PathConfig, PathConfigMap, validatePathConfig } from '@react-navigation/core';\nimport type { NavigationState, PartialState, Route } from '@react-navigation/routers';\nimport * as queryString from 'query-string';\n\nimport { matchDeepDynamicRouteName, matchDynamicName, matchGroupName } from '../matchers';\n\ntype Options<ParamList extends object> = {\n initialRouteName?: string;\n screens: PathConfigMap<ParamList>;\n};\n\nexport type State = NavigationState | Omit<PartialState<NavigationState>, 'stale'>;\n\ntype StringifyConfig = Record<string, (value: any) => string>;\n\ntype ConfigItem = {\n pattern?: string;\n stringify?: StringifyConfig;\n screens?: Record<string, ConfigItem>;\n // Used as fallback for groups\n initialRouteName?: string;\n};\n\ntype CustomRoute = Route<string> & {\n state?: State;\n};\n\nconst DEFAULT_SCREENS: PathConfigMap<object> = {};\n\nconst getActiveRoute = (state: State): { name: string; params?: object } => {\n const route =\n typeof state.index === 'number'\n ? state.routes[state.index]\n : state.routes[state.routes.length - 1];\n\n if (route.state) {\n return getActiveRoute(route.state);\n }\n\n if (route && isInvalidParams(route.params)) {\n return getActiveRoute(createFakeState(route.params));\n }\n\n return route;\n};\n\nfunction createFakeState(params: StateAsParams) {\n return {\n stale: false,\n type: 'UNKNOWN',\n key: 'UNKNOWN',\n index: 0,\n routeNames: [],\n routes: [\n {\n key: 'UNKNOWN',\n name: params.screen,\n params: params.params,\n path: params.path,\n },\n ],\n };\n}\n\nfunction segmentMatchesConvention(segment: string): boolean {\n return (\n segment === 'index' ||\n matchDynamicName(segment) != null ||\n matchGroupName(segment) != null ||\n matchDeepDynamicRouteName(segment) != null\n );\n}\n\nfunction encodeURIComponentPreservingBrackets(str: string) {\n return encodeURIComponent(str).replace(/%5B/g, '[').replace(/%5D/g, ']');\n}\n\n/**\n * Utility to serialize a navigation state object to a path string.\n *\n * @example\n * ```js\n * getPathFromState(\n * {\n * routes: [\n * {\n * name: 'Chat',\n * params: { author: 'Jane', id: 42 },\n * },\n * ],\n * },\n * {\n * screens: {\n * Chat: {\n * path: 'chat/:author/:id',\n * stringify: { author: author => author.toLowerCase() }\n * }\n * }\n * }\n * )\n * ```\n *\n * @param state Navigation state to serialize.\n * @param options Extra options to fine-tune how to serialize the path.\n * @returns Path representing the state, e.g. /foo/bar?count=42.\n */\nexport default function getPathFromState<ParamList extends object>(\n state: State,\n _options?: Options<ParamList> & {\n preserveGroups?: boolean;\n preserveDynamicRoutes?: boolean;\n }\n): string {\n return getPathDataFromState(state, _options).path;\n}\n\nexport function getPathDataFromState<ParamList extends object>(\n state: State,\n _options: Options<ParamList> & {\n preserveGroups?: boolean;\n preserveDynamicRoutes?: boolean;\n } = { screens: DEFAULT_SCREENS }\n) {\n if (state == null) {\n throw Error(\"Got 'undefined' for the navigation state. You must pass a valid state object.\");\n }\n\n const { preserveGroups, preserveDynamicRoutes, ...options } = _options;\n\n validatePathConfig(options);\n\n // Expo Router disallows usage without a linking config.\n if (Object.is(options.screens, DEFAULT_SCREENS)) {\n throw Error(\"You must pass a 'screens' object to 'getPathFromState' to generate a path.\");\n }\n\n return getPathFromResolvedState(\n state,\n // Create a normalized configs object which will be easier to use\n createNormalizedConfigs(options.screens),\n { preserveGroups, preserveDynamicRoutes }\n );\n}\n\nfunction processParamsWithUserSettings(configItem: ConfigItem, params: Record<string, any>) {\n const stringify = configItem?.stringify;\n\n return Object.fromEntries(\n Object.entries(params).map(([key, value]) => [\n key,\n // TODO: Strip nullish values here.\n stringify?.[key]\n ? stringify[key](value)\n : // Preserve rest params\n Array.isArray(value)\n ? value\n : String(value),\n ])\n );\n}\n\nexport function deepEqual(a: any, b: any) {\n if (a === b) {\n return true;\n }\n\n if (Array.isArray(a) && Array.isArray(b)) {\n if (a.length !== b.length) {\n return false;\n }\n\n for (let i = 0; i < a.length; i++) {\n if (!deepEqual(a[i], b[i])) {\n return false;\n }\n }\n\n return true;\n }\n\n if (typeof a === 'object' && typeof b === 'object') {\n const keysA = Object.keys(a);\n const keysB = Object.keys(b);\n\n if (keysA.length !== keysB.length) {\n return false;\n }\n\n for (const key of keysA) {\n if (!deepEqual(a[key], b[key])) {\n return false;\n }\n }\n\n return true;\n }\n\n return false;\n}\n\nfunction walkConfigItems(\n route: CustomRoute,\n focusedRoute: {\n name: string;\n params?: object;\n },\n configs: Record<string, ConfigItem>,\n {\n preserveDynamicRoutes,\n }: {\n preserveDynamicRoutes?: boolean;\n }\n) {\n // NOTE(EvanBacon): Fill in current route using state that was passed as params.\n if (!route.state && isInvalidParams(route.params)) {\n route.state = createFakeState(route.params);\n }\n\n let pattern: string | null = null;\n let focusedParams: Record<string, any> | undefined;\n\n const collectedParams: Record<string, any> = {};\n\n while (route.name in configs) {\n const configItem = configs[route.name];\n const inputPattern = configItem.pattern;\n\n if (inputPattern == null) {\n // This should never happen in Expo Router.\n throw new Error('Unexpected: No pattern found for route ' + route.name);\n }\n pattern = inputPattern;\n\n if (route.params) {\n const params = processParamsWithUserSettings(configItem, route.params);\n // TODO: Does this need to be a null check?\n if (pattern) {\n Object.assign(collectedParams, params);\n }\n if (deepEqual(focusedRoute, route)) {\n if (preserveDynamicRoutes) {\n focusedParams = params;\n } else {\n // If this is the focused route, keep the params for later use\n // We save it here since it's been stringified already\n focusedParams = getParamsWithConventionsCollapsed({\n params,\n pattern,\n routeName: route.name,\n });\n }\n }\n }\n\n if (!route.state && isInvalidParams(route.params)) {\n route.state = createFakeState(route.params);\n }\n\n // If there is no `screens` property or no nested state, we return pattern\n if (!configItem.screens || route.state === undefined) {\n if (\n configItem.initialRouteName &&\n configItem.screens &&\n configItem.initialRouteName in configItem.screens &&\n configItem.screens[configItem.initialRouteName]?.pattern\n ) {\n const initialRouteConfig = configItem.screens[configItem.initialRouteName];\n\n // NOTE(EvanBacon): Big hack to support initial route changes in tab bars.\n pattern = initialRouteConfig.pattern!;\n if (focusedParams) {\n if (!preserveDynamicRoutes) {\n // If this is the focused route, keep the params for later use\n // We save it here since it's been stringified already\n focusedParams = getParamsWithConventionsCollapsed({\n params: focusedParams,\n pattern,\n routeName: route.name,\n });\n }\n }\n }\n break;\n }\n\n const index = route.state.index ?? route.state.routes.length - 1;\n\n const nextRoute = route.state.routes[index];\n const nestedScreens = configItem.screens;\n\n // if there is config for next route name, we go deeper\n if (nestedScreens && nextRoute.name in nestedScreens) {\n route = nextRoute as CustomRoute;\n configs = nestedScreens;\n } else {\n // If not, there is no sense in going deeper in config\n break;\n }\n }\n\n if (pattern == null) {\n throw new Error(\n `No pattern found for route \"${route.name}\". Options are: ${Object.keys(configs).join(', ')}.`\n );\n }\n\n if (pattern && !focusedParams && focusedRoute.params) {\n if (preserveDynamicRoutes) {\n focusedParams = focusedRoute.params;\n } else {\n // If this is the focused route, keep the params for later use\n // We save it here since it's been stringified already\n focusedParams = getParamsWithConventionsCollapsed({\n params: focusedRoute.params,\n pattern,\n routeName: route.name,\n });\n }\n Object.assign(focusedParams, collectedParams);\n }\n\n return {\n pattern,\n nextRoute: route,\n focusedParams,\n params: collectedParams,\n };\n}\n\nfunction getPathFromResolvedState(\n state: State,\n configs: Record<string, ConfigItem>,\n {\n preserveGroups,\n preserveDynamicRoutes,\n }: { preserveGroups?: boolean; preserveDynamicRoutes?: boolean }\n) {\n let path = '';\n let current: State = state;\n\n const allParams: Record<string, any> = {};\n\n while (current) {\n path += '/';\n\n const route = current.routes[current.index ?? 0] as CustomRoute;\n // NOTE(EvanBacon): Fill in current route using state that was passed as params.\n // if (isInvalidParams(route.params)) {\n if (!route.state && isInvalidParams(route.params)) {\n route.state = createFakeState(route.params);\n }\n\n const { pattern, params, nextRoute, focusedParams } = walkConfigItems(\n route,\n getActiveRoute(current),\n { ...configs },\n { preserveDynamicRoutes }\n );\n\n Object.assign(allParams, params);\n\n path += getPathWithConventionsCollapsed({\n pattern,\n routePath: nextRoute.path,\n params: allParams,\n initialRouteName: configs[nextRoute.name]?.initialRouteName,\n preserveGroups,\n preserveDynamicRoutes,\n });\n\n if (\n nextRoute.state &&\n // NOTE(EvanBacon): The upstream implementation allows for sending in synthetic states (states that weren't generated by `getStateFromPath`)\n // and any invalid routes will simply be ignored.\n // Because of this, we need to check if the next route is valid before continuing, otherwise our more strict\n // implementation will throw an error.\n configs[nextRoute.state.routes?.[nextRoute.state?.index ?? 0]?.name]\n ) {\n // Continue looping with the next state if available.\n current = nextRoute.state;\n } else {\n // Finished crawling state.\n\n // Check for query params before exiting.\n if (focusedParams) {\n for (const param in focusedParams) {\n // TODO: This is not good. We shouldn't squat strings named \"undefined\".\n if (focusedParams[param] === 'undefined') {\n // eslint-disable-next-line @typescript-eslint/no-dynamic-delete\n delete focusedParams[param];\n }\n }\n\n const query = queryString.stringify(focusedParams, { sort: false });\n if (query) {\n path += `?${query}`;\n }\n }\n break;\n }\n }\n\n return { path: basicSanitizePath(path), params: decodeParams(allParams) };\n}\n\nfunction decodeParams(params: Record<string, string>) {\n const parsed: Record<string, any> = {};\n\n for (const [key, value] of Object.entries(params)) {\n parsed[key] = decodeURIComponent(value);\n }\n\n return parsed;\n}\n\nfunction getPathWithConventionsCollapsed({\n pattern,\n routePath,\n params,\n preserveGroups,\n preserveDynamicRoutes,\n initialRouteName,\n}: {\n pattern: string;\n routePath?: string;\n params: Record<string, any>;\n preserveGroups?: boolean;\n preserveDynamicRoutes?: boolean;\n initialRouteName?: string;\n}) {\n const segments = pattern.split('/');\n return segments\n .map((p, i) => {\n const name = getParamName(p);\n\n // We don't know what to show for wildcard patterns\n // Showing the route name seems ok, though whatever we show here will be incorrect\n // Since the page doesn't actually exist\n if (p.startsWith('*')) {\n if (preserveDynamicRoutes) {\n return `[...${name}]`;\n }\n if (params[name]) {\n return params[name].join('/');\n }\n if (i === 0) {\n // This can occur when a wildcard matches all routes and the given path was `/`.\n return routePath;\n }\n // remove existing segments from route.path and return it\n // this is used for nested wildcard routes. Without this, the path would add\n // all nested segments to the beginning of the wildcard route.\n return routePath\n ?.split('/')\n .slice(i + 1)\n .join('/');\n }\n\n // If the path has a pattern for a param, put the param in the path\n if (p.startsWith(':')) {\n if (preserveDynamicRoutes) {\n return `[${name}]`;\n }\n // Optional params without value assigned in route.params should be ignored\n return params[name];\n }\n\n if (!preserveGroups && matchGroupName(p) != null) {\n // When the last part is a group it could be a shared URL\n // if the route has an initialRouteName defined, then we should\n // use that as the component path as we can assume it will be shown.\n if (segments.length - 1 === i) {\n if (initialRouteName) {\n // Return an empty string if the init route is ambiguous.\n if (segmentMatchesConvention(initialRouteName)) {\n return '';\n }\n return encodeURIComponentPreservingBrackets(initialRouteName);\n }\n }\n return '';\n }\n // Preserve dynamic syntax for rehydration\n return encodeURIComponentPreservingBrackets(p);\n })\n .map((v) => v ?? '')\n .join('/');\n}\n\n/** Given a set of query params and a pattern with possible conventions, collapse the conventions and return the remaining params. */\nfunction getParamsWithConventionsCollapsed({\n pattern,\n routeName,\n params,\n}: {\n pattern: string;\n /** Route name is required for matching the wildcard route. This is specific to Expo Router. */\n routeName: string;\n params: object;\n}): Record<string, string> {\n const processedParams: Record<string, string> = { ...params };\n\n // Remove the params present in the pattern since we'll only use the rest for query string\n\n const segments = pattern.split('/');\n\n // Dynamic Routes\n segments\n .filter((segment) => segment.startsWith(':'))\n .forEach((segment) => {\n const name = getParamName(segment);\n delete processedParams[name];\n });\n\n // Deep Dynamic Routes\n if (segments.some((segment) => segment.startsWith('*'))) {\n // NOTE(EvanBacon): Drop the param name matching the wildcard route name -- this is specific to Expo Router.\n const name = matchDeepDynamicRouteName(routeName) ?? routeName;\n delete processedParams[name];\n }\n\n return processedParams;\n}\n\n// Remove multiple as well as trailing slashes\nfunction basicSanitizePath(path: string) {\n // Remove duplicate slashes like `foo//bar` -> `foo/bar`\n const simplifiedPath = path.replace(/\\/+/g, '/');\n if (simplifiedPath.length <= 1) {\n return simplifiedPath;\n }\n // Remove trailing slash like `foo/bar/` -> `foo/bar`\n return simplifiedPath.replace(/\\/$/, '');\n}\n\ntype StateAsParams = {\n initial: boolean;\n path?: string;\n screen: string;\n params: Record<string, any>;\n};\n\n// TODO: Make StackRouter not do this...\n// Detect if the params came from StackRouter using `params` to pass around internal state.\nfunction isInvalidParams(params?: Record<string, any>): params is StateAsParams {\n if (!params) {\n return false;\n }\n\n if ('params' in params && typeof params.params === 'object' && !!params.params) {\n return true;\n }\n\n return (\n 'initial' in params &&\n typeof params.initial === 'boolean' &&\n // \"path\" in params &&\n 'screen' in params\n );\n}\n\nconst getParamName = (pattern: string) => pattern.replace(/^[:*]/, '').replace(/\\?$/, '');\n\nconst joinPaths = (...paths: string[]): string =>\n ([] as string[])\n .concat(...paths.map((p) => p.split('/')))\n .filter(Boolean)\n .join('/');\n\nconst createConfigItem = (\n config: PathConfig<object> | string,\n parentPattern?: string\n): ConfigItem => {\n if (typeof config === 'string') {\n // If a string is specified as the value of the key(e.g. Foo: '/path'), use it as the pattern\n const pattern = parentPattern ? joinPaths(parentPattern, config) : config;\n\n return { pattern };\n }\n\n if (config.exact && config.path === undefined) {\n throw new Error(\n \"A 'path' needs to be specified when specifying 'exact: true'. If you don't want this screen in the URL, specify it as empty string, e.g. `path: ''`.\"\n );\n }\n\n // If an object is specified as the value (e.g. Foo: { ... }),\n // It can have `path` property and `screens` prop which has nested configs\n const pattern =\n config.exact !== true ? joinPaths(parentPattern || '', config.path || '') : config.path || '';\n\n const screens = config.screens ? createNormalizedConfigs(config.screens, pattern) : undefined;\n\n return {\n // Normalize pattern to remove any leading, trailing slashes, duplicate slashes etc.\n pattern: pattern?.split('/').filter(Boolean).join('/'),\n stringify: config.stringify,\n screens,\n initialRouteName: config.initialRouteName,\n };\n};\n\nconst createNormalizedConfigs = (\n options: PathConfigMap<object>,\n pattern?: string\n): Record<string, ConfigItem> =>\n Object.fromEntries(\n Object.entries(options).map(([name, c]) => [name, createConfigItem(c, pattern)])\n );\n"]}
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { PathConfigMap } from
|
|
2
|
-
import type { NavigationState, PartialState } from
|
|
3
|
-
import { RouteNode } from
|
|
1
|
+
import { PathConfigMap } from '@react-navigation/core';
|
|
2
|
+
import type { NavigationState, PartialState } from '@react-navigation/routers';
|
|
3
|
+
import { RouteNode } from '../Route';
|
|
4
4
|
type Options<ParamList extends object> = {
|
|
5
5
|
initialRouteName?: string;
|
|
6
6
|
screens: PathConfigMap<ParamList>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"getStateFromPath.d.ts","sourceRoot":"","sources":["../../src/fork/getStateFromPath.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,KAAK,
|
|
1
|
+
{"version":3,"file":"getStateFromPath.d.ts","sourceRoot":"","sources":["../../src/fork/getStateFromPath.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,KAAK,EAAgB,eAAe,EAAE,YAAY,EAAE,MAAM,2BAA2B,CAAC;AAK7F,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAKrC,KAAK,OAAO,CAAC,SAAS,SAAS,MAAM,IAAI;IACvC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,OAAO,EAAE,aAAa,CAAC,SAAS,CAAC,CAAC;CACnC,CAAC;AAEF,KAAK,WAAW,GAAG,MAAM,CAAC,MAAM,EAAE,CAAC,KAAK,EAAE,MAAM,KAAK,GAAG,CAAC,CAAC;AAe1D,KAAK,kBAAkB,GAAG;IACxB,gBAAgB,EAAE,MAAM,CAAC;IACzB,aAAa,EAAE,MAAM,EAAE,CAAC;CACzB,CAAC;AAEF,MAAM,MAAM,WAAW,GAAG,YAAY,CAAC,eAAe,CAAC,GAAG;IACxD,KAAK,CAAC,EAAE,WAAW,CAAC;CACrB,CAAC;AAQF,wBAAgB,oCAAoC,CAAC,IAAI,EAAE,MAAM;;;EAWhE;AAED;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,MAAM,CAAC,OAAO,UAAU,gBAAgB,CAAC,SAAS,SAAS,MAAM,EAC/D,IAAI,EAAE,MAAM,EACZ,OAAO,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC,GAC3B,WAAW,GAAG,SAAS,CAIzB;AAED,wBAAgB,wBAAwB,CAAC,SAAS,SAAS,MAAM,EAAE,OAAO,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC;;;;;;;;;;;;;;EA4C9F"}
|