expo-router 5.0.7 → 5.1.1
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/assets/arrow_down.png +0 -0
- package/build/ExpoRoot.js +1 -0
- package/build/ExpoRoot.js.map +1 -1
- package/build/exports.d.ts +1 -0
- package/build/exports.d.ts.map +1 -1
- package/build/exports.js +3 -1
- package/build/exports.js.map +1 -1
- package/build/fork/getPathFromState-forks.js +1 -4
- package/build/fork/getPathFromState-forks.js.map +1 -1
- package/build/fork/getStateFromPath-forks.d.ts +2 -0
- package/build/fork/getStateFromPath-forks.d.ts.map +1 -1
- package/build/fork/getStateFromPath-forks.js +18 -2
- package/build/fork/getStateFromPath-forks.js.map +1 -1
- package/build/getReactNavigationConfig.d.ts.map +1 -1
- package/build/getReactNavigationConfig.js +8 -7
- package/build/getReactNavigationConfig.js.map +1 -1
- package/build/getRoutes.d.ts +1 -1
- package/build/getRoutes.d.ts.map +1 -1
- package/build/getRoutes.js +14 -6
- package/build/getRoutes.js.map +1 -1
- package/build/getRoutesCore.d.ts +7 -2
- package/build/getRoutesCore.d.ts.map +1 -1
- package/build/getRoutesCore.js +92 -68
- package/build/getRoutesCore.js.map +1 -1
- package/build/getRoutesRedirects.d.ts +2 -2
- package/build/getRoutesRedirects.d.ts.map +1 -1
- package/build/getRoutesRedirects.js +33 -33
- package/build/getRoutesRedirects.js.map +1 -1
- package/build/getRoutesSSR.d.ts +1 -1
- package/build/getRoutesSSR.d.ts.map +1 -1
- package/build/getRoutesSSR.js +2 -3
- package/build/getRoutesSSR.js.map +1 -1
- package/build/global-state/routeInfo.d.ts.map +1 -1
- package/build/global-state/routeInfo.js +21 -1
- package/build/global-state/routeInfo.js.map +1 -1
- package/build/global-state/router-store.d.ts.map +1 -1
- package/build/global-state/router-store.js +7 -1
- package/build/global-state/router-store.js.map +1 -1
- package/build/global-state/routing.js +3 -2
- package/build/global-state/routing.js.map +1 -1
- package/build/layouts/StackClient.d.ts.map +1 -1
- package/build/layouts/StackClient.js +152 -65
- package/build/layouts/StackClient.js.map +1 -1
- package/build/layouts/TabsClient.d.ts +3 -1
- package/build/layouts/TabsClient.d.ts.map +1 -1
- package/build/layouts/TabsClient.js +2 -0
- package/build/layouts/TabsClient.js.map +1 -1
- package/build/link/Link.d.ts +1 -56
- package/build/link/Link.d.ts.map +1 -1
- package/build/link/Link.js +3 -39
- package/build/link/Link.js.map +1 -1
- package/build/link/Redirect.d.ts +59 -0
- package/build/link/Redirect.d.ts.map +1 -0
- package/build/link/Redirect.js +43 -0
- package/build/link/Redirect.js.map +1 -0
- package/build/matchers.d.ts +6 -3
- package/build/matchers.d.ts.map +1 -1
- package/build/matchers.js +15 -11
- package/build/matchers.js.map +1 -1
- package/build/rsc/middleware.d.ts.map +1 -1
- package/build/rsc/middleware.js +15 -27
- package/build/rsc/middleware.js.map +1 -1
- package/build/useFocusEffect.d.ts +2 -2
- package/build/useFocusEffect.d.ts.map +1 -1
- package/build/useFocusEffect.js +7 -5
- package/build/useFocusEffect.js.map +1 -1
- package/build/useScreens.d.ts +1 -3
- package/build/useScreens.d.ts.map +1 -1
- package/build/useScreens.js +2 -2
- package/build/useScreens.js.map +1 -1
- package/build/utils/stack.d.ts +5 -0
- package/build/utils/stack.d.ts.map +1 -0
- package/build/utils/stack.js +10 -0
- package/build/utils/stack.js.map +1 -0
- package/build/views/Navigator.d.ts.map +1 -1
- package/build/views/Navigator.js +5 -2
- package/build/views/Navigator.js.map +1 -1
- package/build/views/Screen.d.ts.map +1 -1
- package/build/views/Screen.js +13 -40
- package/build/views/Screen.js.map +1 -1
- package/build/views/Sitemap.d.ts.map +1 -1
- package/build/views/Sitemap.js +56 -72
- package/build/views/Sitemap.js.map +1 -1
- package/build/views/Unmatched.d.ts.map +1 -1
- package/build/views/Unmatched.js +9 -3
- package/build/views/Unmatched.js.map +1 -1
- package/build/views/useSafeLayoutEffect.d.ts +3 -0
- package/build/views/useSafeLayoutEffect.d.ts.map +1 -0
- package/build/views/useSafeLayoutEffect.js +6 -0
- package/build/views/useSafeLayoutEffect.js.map +1 -0
- package/build/views/useSitemap.d.ts +12 -0
- package/build/views/useSitemap.d.ts.map +1 -0
- package/build/views/useSitemap.js +50 -0
- package/build/views/useSitemap.js.map +1 -0
- package/package.json +3 -3
- package/plugin/options.json +29 -1
- package/_async-server-import.js +0 -21
|
@@ -0,0 +1,59 @@
|
|
|
1
|
+
import type { Href } from '../types';
|
|
2
|
+
export type RedirectProps = {
|
|
3
|
+
/**
|
|
4
|
+
* The path of the route to navigate to. It can either be:
|
|
5
|
+
* - **string**: A full path like `/profile/settings` or a relative path like `../settings`.
|
|
6
|
+
* - **object**: An object with a `pathname` and optional `params`. The `pathname` can be
|
|
7
|
+
* a full path like `/profile/settings` or a relative path like `../settings`. The
|
|
8
|
+
* params can be an object of key-value pairs.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```tsx Dynamic
|
|
12
|
+
* import { Redirect } from 'expo-router';
|
|
13
|
+
*
|
|
14
|
+
* export default function RedirectToAbout() {
|
|
15
|
+
* return (
|
|
16
|
+
* <Redirect href="/about" />
|
|
17
|
+
* );
|
|
18
|
+
*}
|
|
19
|
+
* ```
|
|
20
|
+
*/
|
|
21
|
+
href: Href;
|
|
22
|
+
/**
|
|
23
|
+
* Relative URL references are either relative to the directory or the document.
|
|
24
|
+
* By default, relative paths are relative to the document.
|
|
25
|
+
*
|
|
26
|
+
* @see [Resolving relative references in Mozilla's documentation](https://developer.mozilla.org/en-US/docs/Web/API/URL_API/Resolving_relative_references).
|
|
27
|
+
*/
|
|
28
|
+
relativeToDirectory?: boolean;
|
|
29
|
+
/**
|
|
30
|
+
* Replaces the initial screen with the current route.
|
|
31
|
+
*/
|
|
32
|
+
withAnchor?: boolean;
|
|
33
|
+
};
|
|
34
|
+
/**
|
|
35
|
+
* Redirects to the `href` as soon as the component is mounted.
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* ```tsx
|
|
39
|
+
* import { View, Text } from 'react-native';
|
|
40
|
+
* import { Redirect } from 'expo-router';
|
|
41
|
+
*
|
|
42
|
+
* export default function Page() {
|
|
43
|
+
* const { user } = useAuth();
|
|
44
|
+
*
|
|
45
|
+
* if (!user) {
|
|
46
|
+
* return <Redirect href="/login" />;
|
|
47
|
+
* }
|
|
48
|
+
*
|
|
49
|
+
* return (
|
|
50
|
+
* <View>
|
|
51
|
+
* <Text>Welcome Back!</Text>
|
|
52
|
+
* </View>
|
|
53
|
+
* );
|
|
54
|
+
* }
|
|
55
|
+
* ```
|
|
56
|
+
*/
|
|
57
|
+
export declare function Redirect({ href, relativeToDirectory, withAnchor }: RedirectProps): null;
|
|
58
|
+
export default Redirect;
|
|
59
|
+
//# sourceMappingURL=Redirect.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Redirect.d.ts","sourceRoot":"","sources":["../../src/link/Redirect.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EAAE,IAAI,EAAE,MAAM,UAAU,CAAC;AAGrC,MAAM,MAAM,aAAa,GAAG;IAC1B;;;;;;;;;;;;;;;;;OAiBG;IACH,IAAI,EAAE,IAAI,CAAC;IAEX;;;;;OAKG;IACH,mBAAmB,CAAC,EAAE,OAAO,CAAC;IAE9B;;OAEG;IACH,UAAU,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC;AAEF;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,wBAAgB,QAAQ,CAAC,EAAE,IAAI,EAAE,mBAAmB,EAAE,UAAU,EAAE,EAAE,aAAa,QAUhF;AAED,eAAe,QAAQ,CAAC"}
|
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
'use client';
|
|
3
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
4
|
+
exports.Redirect = Redirect;
|
|
5
|
+
const hooks_1 = require("../hooks");
|
|
6
|
+
const useFocusEffect_1 = require("../useFocusEffect");
|
|
7
|
+
/**
|
|
8
|
+
* Redirects to the `href` as soon as the component is mounted.
|
|
9
|
+
*
|
|
10
|
+
* @example
|
|
11
|
+
* ```tsx
|
|
12
|
+
* import { View, Text } from 'react-native';
|
|
13
|
+
* import { Redirect } from 'expo-router';
|
|
14
|
+
*
|
|
15
|
+
* export default function Page() {
|
|
16
|
+
* const { user } = useAuth();
|
|
17
|
+
*
|
|
18
|
+
* if (!user) {
|
|
19
|
+
* return <Redirect href="/login" />;
|
|
20
|
+
* }
|
|
21
|
+
*
|
|
22
|
+
* return (
|
|
23
|
+
* <View>
|
|
24
|
+
* <Text>Welcome Back!</Text>
|
|
25
|
+
* </View>
|
|
26
|
+
* );
|
|
27
|
+
* }
|
|
28
|
+
* ```
|
|
29
|
+
*/
|
|
30
|
+
function Redirect({ href, relativeToDirectory, withAnchor }) {
|
|
31
|
+
const router = (0, hooks_1.useRouter)();
|
|
32
|
+
(0, useFocusEffect_1.useFocusEffect)(() => {
|
|
33
|
+
try {
|
|
34
|
+
router.replace(href, { relativeToDirectory, withAnchor });
|
|
35
|
+
}
|
|
36
|
+
catch (error) {
|
|
37
|
+
console.error(error);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
return null;
|
|
41
|
+
}
|
|
42
|
+
exports.default = Redirect;
|
|
43
|
+
//# sourceMappingURL=Redirect.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"Redirect.js","sourceRoot":"","sources":["../../src/link/Redirect.tsx"],"names":[],"mappings":";AAAA,YAAY,CAAC;;AA+Db,4BAUC;AAxED,oCAAqC;AAErC,sDAAmD;AAqCnD;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,SAAgB,QAAQ,CAAC,EAAE,IAAI,EAAE,mBAAmB,EAAE,UAAU,EAAiB;IAC/E,MAAM,MAAM,GAAG,IAAA,iBAAS,GAAE,CAAC;IAC3B,IAAA,+BAAc,EAAC,GAAG,EAAE;QAClB,IAAI,CAAC;YACH,MAAM,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,mBAAmB,EAAE,UAAU,EAAE,CAAC,CAAC;QAC5D,CAAC;QAAC,OAAO,KAAK,EAAE,CAAC;YACf,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,CAAC;QACvB,CAAC;IACH,CAAC,CAAC,CAAC;IACH,OAAO,IAAI,CAAC;AACd,CAAC;AAED,kBAAe,QAAQ,CAAC","sourcesContent":["'use client';\nimport { useRouter } from '../hooks';\nimport type { Href } from '../types';\nimport { useFocusEffect } from '../useFocusEffect';\n\nexport type RedirectProps = {\n /**\n * The path of the route to navigate to. It can either be:\n * - **string**: A full path like `/profile/settings` or a relative path like `../settings`.\n * - **object**: An object with a `pathname` and optional `params`. The `pathname` can be\n * a full path like `/profile/settings` or a relative path like `../settings`. The\n * params can be an object of key-value pairs.\n *\n * @example\n * ```tsx Dynamic\n * import { Redirect } from 'expo-router';\n *\n * export default function RedirectToAbout() {\n * return (\n * <Redirect href=\"/about\" />\n * );\n *}\n * ```\n */\n href: Href;\n\n /**\n * Relative URL references are either relative to the directory or the document.\n * By default, relative paths are relative to the document.\n *\n * @see [Resolving relative references in Mozilla's documentation](https://developer.mozilla.org/en-US/docs/Web/API/URL_API/Resolving_relative_references).\n */\n relativeToDirectory?: boolean;\n\n /**\n * Replaces the initial screen with the current route.\n */\n withAnchor?: boolean;\n};\n\n/**\n * Redirects to the `href` as soon as the component is mounted.\n *\n * @example\n * ```tsx\n * import { View, Text } from 'react-native';\n * import { Redirect } from 'expo-router';\n *\n * export default function Page() {\n * const { user } = useAuth();\n *\n * if (!user) {\n * return <Redirect href=\"/login\" />;\n * }\n *\n * return (\n * <View>\n * <Text>Welcome Back!</Text>\n * </View>\n * );\n * }\n * ```\n */\nexport function Redirect({ href, relativeToDirectory, withAnchor }: RedirectProps) {\n const router = useRouter();\n useFocusEffect(() => {\n try {\n router.replace(href, { relativeToDirectory, withAnchor });\n } catch (error) {\n console.error(error);\n }\n });\n return null;\n}\n\nexport default Redirect;\n"]}
|
package/build/matchers.d.ts
CHANGED
|
@@ -1,7 +1,9 @@
|
|
|
1
|
+
interface DynamicNameMatch {
|
|
2
|
+
name: string;
|
|
3
|
+
deep: boolean;
|
|
4
|
+
}
|
|
1
5
|
/** Match `[page]` -> `page` */
|
|
2
|
-
export declare function matchDynamicName(name: string):
|
|
3
|
-
/** Match `[...page]` -> `page` */
|
|
4
|
-
export declare function matchDeepDynamicRouteName(name: string): string | undefined;
|
|
6
|
+
export declare function matchDynamicName(name: string): DynamicNameMatch | undefined;
|
|
5
7
|
/** Test `/` -> `page` */
|
|
6
8
|
export declare function testNotFound(name: string): boolean;
|
|
7
9
|
/** Match `(page)` -> `page` */
|
|
@@ -25,4 +27,5 @@ export declare function stripInvisibleSegmentsFromPath(path: string): string;
|
|
|
25
27
|
* - Routes can still use `+`, but it cannot be in the last segment.
|
|
26
28
|
*/
|
|
27
29
|
export declare function isTypedRoute(name: string): boolean;
|
|
30
|
+
export {};
|
|
28
31
|
//# sourceMappingURL=matchers.d.ts.map
|
package/build/matchers.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"matchers.d.ts","sourceRoot":"","sources":["../src/matchers.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"matchers.d.ts","sourceRoot":"","sources":["../src/matchers.tsx"],"names":[],"mappings":"AAGA,UAAU,gBAAgB;IACxB,IAAI,EAAE,MAAM,CAAC;IACb,IAAI,EAAE,OAAO,CAAC;CACf;AAED,+BAA+B;AAC/B,wBAAgB,gBAAgB,CAAC,IAAI,EAAE,MAAM,GAAG,gBAAgB,GAAG,SAAS,CAS3E;AAED,yBAAyB;AACzB,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,GAAG,OAAO,CAElD;AAED,+BAA+B;AAC/B,wBAAgB,cAAc,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAE/D;AAED,qCAAqC;AACrC,wBAAgB,kBAAkB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,GAAG,SAAS,CAEnE;AAED,oEAAoE;AACpE,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,sBAE/C;AAED,wBAAgB,mBAAmB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAExD;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAQlD;AAED,+DAA+D;AAC/D,wBAAgB,yBAAyB,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE9D;AAED,0CAA0C;AAC1C,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAE/D;AAGD,wBAAgB,oBAAoB,CAAC,QAAQ,EAAE,MAAM,GAAG,MAAM,CAE7D;AAED,wBAAgB,0BAA0B,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAU/D;AAED,wBAAgB,8BAA8B,CAAC,IAAI,EAAE,MAAM,GAAG,MAAM,CAEnE;AAED;;;;GAIG;AACH,wBAAgB,YAAY,CAAC,IAAI,EAAE,MAAM,WAExC"}
|
package/build/matchers.js
CHANGED
|
@@ -1,7 +1,6 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
3
|
exports.matchDynamicName = matchDynamicName;
|
|
4
|
-
exports.matchDeepDynamicRouteName = matchDeepDynamicRouteName;
|
|
5
4
|
exports.testNotFound = testNotFound;
|
|
6
5
|
exports.matchGroupName = matchGroupName;
|
|
7
6
|
exports.matchLastGroupName = matchLastGroupName;
|
|
@@ -14,15 +13,20 @@ exports.removeFileSystemDots = removeFileSystemDots;
|
|
|
14
13
|
exports.stripGroupSegmentsFromPath = stripGroupSegmentsFromPath;
|
|
15
14
|
exports.stripInvisibleSegmentsFromPath = stripInvisibleSegmentsFromPath;
|
|
16
15
|
exports.isTypedRoute = isTypedRoute;
|
|
16
|
+
/** Match `[page]` -> `page` or `[...group]` -> `...group` */
|
|
17
|
+
const dynamicNameRe = /^\[([^[\]]+?)\]$/;
|
|
17
18
|
/** Match `[page]` -> `page` */
|
|
18
19
|
function matchDynamicName(name) {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
}
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
20
|
+
const paramName = name.match(dynamicNameRe)?.[1];
|
|
21
|
+
if (paramName == null) {
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
24
|
+
else if (paramName.startsWith('...')) {
|
|
25
|
+
return { name: paramName.slice(3), deep: true };
|
|
26
|
+
}
|
|
27
|
+
else {
|
|
28
|
+
return { name: paramName, deep: false };
|
|
29
|
+
}
|
|
26
30
|
}
|
|
27
31
|
/** Test `/` -> `page` */
|
|
28
32
|
function testNotFound(name) {
|
|
@@ -30,15 +34,15 @@ function testNotFound(name) {
|
|
|
30
34
|
}
|
|
31
35
|
/** Match `(page)` -> `page` */
|
|
32
36
|
function matchGroupName(name) {
|
|
33
|
-
return name.match(/^(?:[^\\(
|
|
37
|
+
return name.match(/^(?:[^\\()])*?\(([^\\/]+)\)/)?.[1];
|
|
34
38
|
}
|
|
35
39
|
/** Match `(app)/(page)` -> `page` */
|
|
36
40
|
function matchLastGroupName(name) {
|
|
37
|
-
return name.match(/.*(?:\/|^)\(([
|
|
41
|
+
return name.match(/.*(?:\/|^)\(([^\\/]+)\)[^\s]*$/)?.[1];
|
|
38
42
|
}
|
|
39
43
|
/** Match the first array group name `(a,b,c)/(d,c)` -> `'a,b,c'` */
|
|
40
44
|
function matchArrayGroupName(name) {
|
|
41
|
-
return name.match(/(?:[^\\(
|
|
45
|
+
return name.match(/(?:[^\\()])*?\(([^\\/]+,[^\\/]+)\)/)?.[1];
|
|
42
46
|
}
|
|
43
47
|
function getNameFromFilePath(name) {
|
|
44
48
|
return removeSupportedExtensions(removeFileSystemDots(name));
|
package/build/matchers.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"matchers.js","sourceRoot":"","sources":["../src/matchers.tsx"],"names":[],"mappings":";;
|
|
1
|
+
{"version":3,"file":"matchers.js","sourceRoot":"","sources":["../src/matchers.tsx"],"names":[],"mappings":"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","sourcesContent":["/** Match `[page]` -> `page` or `[...group]` -> `...group` */\nconst dynamicNameRe = /^\\[([^[\\]]+?)\\]$/;\n\ninterface DynamicNameMatch {\n name: string;\n deep: boolean;\n}\n\n/** Match `[page]` -> `page` */\nexport function matchDynamicName(name: string): DynamicNameMatch | undefined {\n const paramName = name.match(dynamicNameRe)?.[1];\n if (paramName == null) {\n return undefined;\n } else if (paramName.startsWith('...')) {\n return { name: paramName.slice(3), deep: true };\n } else {\n return { name: paramName, deep: false };\n }\n}\n\n/** Test `/` -> `page` */\nexport function testNotFound(name: string): boolean {\n return /\\+not-found$/.test(name);\n}\n\n/** Match `(page)` -> `page` */\nexport function matchGroupName(name: string): string | undefined {\n return name.match(/^(?:[^\\\\()])*?\\(([^\\\\/]+)\\)/)?.[1];\n}\n\n/** Match `(app)/(page)` -> `page` */\nexport function matchLastGroupName(name: string): string | undefined {\n return name.match(/.*(?:\\/|^)\\(([^\\\\/]+)\\)[^\\s]*$/)?.[1];\n}\n\n/** Match the first array group name `(a,b,c)/(d,c)` -> `'a,b,c'` */\nexport function matchArrayGroupName(name: string) {\n return name.match(/(?:[^\\\\()])*?\\(([^\\\\/]+,[^\\\\/]+)\\)/)?.[1];\n}\n\nexport function getNameFromFilePath(name: string): string {\n return removeSupportedExtensions(removeFileSystemDots(name));\n}\n\nexport function getContextKey(name: string): string {\n // The root path is `` (empty string) so always prepend `/` to ensure\n // there is some value.\n const normal = '/' + getNameFromFilePath(name);\n if (!normal.endsWith('_layout')) {\n return normal;\n }\n return normal.replace(/\\/?_layout$/, '');\n}\n\n/** Remove `.js`, `.ts`, `.jsx`, `.tsx`, and the +api suffix */\nexport function removeSupportedExtensions(name: string): string {\n return name.replace(/(\\+api)?\\.[jt]sx?$/g, '');\n}\n\n/** Remove `.js`, `.ts`, `.jsx`, `.tsx` */\nexport function removeFileSystemExtensions(name: string): string {\n return name.replace(/\\.[jt]sx?$/g, '');\n}\n\n// Remove any amount of `./` and `../` from the start of the string\nexport function removeFileSystemDots(filePath: string): string {\n return filePath.replace(/^(?:\\.\\.?\\/)+/g, '');\n}\n\nexport function stripGroupSegmentsFromPath(path: string): string {\n return path\n .split('/')\n .reduce((acc, v) => {\n if (matchGroupName(v) == null) {\n acc.push(v);\n }\n return acc;\n }, [] as string[])\n .join('/');\n}\n\nexport function stripInvisibleSegmentsFromPath(path: string): string {\n return stripGroupSegmentsFromPath(path).replace(/\\/?index$/, '');\n}\n\n/**\n * Match:\n * - _layout files, +html, +not-found, string+api, etc\n * - Routes can still use `+`, but it cannot be in the last segment.\n */\nexport function isTypedRoute(name: string) {\n return !name.startsWith('+') && name.match(/(_layout|[^/]*?\\+[^/]*?)\\.[tj]sx?$/) === null;\n}\n"]}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../../src/rsc/middleware.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mCAAmC,CAAC;
|
|
1
|
+
{"version":3,"file":"middleware.d.ts","sourceRoot":"","sources":["../../src/rsc/middleware.ts"],"names":[],"mappings":"AAAA;;;;;;GAMG;AAEH,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,mCAAmC,CAAC;AAkEvE,KAAK,SAAS,GAAG;IACf,MAAM,EAAE,MAAM,OAAO,CAAC,cAAc,6BAA6B,CAAC,CAAC,CAAC;CACrE,CAAC;AAEF,wBAAsB,yBAAyB,CAC7C,UAAU,EAAE,MAAM,EAClB,OAAO,EAAE,SAAS,EAClB,EAAE,IAAI,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,OAAO,EAAE,EAAE,aAAa,GAC3F,OAAO,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAiE9B;AAED,wBAAsB,cAAc,CAClC,UAAU,EAAE,MAAM,EAClB,IAAI,EAAE,aAAa,GAClB,OAAO,CAAC,cAAc,CAAC,GAAG,CAAC,CAAC,CAY9B"}
|
package/build/rsc/middleware.js
CHANGED
|
@@ -6,12 +6,16 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
6
6
|
exports.renderRscWithImportsAsync = renderRscWithImportsAsync;
|
|
7
7
|
exports.renderRscAsync = renderRscAsync;
|
|
8
8
|
const expo_constants_1 = __importDefault(require("expo-constants"));
|
|
9
|
-
const _async_server_import_1 = require("expo-router/_async-server-import");
|
|
10
9
|
const node_path_1 = __importDefault(require("node:path"));
|
|
11
10
|
const rsc_renderer_1 = require("./rsc-renderer");
|
|
12
11
|
const debug = require('debug')('expo:server:rsc-renderer');
|
|
13
12
|
// Tracking the implementation in expo/cli's MetroBundlerDevServer
|
|
14
13
|
const rscRenderContext = new Map();
|
|
14
|
+
function serverRequire(...targetOutputModulePath) {
|
|
15
|
+
// NOTE(@kitten): This `__dirname` will be located in the output file system, e.g. `dist/server/*`
|
|
16
|
+
const filePath = node_path_1.default.join(__dirname, ...targetOutputModulePath);
|
|
17
|
+
return $$require_external(filePath);
|
|
18
|
+
}
|
|
15
19
|
function getRscRenderContext(platform) {
|
|
16
20
|
// NOTE(EvanBacon): We memoize this now that there's a persistent server storage cache for Server Actions.
|
|
17
21
|
if (rscRenderContext.has(platform)) {
|
|
@@ -21,23 +25,13 @@ function getRscRenderContext(platform) {
|
|
|
21
25
|
rscRenderContext.set(platform, context);
|
|
22
26
|
return context;
|
|
23
27
|
}
|
|
24
|
-
function
|
|
25
|
-
if ('default' in mod && typeof mod.default === 'object' && mod.default) {
|
|
26
|
-
const def = mod.default;
|
|
27
|
-
if ('default' in def && typeof def.default === 'object' && def.default) {
|
|
28
|
-
return def.default;
|
|
29
|
-
}
|
|
30
|
-
return mod.default;
|
|
31
|
-
}
|
|
32
|
-
return mod;
|
|
33
|
-
}
|
|
34
|
-
async function getServerActionManifest(distFolder, platform) {
|
|
28
|
+
function getServerActionManifest(_distFolder, platform) {
|
|
35
29
|
const filePath = `../../rsc/${platform}/action-manifest.js`;
|
|
36
|
-
return
|
|
30
|
+
return serverRequire(filePath);
|
|
37
31
|
}
|
|
38
|
-
|
|
32
|
+
function getSSRManifest(_distFolder, platform) {
|
|
39
33
|
const filePath = `../../rsc/${platform}/ssr-manifest.js`;
|
|
40
|
-
return
|
|
34
|
+
return serverRequire(filePath);
|
|
41
35
|
}
|
|
42
36
|
async function renderRscWithImportsAsync(distFolder, imports, { body, platform, searchParams, config, method, input, contentType, headers }) {
|
|
43
37
|
globalThis.__expo_platform_header = platform;
|
|
@@ -51,8 +45,8 @@ async function renderRscWithImportsAsync(distFolder, imports, { body, platform,
|
|
|
51
45
|
redirects: expo_constants_1.default.expoConfig?.extra?.router?.redirects,
|
|
52
46
|
rewrites: expo_constants_1.default.expoConfig?.extra?.router?.rewrites,
|
|
53
47
|
});
|
|
54
|
-
const ssrManifest =
|
|
55
|
-
const actionManifest =
|
|
48
|
+
const ssrManifest = getSSRManifest(distFolder, platform);
|
|
49
|
+
const actionManifest = getServerActionManifest(distFolder, platform);
|
|
56
50
|
return (0, rsc_renderer_1.renderRsc)({
|
|
57
51
|
body: body ?? undefined,
|
|
58
52
|
context,
|
|
@@ -85,13 +79,8 @@ async function renderRscWithImportsAsync(distFolder, imports, { body, platform,
|
|
|
85
79
|
},
|
|
86
80
|
async loadServerModuleRsc(file) {
|
|
87
81
|
debug('loadServerModuleRsc', file);
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
// TODO: This is a hack to workaround a cloudflare/metro issue where there's an extra `default` wrapper.
|
|
91
|
-
if (typeof caches !== 'undefined') {
|
|
92
|
-
return m.default;
|
|
93
|
-
}
|
|
94
|
-
return m;
|
|
82
|
+
// NOTE(@kitten): [WORKAROUND] Assumes __dirname is at `dist/server/_expo/functions/_flight`
|
|
83
|
+
return serverRequire('../../../', file);
|
|
95
84
|
},
|
|
96
85
|
entries: entries,
|
|
97
86
|
});
|
|
@@ -100,9 +89,8 @@ async function renderRscAsync(distFolder, args) {
|
|
|
100
89
|
const platform = args.platform;
|
|
101
90
|
return renderRscWithImportsAsync(distFolder, {
|
|
102
91
|
router: () => {
|
|
103
|
-
// Assumes
|
|
104
|
-
|
|
105
|
-
return (0, _async_server_import_1.asyncServerImport)(filePath);
|
|
92
|
+
// NOTE(@kitten): [WORKAROUND] Assumes __dirname is at `dist/server/_expo/functions/_flight`
|
|
93
|
+
return serverRequire(`../../rsc/${platform}/router.js`);
|
|
106
94
|
},
|
|
107
95
|
}, args);
|
|
108
96
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"middleware.js","sourceRoot":"","sources":["../../src/rsc/middleware.ts"],"names":[],"mappings":";;;;;
|
|
1
|
+
{"version":3,"file":"middleware.js","sourceRoot":"","sources":["../../src/rsc/middleware.ts"],"names":[],"mappings":";;;;;AA8EA,8DAqEC;AAED,wCAeC;AA3JD,oEAAuC;AACvC,0DAA6B;AAE7B,iDAA2C;AAI3C,MAAM,KAAK,GAAG,OAAO,CAAC,OAAO,CAAC,CAAC,0BAA0B,CAAC,CAAC;AAE3D,kEAAkE;AAClE,MAAM,gBAAgB,GAAG,IAAI,GAAG,EAAe,CAAC;AAEhD,SAAS,aAAa,CAAU,GAAG,sBAAgC;IACjE,kGAAkG;IAClG,MAAM,QAAQ,GAAG,mBAAI,CAAC,IAAI,CAAC,SAAS,EAAE,GAAG,sBAAsB,CAAC,CAAC;IACjE,OAAO,kBAAkB,CAAC,QAAQ,CAAC,CAAC;AACtC,CAAC;AAED,SAAS,mBAAmB,CAAC,QAAgB;IAC3C,0GAA0G;IAC1G,IAAI,gBAAgB,CAAC,GAAG,CAAC,QAAQ,CAAC,EAAE,CAAC;QACnC,OAAO,gBAAgB,CAAC,GAAG,CAAC,QAAQ,CAAE,CAAC;IACzC,CAAC;IAED,MAAM,OAAO,GAAG,EAAE,CAAC;IAEnB,gBAAgB,CAAC,GAAG,CAAC,QAAQ,EAAE,OAAO,CAAC,CAAC;IACxC,OAAO,OAAO,CAAC;AACjB,CAAC;AAED,SAAS,uBAAuB,CAC9B,WAAmB,EACnB,QAAgB;IAWhB,MAAM,QAAQ,GAAG,aAAa,QAAQ,qBAAqB,CAAC;IAC5D,OAAO,aAAa,CAAC,QAAQ,CAAC,CAAC;AACjC,CAAC;AAED,SAAS,cAAc,CACrB,WAAmB,EACnB,QAAgB;IAWhB,MAAM,QAAQ,GAAG,aAAa,QAAQ,kBAAkB,CAAC;IACzD,OAAO,aAAa,CAAC,QAAQ,CAAC,CAAC;AACjC,CAAC;AAOM,KAAK,UAAU,yBAAyB,CAC7C,UAAkB,EAClB,OAAkB,EAClB,EAAE,IAAI,EAAE,QAAQ,EAAE,YAAY,EAAE,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,OAAO,EAAiB;IAE5F,UAAU,CAAC,sBAAsB,GAAG,QAAQ,CAAC;IAC7C,IAAI,MAAM,KAAK,MAAM,IAAI,CAAC,IAAI,EAAE,CAAC;QAC/B,MAAM,IAAI,KAAK,CAAC,sEAAsE,CAAC,CAAC;IAC1F,CAAC;IAED,MAAM,OAAO,GAAG,mBAAmB,CAAC,QAAQ,CAAC,CAAC;IAC9C,OAAO,CAAC,uBAAuB,CAAC,GAAG,OAAO,CAAC;IAE3C,MAAM,MAAM,GAAG,MAAM,OAAO,CAAC,MAAM,EAAE,CAAC;IACtC,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC;QAC7B,SAAS,EAAE,wBAAS,CAAC,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,SAAS;QACzD,QAAQ,EAAE,wBAAS,CAAC,UAAU,EAAE,KAAK,EAAE,MAAM,EAAE,QAAQ;KACxD,CAAC,CAAC;IAEH,MAAM,WAAW,GAAG,cAAc,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;IACzD,MAAM,cAAc,GAAG,uBAAuB,CAAC,UAAU,EAAE,QAAQ,CAAC,CAAC;IACrE,OAAO,IAAA,wBAAS,EACd;QACE,IAAI,EAAE,IAAI,IAAI,SAAS;QACvB,OAAO;QACP,MAAM;QACN,KAAK;QACL,WAAW;QACX,WAAW,EAAE,YAAY,CAAC,GAAG,CAAC,eAAe,CAAC;KAC/C,EACD;QACE,WAAW,EAAE,IAAI;QAEjB,kBAAkB,CAAC,IAAY,EAAE,QAAiB;YAChD,KAAK,CAAC,oBAAoB,EAAE,IAAI,EAAE,EAAE,QAAQ,EAAE,CAAC,CAAC;YAEhD,IAAI,QAAQ,EAAE,CAAC;gBACb,IAAI,CAAC,CAAC,IAAI,IAAI,cAAc,CAAC,EAAE,CAAC;oBAC9B,MAAM,IAAI,KAAK,CACb,kDAAkD,IAAI,KAAK,IAAI,CAAC,SAAS,CAAC,cAAc,CAAC,EAAE,CAC5F,CAAC;gBACJ,CAAC;gBAED,MAAM,CAAC,EAAE,EAAE,KAAK,CAAC,GAAG,cAAc,CAAC,IAAI,CAAC,CAAC;gBACzC,OAAO;oBACL,EAAE;oBACF,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE;iBAC7B,CAAC;YACJ,CAAC;YAED,IAAI,CAAC,CAAC,IAAI,IAAI,WAAW,CAAC,EAAE,CAAC;gBAC3B,MAAM,IAAI,KAAK,CAAC,wCAAwC,IAAI,EAAE,CAAC,CAAC;YAClE,CAAC;YAED,MAAM,CAAC,EAAE,EAAE,KAAK,CAAC,GAAG,WAAW,CAAC,IAAI,CAAC,CAAC;YACtC,OAAO;gBACL,EAAE;gBACF,MAAM,EAAE,KAAK,CAAC,CAAC,CAAC,CAAC,KAAK,CAAC,CAAC,CAAC,CAAC,EAAE;aAC7B,CAAC;QACJ,CAAC;QACD,KAAK,CAAC,mBAAmB,CAAC,IAAI;YAC5B,KAAK,CAAC,qBAAqB,EAAE,IAAI,CAAC,CAAC;YACnC,4FAA4F;YAC5F,OAAO,aAAa,CAAC,WAAW,EAAE,IAAI,CAAC,CAAC;QAC1C,CAAC;QAED,OAAO,EAAE,OAAQ;KAClB,CACF,CAAC;AACJ,CAAC;AAEM,KAAK,UAAU,cAAc,CAClC,UAAkB,EAClB,IAAmB;IAEnB,MAAM,QAAQ,GAAG,IAAI,CAAC,QAAQ,CAAC;IAC/B,OAAO,yBAAyB,CAC9B,UAAU,EACV;QACE,MAAM,EAAE,GAAG,EAAE;YACX,4FAA4F;YAC5F,OAAO,aAAa,CAAC,aAAa,QAAQ,YAAY,CAAC,CAAC;QAC1D,CAAC;KACF,EACD,IAAI,CACL,CAAC;AACJ,CAAC","sourcesContent":["/**\n * Copyright © 2024 650 Industries.\n *\n * This source code is licensed under the MIT license found in the\n * LICENSE file in the root directory of this source tree.\n *\n */\n// This module is bundled with Metro in web/react-server mode and redirects to platform specific renderers.\nimport type { RenderRscArgs } from '@expo/server/build/middleware/rsc';\nimport Constants from 'expo-constants';\nimport path from 'node:path';\n\nimport { renderRsc } from './rsc-renderer';\n\ndeclare const $$require_external: typeof require;\n\nconst debug = require('debug')('expo:server:rsc-renderer');\n\n// Tracking the implementation in expo/cli's MetroBundlerDevServer\nconst rscRenderContext = new Map<string, any>();\n\nfunction serverRequire<T = any>(...targetOutputModulePath: string[]): T {\n // NOTE(@kitten): This `__dirname` will be located in the output file system, e.g. `dist/server/*`\n const filePath = path.join(__dirname, ...targetOutputModulePath);\n return $$require_external(filePath);\n}\n\nfunction getRscRenderContext(platform: string) {\n // NOTE(EvanBacon): We memoize this now that there's a persistent server storage cache for Server Actions.\n if (rscRenderContext.has(platform)) {\n return rscRenderContext.get(platform)!;\n }\n\n const context = {};\n\n rscRenderContext.set(platform, context);\n return context;\n}\n\nfunction getServerActionManifest(\n _distFolder: string,\n platform: string\n): Record<\n // Input ID\n string,\n [\n // Metro ID\n string,\n // Chunk location.\n string,\n ]\n> {\n const filePath = `../../rsc/${platform}/action-manifest.js`;\n return serverRequire(filePath);\n}\n\nfunction getSSRManifest(\n _distFolder: string,\n platform: string\n): Record<\n // Input ID\n string,\n [\n // Metro ID\n string,\n // Chunk location.\n string,\n ]\n> {\n const filePath = `../../rsc/${platform}/ssr-manifest.js`;\n return serverRequire(filePath);\n}\n\n// The import map allows us to use external modules from different bundling contexts.\ntype ImportMap = {\n router: () => Promise<typeof import('./router/expo-definedRouter')>;\n};\n\nexport async function renderRscWithImportsAsync(\n distFolder: string,\n imports: ImportMap,\n { body, platform, searchParams, config, method, input, contentType, headers }: RenderRscArgs\n): Promise<ReadableStream<any>> {\n globalThis.__expo_platform_header = platform;\n if (method === 'POST' && !body) {\n throw new Error('Server request must be provided when method is POST (server actions)');\n }\n\n const context = getRscRenderContext(platform);\n context['__expo_requestHeaders'] = headers;\n\n const router = await imports.router();\n const entries = router.default({\n redirects: Constants.expoConfig?.extra?.router?.redirects,\n rewrites: Constants.expoConfig?.extra?.router?.rewrites,\n });\n\n const ssrManifest = getSSRManifest(distFolder, platform);\n const actionManifest = getServerActionManifest(distFolder, platform);\n return renderRsc(\n {\n body: body ?? undefined,\n context,\n config,\n input,\n contentType,\n decodedBody: searchParams.get('x-expo-params'),\n },\n {\n isExporting: true,\n\n resolveClientEntry(file: string, isServer: boolean) {\n debug('resolveClientEntry', file, { isServer });\n\n if (isServer) {\n if (!(file in actionManifest)) {\n throw new Error(\n `Could not find file in server action manifest: ${file}. ${JSON.stringify(actionManifest)}`\n );\n }\n\n const [id, chunk] = actionManifest[file];\n return {\n id,\n chunks: chunk ? [chunk] : [],\n };\n }\n\n if (!(file in ssrManifest)) {\n throw new Error(`Could not find file in SSR manifest: ${file}`);\n }\n\n const [id, chunk] = ssrManifest[file];\n return {\n id,\n chunks: chunk ? [chunk] : [],\n };\n },\n async loadServerModuleRsc(file) {\n debug('loadServerModuleRsc', file);\n // NOTE(@kitten): [WORKAROUND] Assumes __dirname is at `dist/server/_expo/functions/_flight`\n return serverRequire('../../../', file);\n },\n\n entries: entries!,\n }\n );\n}\n\nexport async function renderRscAsync(\n distFolder: string,\n args: RenderRscArgs\n): Promise<ReadableStream<any>> {\n const platform = args.platform;\n return renderRscWithImportsAsync(\n distFolder,\n {\n router: () => {\n // NOTE(@kitten): [WORKAROUND] Assumes __dirname is at `dist/server/_expo/functions/_flight`\n return serverRequire(`../../rsc/${platform}/router.js`);\n },\n },\n args\n );\n}\n"]}
|
|
@@ -20,13 +20,13 @@ export type EffectCallback = () => undefined | void | (() => void);
|
|
|
20
20
|
* // Callback should be wrapped in `React.useCallback` to avoid running the effect too often.
|
|
21
21
|
* useCallback(() => {
|
|
22
22
|
* // Invoked whenever the route is focused.
|
|
23
|
-
* console.log(
|
|
23
|
+
* console.log("Hello, I'm focused!");
|
|
24
24
|
*
|
|
25
25
|
* // Return function is invoked whenever the route gets out of focus.
|
|
26
26
|
* return () => {
|
|
27
27
|
* console.log('This route is now unfocused.');
|
|
28
28
|
* };
|
|
29
|
-
* }, [])
|
|
29
|
+
* }, []),
|
|
30
30
|
* );
|
|
31
31
|
*
|
|
32
32
|
* return </>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useFocusEffect.d.ts","sourceRoot":"","sources":["../src/useFocusEffect.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"useFocusEffect.d.ts","sourceRoot":"","sources":["../src/useFocusEffect.ts"],"names":[],"mappings":"AAQA;;GAEG;AACH,MAAM,MAAM,cAAc,GAAG,MAAM,SAAS,GAAG,IAAI,GAAG,CAAC,MAAM,IAAI,CAAC,CAAC;AAEnE;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAiCG;AACH,wBAAgB,cAAc,CAAC,MAAM,EAAE,cAAc,EAAE,yBAAyB,CAAC,EAAE,KAAK,QAuGvF"}
|
package/build/useFocusEffect.js
CHANGED
|
@@ -39,6 +39,7 @@ exports.useFocusEffect = useFocusEffect;
|
|
|
39
39
|
// running the effect. This is especially useful for native redirects.
|
|
40
40
|
const React = __importStar(require("react"));
|
|
41
41
|
const useLoadedNavigation_1 = require("./link/useLoadedNavigation");
|
|
42
|
+
const useNavigation_1 = require("./useNavigation");
|
|
42
43
|
/**
|
|
43
44
|
* Hook to run an effect whenever a route is **focused**. Similar to
|
|
44
45
|
* [`React.useEffect`](https://react.dev/reference/react/useEffect).
|
|
@@ -57,13 +58,13 @@ const useLoadedNavigation_1 = require("./link/useLoadedNavigation");
|
|
|
57
58
|
* // Callback should be wrapped in `React.useCallback` to avoid running the effect too often.
|
|
58
59
|
* useCallback(() => {
|
|
59
60
|
* // Invoked whenever the route is focused.
|
|
60
|
-
* console.log(
|
|
61
|
+
* console.log("Hello, I'm focused!");
|
|
61
62
|
*
|
|
62
63
|
* // Return function is invoked whenever the route gets out of focus.
|
|
63
64
|
* return () => {
|
|
64
65
|
* console.log('This route is now unfocused.');
|
|
65
66
|
* };
|
|
66
|
-
* }, [])
|
|
67
|
+
* }, []),
|
|
67
68
|
* );
|
|
68
69
|
*
|
|
69
70
|
* return </>;
|
|
@@ -74,7 +75,8 @@ const useLoadedNavigation_1 = require("./link/useLoadedNavigation");
|
|
|
74
75
|
* @param do_not_pass_a_second_prop
|
|
75
76
|
*/
|
|
76
77
|
function useFocusEffect(effect, do_not_pass_a_second_prop) {
|
|
77
|
-
const
|
|
78
|
+
const optionalNavigation = (0, useLoadedNavigation_1.useOptionalNavigation)();
|
|
79
|
+
const navigation = (0, useNavigation_1.useNavigation)();
|
|
78
80
|
if (do_not_pass_a_second_prop !== undefined) {
|
|
79
81
|
const message = "You passed a second argument to 'useFocusEffect', but it only accepts one argument. " +
|
|
80
82
|
"If you want to pass a dependency array, you can use 'React.useCallback':\n\n" +
|
|
@@ -87,7 +89,7 @@ function useFocusEffect(effect, do_not_pass_a_second_prop) {
|
|
|
87
89
|
console.error(message);
|
|
88
90
|
}
|
|
89
91
|
React.useEffect(() => {
|
|
90
|
-
if (!navigation) {
|
|
92
|
+
if (!navigation || !optionalNavigation) {
|
|
91
93
|
return;
|
|
92
94
|
}
|
|
93
95
|
let isFocused = false;
|
|
@@ -157,6 +159,6 @@ function useFocusEffect(effect, do_not_pass_a_second_prop) {
|
|
|
157
159
|
unsubscribeFocus();
|
|
158
160
|
unsubscribeBlur();
|
|
159
161
|
};
|
|
160
|
-
}, [effect, navigation]);
|
|
162
|
+
}, [effect, navigation, optionalNavigation, navigation.isFocused()]);
|
|
161
163
|
}
|
|
162
164
|
//# sourceMappingURL=useFocusEffect.js.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useFocusEffect.js","sourceRoot":"","sources":["../src/useFocusEffect.ts"],"names":[],"mappings":";AAAA,YAAY,CAAC;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
|
|
1
|
+
{"version":3,"file":"useFocusEffect.js","sourceRoot":"","sources":["../src/useFocusEffect.ts"],"names":[],"mappings":"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","sourcesContent":["'use client';\n// A fork of `useFocusEffect` that waits for the navigation state to load before\n// running the effect. This is especially useful for native redirects.\nimport * as React from 'react';\n\nimport { useOptionalNavigation } from './link/useLoadedNavigation';\nimport { useNavigation } from './useNavigation';\n\n/**\n * Memoized callback containing the effect, should optionally return a cleanup function.\n */\nexport type EffectCallback = () => undefined | void | (() => void);\n\n/**\n * Hook to run an effect whenever a route is **focused**. Similar to\n * [`React.useEffect`](https://react.dev/reference/react/useEffect).\n *\n * This can be used to perform side-effects such as fetching data or subscribing to events.\n * The passed callback should be wrapped in [`React.useCallback`](https://react.dev/reference/react/useCallback)\n * to avoid running the effect too often.\n *\n * @example\n * ```tsx\n * import { useFocusEffect } from 'expo-router';\n * import { useCallback } from 'react';\n *\n * export default function Route() {\n * useFocusEffect(\n * // Callback should be wrapped in `React.useCallback` to avoid running the effect too often.\n * useCallback(() => {\n * // Invoked whenever the route is focused.\n * console.log(\"Hello, I'm focused!\");\n *\n * // Return function is invoked whenever the route gets out of focus.\n * return () => {\n * console.log('This route is now unfocused.');\n * };\n * }, []),\n * );\n *\n * return </>;\n * }\n *```\n *\n * @param effect Memoized callback containing the effect, should optionally return a cleanup function.\n * @param do_not_pass_a_second_prop\n */\nexport function useFocusEffect(effect: EffectCallback, do_not_pass_a_second_prop?: never) {\n const optionalNavigation = useOptionalNavigation();\n const navigation = useNavigation();\n\n if (do_not_pass_a_second_prop !== undefined) {\n const message =\n \"You passed a second argument to 'useFocusEffect', but it only accepts one argument. \" +\n \"If you want to pass a dependency array, you can use 'React.useCallback':\\n\\n\" +\n 'useFocusEffect(\\n' +\n ' React.useCallback(() => {\\n' +\n ' // Your code here\\n' +\n ' }, [depA, depB])\\n' +\n ');\\n\\n' +\n 'See usage guide: https://reactnavigation.org/docs/use-focus-effect';\n\n console.error(message);\n }\n\n React.useEffect(() => {\n if (!navigation || !optionalNavigation) {\n return;\n }\n\n let isFocused = false;\n let cleanup: undefined | void | (() => void);\n\n const callback = () => {\n const destroy = effect();\n\n if (destroy === undefined || typeof destroy === 'function') {\n return destroy;\n }\n\n if (process.env.NODE_ENV !== 'production') {\n let message =\n 'An effect function must not return anything besides a function, which is used for clean-up.';\n\n if (destroy === null) {\n message +=\n \" You returned 'null'. If your effect does not require clean-up, return 'undefined' (or nothing).\";\n } else if (typeof (destroy as any).then === 'function') {\n message +=\n \"\\n\\nIt looks like you wrote 'useFocusEffect(async () => ...)' or returned a Promise. \" +\n 'Instead, write the async function inside your effect ' +\n 'and call it immediately:\\n\\n' +\n 'useFocusEffect(\\n' +\n ' React.useCallback(() => {\\n' +\n ' async function fetchData() {\\n' +\n ' // You can await here\\n' +\n ' const response = await MyAPI.getData(someId);\\n' +\n ' // ...\\n' +\n ' }\\n\\n' +\n ' fetchData();\\n' +\n ' }, [someId])\\n' +\n ');\\n\\n' +\n 'See usage guide: https://reactnavigation.org/docs/use-focus-effect';\n } else {\n message += ` You returned '${JSON.stringify(destroy)}'.`;\n }\n\n console.error(message);\n }\n };\n\n // We need to run the effect on initial render/dep changes if the screen is focused\n if (navigation.isFocused()) {\n cleanup = callback();\n isFocused = true;\n }\n\n const unsubscribeFocus = navigation.addListener('focus', () => {\n // If callback was already called for focus, avoid calling it again\n // The focus event may also fire on initial render, so we guard against running the effect twice\n if (isFocused) {\n return;\n }\n\n if (cleanup !== undefined) {\n cleanup();\n }\n\n cleanup = callback();\n isFocused = true;\n });\n\n const unsubscribeBlur = navigation.addListener('blur', () => {\n if (cleanup !== undefined) {\n cleanup();\n }\n\n cleanup = undefined;\n isFocused = false;\n });\n\n return () => {\n if (cleanup !== undefined) {\n cleanup();\n }\n\n unsubscribeFocus();\n unsubscribeBlur();\n };\n }, [effect, navigation, optionalNavigation, navigation.isFocused()]);\n}\n"]}
|
package/build/useScreens.d.ts
CHANGED
|
@@ -36,7 +36,5 @@ export declare function getQualifiedRouteComponent(value: RouteNode): React.Comp
|
|
|
36
36
|
};
|
|
37
37
|
export declare function screenOptionsFactory(route: RouteNode, options?: ScreenProps['options']): ScreenProps['options'];
|
|
38
38
|
export declare function routeToScreen(route: RouteNode, { options, getId, ...props }?: Partial<ScreenProps>): React.JSX.Element;
|
|
39
|
-
export declare function getSingularId(name: string, options?:
|
|
40
|
-
params?: Record<string, any> | undefined;
|
|
41
|
-
}): string;
|
|
39
|
+
export declare function getSingularId(name: string, options?: Record<string, any>): string;
|
|
42
40
|
//# sourceMappingURL=useScreens.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useScreens.d.ts","sourceRoot":"","sources":["../src/useScreens.tsx"],"names":[],"mappings":"AAEA,OAAO,EAGL,KAAK,YAAY,EACjB,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,KAAK,SAAS,EACd,KAAK,eAAe,EACrB,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAsB,SAAS,EAAuC,MAAM,SAAS,CAAC;AAI7F,OAAO,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAK9C,MAAM,MAAM,WAAW,CACrB,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC1D,MAAM,SAAS,eAAe,GAAG,eAAe,EAChD,SAAS,SAAS,YAAY,GAAG,YAAY,IAC3C;IACF,4DAA4D;IAC5D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACpC,OAAO,CAAC,EACJ,QAAQ,GACR,CAAC,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,SAAS,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;QAAC,UAAU,EAAE,GAAG,CAAA;KAAE,KAAK,QAAQ,CAAC,CAAC;IAEvF,SAAS,CAAC,EACN,eAAe,CAAC,MAAM,EAAE,SAAS,CAAC,GAClC,CAAC,CAAC,IAAI,EAAE;QACN,KAAK,EAAE,SAAS,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;QACxC,UAAU,EAAE,GAAG,CAAC;KACjB,KAAK,eAAe,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC;IAE9C,KAAK,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;KAAE,KAAK,MAAM,GAAG,SAAS,CAAC;IAE7E,mBAAmB,CAAC,EAAE,eAAe,CAAC;CACvC,CAAC;AAEF,MAAM,MAAM,eAAe,GACvB,OAAO,GACP,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,mBAAmB,KAAK,MAAM,GAAG,SAAS,CAAC,CAAC;AA2FxE;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,WAAW,EAAE,EACpB,gBAAgB,EAAE,GAAG,CAAC,MAAM,CAAC,GAC5B,KAAK,CAAC,SAAS,EAAE,CAenB;AAkDD,mFAAmF;AACnF,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,SAAS;sCAiCtD,GAAG;;EA+BP;AAED,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,SAAS,EAChB,OAAO,CAAC,EAAE,WAAW,CAAC,SAAS,CAAC,GAC/B,WAAW,CAAC,SAAS,CAAC,CAqBxB;AAED,wBAAgB,aAAa,CAC3B,KAAK,EAAE,SAAS,EAChB,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,KAAK,EAAE,GAAE,OAAO,CAAC,WAAW,CAAM,qBAYxD;AAED,wBAAgB,aAAa,
|
|
1
|
+
{"version":3,"file":"useScreens.d.ts","sourceRoot":"","sources":["../src/useScreens.tsx"],"names":[],"mappings":"AAEA,OAAO,EAGL,KAAK,YAAY,EACjB,KAAK,eAAe,EACpB,KAAK,aAAa,EAClB,KAAK,SAAS,EACd,KAAK,eAAe,EACrB,MAAM,0BAA0B,CAAC;AAClC,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAsB,SAAS,EAAuC,MAAM,SAAS,CAAC;AAI7F,OAAO,EAAE,mBAAmB,EAAE,MAAM,SAAS,CAAC;AAK9C,MAAM,MAAM,WAAW,CACrB,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,EAC1D,MAAM,SAAS,eAAe,GAAG,eAAe,EAChD,SAAS,SAAS,YAAY,GAAG,YAAY,IAC3C;IACF,4DAA4D;IAC5D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,aAAa,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACpC,OAAO,CAAC,EACJ,QAAQ,GACR,CAAC,CAAC,IAAI,EAAE;QAAE,KAAK,EAAE,SAAS,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;QAAC,UAAU,EAAE,GAAG,CAAA;KAAE,KAAK,QAAQ,CAAC,CAAC;IAEvF,SAAS,CAAC,EACN,eAAe,CAAC,MAAM,EAAE,SAAS,CAAC,GAClC,CAAC,CAAC,IAAI,EAAE;QACN,KAAK,EAAE,SAAS,CAAC,aAAa,EAAE,MAAM,CAAC,CAAC;QACxC,UAAU,EAAE,GAAG,CAAC;KACjB,KAAK,eAAe,CAAC,MAAM,EAAE,SAAS,CAAC,CAAC,CAAC;IAE9C,KAAK,CAAC,EAAE,CAAC,EAAE,MAAM,EAAE,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAA;KAAE,KAAK,MAAM,GAAG,SAAS,CAAC;IAE7E,mBAAmB,CAAC,EAAE,eAAe,CAAC;CACvC,CAAC;AAEF,MAAM,MAAM,eAAe,GACvB,OAAO,GACP,CAAC,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,EAAE,mBAAmB,KAAK,MAAM,GAAG,SAAS,CAAC,CAAC;AA2FxE;;GAEG;AACH,wBAAgB,gBAAgB,CAC9B,KAAK,EAAE,WAAW,EAAE,EACpB,gBAAgB,EAAE,GAAG,CAAC,MAAM,CAAC,GAC5B,KAAK,CAAC,SAAS,EAAE,CAenB;AAkDD,mFAAmF;AACnF,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,SAAS;sCAiCtD,GAAG;;EA+BP;AAED,wBAAgB,oBAAoB,CAClC,KAAK,EAAE,SAAS,EAChB,OAAO,CAAC,EAAE,WAAW,CAAC,SAAS,CAAC,GAC/B,WAAW,CAAC,SAAS,CAAC,CAqBxB;AAED,wBAAgB,aAAa,CAC3B,KAAK,EAAE,SAAS,EAChB,EAAE,OAAO,EAAE,KAAK,EAAE,GAAG,KAAK,EAAE,GAAE,OAAO,CAAC,WAAW,CAAM,qBAYxD;AAED,wBAAgB,aAAa,CAAC,IAAI,EAAE,MAAM,EAAE,OAAO,GAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAM,UAa5E"}
|
package/build/useScreens.js
CHANGED
|
@@ -189,7 +189,7 @@ function screenOptionsFactory(route, options) {
|
|
|
189
189
|
...dynamicResult,
|
|
190
190
|
};
|
|
191
191
|
// Prevent generated screens from showing up in the tab bar.
|
|
192
|
-
if (route.
|
|
192
|
+
if (route.internal) {
|
|
193
193
|
output.tabBarItemStyle = { display: 'none' };
|
|
194
194
|
output.tabBarButton = () => null;
|
|
195
195
|
// TODO: React Navigation doesn't provide a way to prevent rendering the drawer item.
|
|
@@ -208,7 +208,7 @@ function getSingularId(name, options = {}) {
|
|
|
208
208
|
if (segment.startsWith('[...')) {
|
|
209
209
|
return options.params?.[segment.slice(4, -1)]?.join('/') || segment;
|
|
210
210
|
}
|
|
211
|
-
else if (segment.startsWith('[')) {
|
|
211
|
+
else if (segment.startsWith('[') && segment.endsWith(']')) {
|
|
212
212
|
return options.params?.[segment.slice(1, -1)] || segment;
|
|
213
213
|
}
|
|
214
214
|
else {
|
package/build/useScreens.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useScreens.js","sourceRoot":"","sources":["../src/useScreens.tsx"],"names":[],"mappings":"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","sourcesContent":["'use client';\n\nimport {\n useIsFocused,\n useStateForPath,\n type EventMapBase,\n type NavigationState,\n type ParamListBase,\n type RouteProp,\n type ScreenListeners,\n} from '@react-navigation/native';\nimport React from 'react';\n\nimport { LoadedRoute, Route, RouteNode, sortRoutesWithInitial, useRouteNode } from './Route';\nimport { useExpoRouterStore } from './global-state/storeContext';\nimport EXPO_ROUTER_IMPORT_MODE from './import-mode';\nimport { Screen } from './primitives';\nimport { UnknownOutputParams } from './types';\nimport { EmptyRoute } from './views/EmptyRoute';\nimport { SuspenseFallback } from './views/SuspenseFallback';\nimport { Try } from './views/Try';\n\nexport type ScreenProps<\n TOptions extends Record<string, any> = Record<string, any>,\n TState extends NavigationState = NavigationState,\n TEventMap extends EventMapBase = EventMapBase,\n> = {\n /** Name is required when used inside a Layout component. */\n name?: string;\n /**\n * Redirect to the nearest sibling route.\n * If all children are `redirect={true}`, the layout will render `null` as there are no children to render.\n */\n redirect?: boolean;\n initialParams?: Record<string, any>;\n options?:\n | TOptions\n | ((prop: { route: RouteProp<ParamListBase, string>; navigation: any }) => TOptions);\n\n listeners?:\n | ScreenListeners<TState, TEventMap>\n | ((prop: {\n route: RouteProp<ParamListBase, string>;\n navigation: any;\n }) => ScreenListeners<TState, TEventMap>);\n\n getId?: ({ params }: { params?: Record<string, any> }) => string | undefined;\n\n dangerouslySingular?: SingularOptions;\n};\n\nexport type SingularOptions =\n | boolean\n | ((name: string, params: UnknownOutputParams) => string | undefined);\n\nfunction getSortedChildren(\n children: RouteNode[],\n order: ScreenProps[] = [],\n initialRouteName?: string\n): { route: RouteNode; props: Partial<ScreenProps> }[] {\n if (!order?.length) {\n return children\n .sort(sortRoutesWithInitial(initialRouteName))\n .map((route) => ({ route, props: {} }));\n }\n const entries = [...children];\n\n const ordered = order\n .map(\n ({\n name,\n redirect,\n initialParams,\n listeners,\n options,\n getId,\n dangerouslySingular: singular,\n }) => {\n if (!entries.length) {\n console.warn(\n `[Layout children]: Too many screens defined. Route \"${name}\" is extraneous.`\n );\n return null;\n }\n const matchIndex = entries.findIndex((child) => child.route === name);\n if (matchIndex === -1) {\n console.warn(\n `[Layout children]: No route named \"${name}\" exists in nested children:`,\n children.map(({ route }) => route)\n );\n return null;\n } else {\n // Get match and remove from entries\n const match = entries[matchIndex];\n entries.splice(matchIndex, 1);\n\n // Ensure to return null after removing from entries.\n if (redirect) {\n if (typeof redirect === 'string') {\n throw new Error(`Redirecting to a specific route is not supported yet.`);\n }\n return null;\n }\n\n if (getId) {\n console.warn(\n `Deprecated: prop 'getId' on screen ${name} is deprecated. Please rename the prop to 'dangerouslySingular'`\n );\n if (singular) {\n console.warn(\n `Screen ${name} cannot use both getId and dangerouslySingular together.`\n );\n }\n } else if (singular) {\n // If singular is set, use it as the getId function.\n if (typeof singular === 'string') {\n getId = () => singular;\n } else if (typeof singular === 'function' && name) {\n getId = (options) => singular(name, options.params || {});\n } else if (singular === true && name) {\n getId = (options) => getSingularId(name, options);\n }\n }\n\n return {\n route: match,\n props: { initialParams, listeners, options, getId },\n };\n }\n }\n )\n .filter(Boolean) as {\n route: RouteNode;\n props: Partial<ScreenProps>;\n }[];\n\n // Add any remaining children\n ordered.push(\n ...entries.sort(sortRoutesWithInitial(initialRouteName)).map((route) => ({ route, props: {} }))\n );\n\n return ordered;\n}\n\n/**\n * @returns React Navigation screens sorted by the `route` property.\n */\nexport function useSortedScreens(\n order: ScreenProps[],\n protectedScreens: Set<string>\n): React.ReactNode[] {\n const node = useRouteNode();\n\n const sorted = node?.children?.length\n ? getSortedChildren(node.children, order, node.initialRouteName)\n : [];\n return React.useMemo(\n () =>\n sorted\n .filter((item) => !protectedScreens.has(item.route.route))\n .map((value) => {\n return routeToScreen(value.route, value.props);\n }),\n [sorted, protectedScreens]\n );\n}\n\nfunction fromImport(value: RouteNode, { ErrorBoundary, ...component }: LoadedRoute) {\n // If possible, add a more helpful display name for the component stack to improve debugging of React errors such as `Text strings must be rendered within a <Text> component.`.\n if (component?.default && __DEV__) {\n component.default.displayName ??= `${component.default.name ?? 'Route'}(${value.contextKey})`;\n }\n\n if (ErrorBoundary) {\n const Wrapped = React.forwardRef((props: any, ref: any) => {\n const children = React.createElement(component.default || EmptyRoute, {\n ...props,\n ref,\n });\n return <Try catch={ErrorBoundary}>{children}</Try>;\n });\n\n if (__DEV__) {\n Wrapped.displayName = `ErrorBoundary(${value.contextKey})`;\n }\n\n return {\n default: Wrapped,\n };\n }\n if (process.env.NODE_ENV !== 'production') {\n if (\n typeof component.default === 'object' &&\n component.default &&\n Object.keys(component.default).length === 0\n ) {\n return { default: EmptyRoute };\n }\n }\n\n return { default: component.default };\n}\n\nfunction fromLoadedRoute(value: RouteNode, res: LoadedRoute) {\n if (!(res instanceof Promise)) {\n return fromImport(value, res);\n }\n\n return res.then(fromImport.bind(null, value));\n}\n\n// TODO: Maybe there's a more React-y way to do this?\n// Without this store, the process enters a recursive loop.\nconst qualifiedStore = new WeakMap<RouteNode, React.ComponentType<any>>();\n\n/** Wrap the component with various enhancements and add access to child routes. */\nexport function getQualifiedRouteComponent(value: RouteNode) {\n if (qualifiedStore.has(value)) {\n return qualifiedStore.get(value)!;\n }\n\n let ScreenComponent:\n | React.ForwardRefExoticComponent<React.RefAttributes<unknown>>\n | React.ComponentType<any>;\n\n // TODO: This ensures sync doesn't use React.lazy, but it's not ideal.\n if (EXPO_ROUTER_IMPORT_MODE === 'lazy') {\n ScreenComponent = React.lazy(async () => {\n const res = value.loadRoute();\n return fromLoadedRoute(value, res) as Promise<{\n default: React.ComponentType<any>;\n }>;\n });\n\n if (__DEV__) {\n ScreenComponent.displayName = `AsyncRoute(${value.route})`;\n }\n } else {\n const res = value.loadRoute();\n ScreenComponent = fromImport(value, res).default!;\n }\n function BaseRoute({\n // Remove these React Navigation props to\n // enforce usage of expo-router hooks (where the query params are correct).\n route,\n navigation,\n\n // Pass all other props to the component\n ...props\n }: any) {\n const stateForPath = useStateForPath();\n const isFocused = useIsFocused();\n const store = useExpoRouterStore();\n\n if (isFocused) {\n const state = navigation.getState();\n const isLeaf = !('state' in state.routes[state.index]);\n if (isLeaf && stateForPath) store.setFocusedState(stateForPath);\n }\n\n return (\n <Route node={value} route={route}>\n <React.Suspense fallback={<SuspenseFallback route={value} />}>\n <ScreenComponent\n {...props}\n // Expose the template segment path, e.g. `(home)`, `[foo]`, `index`\n // the intention is to make it possible to deduce shared routes.\n segment={value.route}\n />\n </React.Suspense>\n </Route>\n );\n }\n\n if (__DEV__) {\n BaseRoute.displayName = `Route(${value.route})`;\n }\n\n qualifiedStore.set(value, BaseRoute);\n return BaseRoute;\n}\n\nexport function screenOptionsFactory(\n route: RouteNode,\n options?: ScreenProps['options']\n): ScreenProps['options'] {\n return (args) => {\n // Only eager load generated components\n const staticOptions = route.generated ? route.loadRoute()?.getNavOptions : null;\n const staticResult = typeof staticOptions === 'function' ? staticOptions(args) : staticOptions;\n const dynamicResult = typeof options === 'function' ? options?.(args) : options;\n const output = {\n ...staticResult,\n ...dynamicResult,\n };\n\n // Prevent generated screens from showing up in the tab bar.\n if (route.generated) {\n output.tabBarItemStyle = { display: 'none' };\n output.tabBarButton = () => null;\n // TODO: React Navigation doesn't provide a way to prevent rendering the drawer item.\n output.drawerItemStyle = { height: 0, display: 'none' };\n }\n\n return output;\n };\n}\n\nexport function routeToScreen(\n route: RouteNode,\n { options, getId, ...props }: Partial<ScreenProps> = {}\n) {\n return (\n <Screen\n {...props}\n name={route.route}\n key={route.route}\n getId={getId}\n options={screenOptionsFactory(route, options)}\n getComponent={() => getQualifiedRouteComponent(route)}\n />\n );\n}\n\nexport function getSingularId(\n name: string,\n options: { params?: Record<string, any> | undefined } = {}\n) {\n return name\n .split('/')\n .map((segment) => {\n if (segment.startsWith('[...')) {\n return options.params?.[segment.slice(4, -1)]?.join('/') || segment;\n } else if (segment.startsWith('[')) {\n return options.params?.[segment.slice(1, -1)] || segment;\n } else {\n return segment;\n }\n })\n .join('/');\n}\n"]}
|
|
1
|
+
{"version":3,"file":"useScreens.js","sourceRoot":"","sources":["../src/useScreens.tsx"],"names":[],"mappings":"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","sourcesContent":["'use client';\n\nimport {\n useIsFocused,\n useStateForPath,\n type EventMapBase,\n type NavigationState,\n type ParamListBase,\n type RouteProp,\n type ScreenListeners,\n} from '@react-navigation/native';\nimport React from 'react';\n\nimport { LoadedRoute, Route, RouteNode, sortRoutesWithInitial, useRouteNode } from './Route';\nimport { useExpoRouterStore } from './global-state/storeContext';\nimport EXPO_ROUTER_IMPORT_MODE from './import-mode';\nimport { Screen } from './primitives';\nimport { UnknownOutputParams } from './types';\nimport { EmptyRoute } from './views/EmptyRoute';\nimport { SuspenseFallback } from './views/SuspenseFallback';\nimport { Try } from './views/Try';\n\nexport type ScreenProps<\n TOptions extends Record<string, any> = Record<string, any>,\n TState extends NavigationState = NavigationState,\n TEventMap extends EventMapBase = EventMapBase,\n> = {\n /** Name is required when used inside a Layout component. */\n name?: string;\n /**\n * Redirect to the nearest sibling route.\n * If all children are `redirect={true}`, the layout will render `null` as there are no children to render.\n */\n redirect?: boolean;\n initialParams?: Record<string, any>;\n options?:\n | TOptions\n | ((prop: { route: RouteProp<ParamListBase, string>; navigation: any }) => TOptions);\n\n listeners?:\n | ScreenListeners<TState, TEventMap>\n | ((prop: {\n route: RouteProp<ParamListBase, string>;\n navigation: any;\n }) => ScreenListeners<TState, TEventMap>);\n\n getId?: ({ params }: { params?: Record<string, any> }) => string | undefined;\n\n dangerouslySingular?: SingularOptions;\n};\n\nexport type SingularOptions =\n | boolean\n | ((name: string, params: UnknownOutputParams) => string | undefined);\n\nfunction getSortedChildren(\n children: RouteNode[],\n order: ScreenProps[] = [],\n initialRouteName?: string\n): { route: RouteNode; props: Partial<ScreenProps> }[] {\n if (!order?.length) {\n return children\n .sort(sortRoutesWithInitial(initialRouteName))\n .map((route) => ({ route, props: {} }));\n }\n const entries = [...children];\n\n const ordered = order\n .map(\n ({\n name,\n redirect,\n initialParams,\n listeners,\n options,\n getId,\n dangerouslySingular: singular,\n }) => {\n if (!entries.length) {\n console.warn(\n `[Layout children]: Too many screens defined. Route \"${name}\" is extraneous.`\n );\n return null;\n }\n const matchIndex = entries.findIndex((child) => child.route === name);\n if (matchIndex === -1) {\n console.warn(\n `[Layout children]: No route named \"${name}\" exists in nested children:`,\n children.map(({ route }) => route)\n );\n return null;\n } else {\n // Get match and remove from entries\n const match = entries[matchIndex];\n entries.splice(matchIndex, 1);\n\n // Ensure to return null after removing from entries.\n if (redirect) {\n if (typeof redirect === 'string') {\n throw new Error(`Redirecting to a specific route is not supported yet.`);\n }\n return null;\n }\n\n if (getId) {\n console.warn(\n `Deprecated: prop 'getId' on screen ${name} is deprecated. Please rename the prop to 'dangerouslySingular'`\n );\n if (singular) {\n console.warn(\n `Screen ${name} cannot use both getId and dangerouslySingular together.`\n );\n }\n } else if (singular) {\n // If singular is set, use it as the getId function.\n if (typeof singular === 'string') {\n getId = () => singular;\n } else if (typeof singular === 'function' && name) {\n getId = (options) => singular(name, options.params || {});\n } else if (singular === true && name) {\n getId = (options) => getSingularId(name, options);\n }\n }\n\n return {\n route: match,\n props: { initialParams, listeners, options, getId },\n };\n }\n }\n )\n .filter(Boolean) as {\n route: RouteNode;\n props: Partial<ScreenProps>;\n }[];\n\n // Add any remaining children\n ordered.push(\n ...entries.sort(sortRoutesWithInitial(initialRouteName)).map((route) => ({ route, props: {} }))\n );\n\n return ordered;\n}\n\n/**\n * @returns React Navigation screens sorted by the `route` property.\n */\nexport function useSortedScreens(\n order: ScreenProps[],\n protectedScreens: Set<string>\n): React.ReactNode[] {\n const node = useRouteNode();\n\n const sorted = node?.children?.length\n ? getSortedChildren(node.children, order, node.initialRouteName)\n : [];\n return React.useMemo(\n () =>\n sorted\n .filter((item) => !protectedScreens.has(item.route.route))\n .map((value) => {\n return routeToScreen(value.route, value.props);\n }),\n [sorted, protectedScreens]\n );\n}\n\nfunction fromImport(value: RouteNode, { ErrorBoundary, ...component }: LoadedRoute) {\n // If possible, add a more helpful display name for the component stack to improve debugging of React errors such as `Text strings must be rendered within a <Text> component.`.\n if (component?.default && __DEV__) {\n component.default.displayName ??= `${component.default.name ?? 'Route'}(${value.contextKey})`;\n }\n\n if (ErrorBoundary) {\n const Wrapped = React.forwardRef((props: any, ref: any) => {\n const children = React.createElement(component.default || EmptyRoute, {\n ...props,\n ref,\n });\n return <Try catch={ErrorBoundary}>{children}</Try>;\n });\n\n if (__DEV__) {\n Wrapped.displayName = `ErrorBoundary(${value.contextKey})`;\n }\n\n return {\n default: Wrapped,\n };\n }\n if (process.env.NODE_ENV !== 'production') {\n if (\n typeof component.default === 'object' &&\n component.default &&\n Object.keys(component.default).length === 0\n ) {\n return { default: EmptyRoute };\n }\n }\n\n return { default: component.default };\n}\n\nfunction fromLoadedRoute(value: RouteNode, res: LoadedRoute) {\n if (!(res instanceof Promise)) {\n return fromImport(value, res);\n }\n\n return res.then(fromImport.bind(null, value));\n}\n\n// TODO: Maybe there's a more React-y way to do this?\n// Without this store, the process enters a recursive loop.\nconst qualifiedStore = new WeakMap<RouteNode, React.ComponentType<any>>();\n\n/** Wrap the component with various enhancements and add access to child routes. */\nexport function getQualifiedRouteComponent(value: RouteNode) {\n if (qualifiedStore.has(value)) {\n return qualifiedStore.get(value)!;\n }\n\n let ScreenComponent:\n | React.ForwardRefExoticComponent<React.RefAttributes<unknown>>\n | React.ComponentType<any>;\n\n // TODO: This ensures sync doesn't use React.lazy, but it's not ideal.\n if (EXPO_ROUTER_IMPORT_MODE === 'lazy') {\n ScreenComponent = React.lazy(async () => {\n const res = value.loadRoute();\n return fromLoadedRoute(value, res) as Promise<{\n default: React.ComponentType<any>;\n }>;\n });\n\n if (__DEV__) {\n ScreenComponent.displayName = `AsyncRoute(${value.route})`;\n }\n } else {\n const res = value.loadRoute();\n ScreenComponent = fromImport(value, res).default!;\n }\n function BaseRoute({\n // Remove these React Navigation props to\n // enforce usage of expo-router hooks (where the query params are correct).\n route,\n navigation,\n\n // Pass all other props to the component\n ...props\n }: any) {\n const stateForPath = useStateForPath();\n const isFocused = useIsFocused();\n const store = useExpoRouterStore();\n\n if (isFocused) {\n const state = navigation.getState();\n const isLeaf = !('state' in state.routes[state.index]);\n if (isLeaf && stateForPath) store.setFocusedState(stateForPath);\n }\n\n return (\n <Route node={value} route={route}>\n <React.Suspense fallback={<SuspenseFallback route={value} />}>\n <ScreenComponent\n {...props}\n // Expose the template segment path, e.g. `(home)`, `[foo]`, `index`\n // the intention is to make it possible to deduce shared routes.\n segment={value.route}\n />\n </React.Suspense>\n </Route>\n );\n }\n\n if (__DEV__) {\n BaseRoute.displayName = `Route(${value.route})`;\n }\n\n qualifiedStore.set(value, BaseRoute);\n return BaseRoute;\n}\n\nexport function screenOptionsFactory(\n route: RouteNode,\n options?: ScreenProps['options']\n): ScreenProps['options'] {\n return (args) => {\n // Only eager load generated components\n const staticOptions = route.generated ? route.loadRoute()?.getNavOptions : null;\n const staticResult = typeof staticOptions === 'function' ? staticOptions(args) : staticOptions;\n const dynamicResult = typeof options === 'function' ? options?.(args) : options;\n const output = {\n ...staticResult,\n ...dynamicResult,\n };\n\n // Prevent generated screens from showing up in the tab bar.\n if (route.internal) {\n output.tabBarItemStyle = { display: 'none' };\n output.tabBarButton = () => null;\n // TODO: React Navigation doesn't provide a way to prevent rendering the drawer item.\n output.drawerItemStyle = { height: 0, display: 'none' };\n }\n\n return output;\n };\n}\n\nexport function routeToScreen(\n route: RouteNode,\n { options, getId, ...props }: Partial<ScreenProps> = {}\n) {\n return (\n <Screen\n {...props}\n name={route.route}\n key={route.route}\n getId={getId}\n options={screenOptionsFactory(route, options)}\n getComponent={() => getQualifiedRouteComponent(route)}\n />\n );\n}\n\nexport function getSingularId(name: string, options: Record<string, any> = {}) {\n return name\n .split('/')\n .map((segment) => {\n if (segment.startsWith('[...')) {\n return options.params?.[segment.slice(4, -1)]?.join('/') || segment;\n } else if (segment.startsWith('[') && segment.endsWith(']')) {\n return options.params?.[segment.slice(1, -1)] || segment;\n } else {\n return segment;\n }\n })\n .join('/');\n}\n"]}
|