expo-router 2.0.0-rc.9 → 2.0.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/build/ExpoRoot.d.ts.map +1 -1
- package/build/fork/getStateFromPath.d.ts +4 -0
- package/build/fork/getStateFromPath.d.ts.map +1 -1
- package/build/global-state/router-store.d.ts +2 -0
- package/build/global-state/router-store.d.ts.map +1 -1
- package/build/global-state/routing.d.ts +1 -0
- package/build/global-state/routing.d.ts.map +1 -1
- package/build/global-state/sort-routes.d.ts +1 -2
- package/build/global-state/sort-routes.d.ts.map +1 -1
- package/build/hooks.d.ts.map +1 -1
- package/build/imperative-api.d.ts.map +1 -1
- package/build/link/href.d.ts.map +1 -1
- package/build/onboard/Tutorial.d.ts.map +1 -1
- package/build/types.d.ts +2 -0
- package/build/types.d.ts.map +1 -1
- package/build/useDeprecated.d.ts +3 -0
- package/build/useDeprecated.d.ts.map +1 -0
- package/build/useScreens.d.ts +3 -0
- package/build/useScreens.d.ts.map +1 -1
- package/build/views/ErrorBoundary.d.ts.map +1 -1
- package/build/views/Screen.d.ts.map +1 -1
- package/build/views/Sitemap.d.ts.map +1 -1
- package/build/views/Splash.d.ts.map +1 -1
- package/build/views/Unmatched.d.ts.map +1 -1
- package/package.json +4 -4
- package/src/ExpoRoot.tsx +14 -2
- package/src/fork/getStateFromPath.ts +46 -19
- package/src/global-state/router-store.tsx +13 -6
- package/src/global-state/routing.ts +8 -1
- package/src/global-state/sort-routes.ts +2 -38
- package/src/hooks.ts +13 -9
- package/src/imperative-api.ts +1 -0
- package/src/link/href.ts +9 -7
- package/src/onboard/Tutorial.tsx +5 -11
- package/src/static/html.tsx +1 -1
- package/src/types.ts +2 -0
- package/src/useDeprecated.ts +35 -0
- package/src/useScreens.tsx +11 -2
- package/src/views/ErrorBoundary.tsx +1 -5
- package/src/views/Screen.tsx +17 -1
- package/src/views/Sitemap.tsx +3 -6
- package/src/views/Splash.tsx +5 -5
- package/src/views/Unmatched.tsx +4 -12
- package/types/react-native-web.d.ts +0 -2
package/build/ExpoRoot.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ExpoRoot.d.ts","sourceRoot":"","sources":["../src/ExpoRoot.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"ExpoRoot.d.ts","sourceRoot":"","sources":["../src/ExpoRoot.tsx"],"names":[],"mappings":"AAEA,OAAc,EAAE,iBAAiB,EAAE,SAAS,EAAY,MAAM,OAAO,CAAC;AAMtE,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAGzC,MAAM,MAAM,aAAa,GAAG;IAC1B,OAAO,EAAE,cAAc,CAAC;IACxB,QAAQ,CAAC,EAAE,GAAG,CAAC;IACf,OAAO,CAAC,EAAE,iBAAiB,CAAC;QAAE,QAAQ,EAAE,SAAS,CAAA;KAAE,CAAC,CAAC;CACtD,CAAC;AAqCF,wBAAgB,QAAQ,CAAC,EACvB,OAAO,EAAE,aAAwB,EACjC,GAAG,KAAK,EACT,EAAE,aAAa,eA2Bf"}
|
|
@@ -13,6 +13,10 @@ type InitialRouteConfig = {
|
|
|
13
13
|
export type ResultState = PartialState<NavigationState> & {
|
|
14
14
|
state?: ResultState;
|
|
15
15
|
};
|
|
16
|
+
export declare function getUrlWithReactNavigationConcessions(path: string): {
|
|
17
|
+
nonstandardPathname: string;
|
|
18
|
+
inputPathnameWithoutHash: string;
|
|
19
|
+
};
|
|
16
20
|
/**
|
|
17
21
|
* Utility to parse a path string to initial state object accepted by the container.
|
|
18
22
|
* This is useful for deep linking when we need to handle the incoming URL.
|
|
@@ -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,EAEV,eAAe,EACf,YAAY,EACb,MAAM,2BAA2B,CAAC;
|
|
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,EAEV,eAAe,EACf,YAAY,EACb,MAAM,2BAA2B,CAAC;AAKnC,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;;;EAYhE;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,EAC/D,OAAO,CAAC,EAAE,OAAO,CAAC,SAAS,CAAC;;;;;;;;;;;;;;EA+C7B"}
|
|
@@ -15,6 +15,7 @@ export declare class RouterStore {
|
|
|
15
15
|
rootComponent: ComponentType;
|
|
16
16
|
linking: ExpoLinkingOptions | undefined;
|
|
17
17
|
isReady: boolean;
|
|
18
|
+
private hasAttemptedToHideSplash;
|
|
18
19
|
initialState: ResultState | undefined;
|
|
19
20
|
rootState: ResultState | undefined;
|
|
20
21
|
nextState: ResultState | undefined;
|
|
@@ -26,6 +27,7 @@ export declare class RouterStore {
|
|
|
26
27
|
linkTo: (href: string, event?: string | undefined) => void;
|
|
27
28
|
getSortedRoutes: () => RouteNode[];
|
|
28
29
|
goBack: () => void;
|
|
30
|
+
canGoBack: () => boolean;
|
|
29
31
|
push: (url: import("../link/href").Href) => void;
|
|
30
32
|
replace: (url: import("../link/href").Href) => void;
|
|
31
33
|
setParams: (params?: Record<string, string | number> | undefined) => any;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"router-store.d.ts","sourceRoot":"","sources":["../../src/global-state/router-store.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,iCAAiC,EAGlC,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAiC,aAAa,EAAY,MAAM,OAAO,CAAC;AAE/E,OAAO,EAAE,SAAS,EAAyB,MAAM,qBAAqB,CAAC;AACvE,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAErC,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAoB,MAAM,qBAAqB,CAAC;AAE3E,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAM1C;;;;GAIG;AACH,qBAAa,WAAW;IACtB,SAAS,EAAG,SAAS,GAAG,IAAI,CAAC;IAC7B,aAAa,EAAG,aAAa,CAAC;IAC9B,OAAO,EAAE,kBAAkB,GAAG,SAAS,CAAC;IACxC,OAAO,EAAE,OAAO,CAAS;
|
|
1
|
+
{"version":3,"file":"router-store.d.ts","sourceRoot":"","sources":["../../src/global-state/router-store.tsx"],"names":[],"mappings":"AAAA,OAAO,EACL,iCAAiC,EAGlC,MAAM,0BAA0B,CAAC;AAClC,OAAO,EAAiC,aAAa,EAAY,MAAM,OAAO,CAAC;AAE/E,OAAO,EAAE,SAAS,EAAyB,MAAM,qBAAqB,CAAC;AACvE,OAAO,EAAE,SAAS,EAAE,MAAM,UAAU,CAAC;AAErC,OAAO,EAAE,WAAW,EAAE,MAAM,0BAA0B,CAAC;AACvD,OAAO,EAAE,kBAAkB,EAAoB,MAAM,qBAAqB,CAAC;AAE3E,OAAO,EAAE,cAAc,EAAE,MAAM,UAAU,CAAC;AAM1C;;;;GAIG;AACH,qBAAa,WAAW;IACtB,SAAS,EAAG,SAAS,GAAG,IAAI,CAAC;IAC7B,aAAa,EAAG,aAAa,CAAC;IAC9B,OAAO,EAAE,kBAAkB,GAAG,SAAS,CAAC;IACxC,OAAO,EAAE,OAAO,CAAS;IACzB,OAAO,CAAC,wBAAwB,CAAkB;IAElD,YAAY,EAAE,WAAW,GAAG,SAAS,CAAC;IACtC,SAAS,EAAE,WAAW,GAAG,SAAS,CAAC;IACnC,SAAS,EAAE,WAAW,GAAG,SAAS,CAAC;IACnC,SAAS,CAAC,EAAE,SAAS,GAAG,SAAS,CAAC;IAElC,aAAa,EAAG,iCAAiC,CAAC,eAAe,CAAC,aAAa,CAAC,CAAC;IACjF,yBAAyB,EAAG,MAAM,IAAI,CAAC;IAEvC,oBAAoB,YAAiB,IAAI,EAAI;IAC7C,gBAAgB,YAAiB,IAAI,EAAI;IAEzC,MAAM,qDAAqB;IAC3B,eAAe,oBAA8B;IAC7C,MAAM,aAAqB;IAC3B,SAAS,gBAAwB;IACjC,IAAI,6CAAmB;IACvB,OAAO,6CAAsB;IAC7B,SAAS,gEAAwB;IAEjC,UAAU,CACR,OAAO,EAAE,cAAc,EACvB,aAAa,EAAE,iCAAiC,CAAC,eAAe,CAAC,aAAa,CAAC,EAC/E,eAAe,CAAC,EAAE,GAAG;IAwGvB,WAAW,CAAC,KAAK,EAAE,WAAW,EAAE,SAAS,cAAQ;IAWjD,YAAY,CAAC,KAAK,EAAE,WAAW;IAgB/B,kBAAkB;IAIlB,uEAAuE;IACvE,OAAO,aAEL;IACF,oBAAoB,eAAgB,MAAM,IAAI,mBAG5C;IACF,gBAAgB,eAAgB,MAAM,IAAI,mBAGxC;IACF,QAAQ,aAEN;IACF,iBAAiB,oBAEf;IACF,iBAAiB,kBAEf;CACH;AAED,eAAO,MAAM,KAAK,aAAoB,CAAC;AAEvC,wBAAgB,aAAa,gBAM5B;AAaD,wBAAgB,iBAAiB,gBAOhC;AAED,wBAAgB,iBAAiB,cAOhC;AAED,wBAAgB,uBAAuB,CACrC,OAAO,EAAE,cAAc,EACvB,eAAe,EAAE,GAAG,GAAG,SAAS,eASjC"}
|
|
@@ -5,6 +5,7 @@ import type { RouterStore } from "./router-store";
|
|
|
5
5
|
export declare function push(this: RouterStore, url: Href): void;
|
|
6
6
|
export declare function replace(this: RouterStore, url: Href): void;
|
|
7
7
|
export declare function goBack(this: RouterStore): void;
|
|
8
|
+
export declare function canGoBack(this: RouterStore): boolean;
|
|
8
9
|
export declare function setParams(this: RouterStore, params?: Record<string, string | number>): any;
|
|
9
10
|
export declare function linkTo(this: RouterStore, href: string, event?: string): void;
|
|
10
11
|
/** @returns `true` if the action is moving to the first screen of all the navigators in the action. */
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"routing.d.ts","sourceRoot":"","sources":["../../src/global-state/routing.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,kBAAkB,EAEnB,MAAM,wBAAwB,CAAC;AAIhC,OAAO,EAAE,IAAI,EAAe,MAAM,cAAc,CAAC;AAEjD,OAAO,EACL,cAAc,EAKf,MAAM,yBAAyB,CAAC;AAEjC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;
|
|
1
|
+
{"version":3,"file":"routing.d.ts","sourceRoot":"","sources":["../../src/global-state/routing.ts"],"names":[],"mappings":"AAAA,OAAO,EAEL,kBAAkB,EAEnB,MAAM,wBAAwB,CAAC;AAIhC,OAAO,EAAE,IAAI,EAAe,MAAM,cAAc,CAAC;AAEjD,OAAO,EACL,cAAc,EAKf,MAAM,yBAAyB,CAAC;AAEjC,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAUlD,wBAAgB,IAAI,CAAC,IAAI,EAAE,WAAW,EAAE,GAAG,EAAE,IAAI,QAEhD;AAED,wBAAgB,OAAO,CAAC,IAAI,EAAE,WAAW,EAAE,GAAG,EAAE,IAAI,QAEnD;AAED,wBAAgB,MAAM,CAAC,IAAI,EAAE,WAAW,QAGvC;AAED,wBAAgB,SAAS,CAAC,IAAI,EAAE,WAAW,GAAG,OAAO,CAGpD;AAED,wBAAgB,SAAS,CACvB,IAAI,EAAE,WAAW,EACjB,MAAM,GAAE,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAAM,OAI7C;AAED,wBAAgB,MAAM,CAAC,IAAI,EAAE,WAAW,EAAE,IAAI,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,MAAM,QAwHrE;AAED,uGAAuG;AACvG,wBAAgB,sBAAsB,CACpC,MAAM,EAAE,UAAU,CAAC,OAAO,kBAAkB,CAAC,GAC5C,MAAM,IAAI,cAAc,CAqB1B"}
|
|
@@ -1,4 +1,3 @@
|
|
|
1
|
-
import { RouteNode } from "../Route";
|
|
2
1
|
import type { RouterStore } from "./router-store";
|
|
3
|
-
export declare function getSortedRoutes(this: RouterStore): RouteNode[];
|
|
2
|
+
export declare function getSortedRoutes(this: RouterStore): import("../Route").RouteNode[];
|
|
4
3
|
//# sourceMappingURL=sort-routes.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"sort-routes.d.ts","sourceRoot":"","sources":["../../src/global-state/sort-routes.ts"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"sort-routes.d.ts","sourceRoot":"","sources":["../../src/global-state/sort-routes.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,EAAE,WAAW,EAAE,MAAM,gBAAgB,CAAC;AAElD,wBAAgB,eAAe,CAAC,IAAI,EAAE,WAAW,kCAQhD"}
|
package/build/hooks.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;
|
|
1
|
+
{"version":3,"file":"hooks.d.ts","sourceRoot":"","sources":["../src/hooks.ts"],"names":[],"mappings":"AAYA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAGjC,KAAK,YAAY,GAAG,MAAM,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,EAAE,CAAC,CAAC;AAEtD,wBAAgB,sBAAsB,kDAErC;AAED,wBAAgB,YAAY,2CAE3B;AAED,wBAAgB,iBAAiB,oGAEhC;AAGD,wBAAgB,OAAO,WAGtB;AAED,wBAAgB,SAAS,IAAI,MAAM,CAYlC;AAED;;;GAGG;AACH,wBAAgB,qBAAqB,IAAI,MAAM,CAE9C;AAED;;;;;;;;;;;;;;;;;;GAkBG;AACH,wBAAgB,WAAW,CACzB,SAAS,SAAS,MAAM,EAAE,GAAG,MAAM,EAAE,KAClC,SAAS,CAEb;AAED,kEAAkE;AAClE,wBAAgB,WAAW,IAAI,MAAM,CAEpC;AAED;;;;;;;;GAQG;AACH,wBAAgB,qBAAqB,CACnC,OAAO,SAAS,YAAY,GAAG,YAAY,KACxC,OAAO,CAAC,OAAO,CAAC,CAEpB;AAED,qDAAqD;AACrD,wBAAgB,eAAe,CAC7B,OAAO,SAAS,YAAY,GAAG,YAAY,KACxC,OAAO,CAAC,OAAO,CAAC,CAEpB;AAED;;;;;GAKG;AACH,wBAAgB,oBAAoB,CAClC,OAAO,SAAS,YAAY,GAAG,YAAY,KACxC,OAAO,CAAC,OAAO,CAAC,CAEpB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"imperative-api.d.ts","sourceRoot":"","sources":["../src/imperative-api.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAEjC,eAAO,MAAM,MAAM,EAAE,
|
|
1
|
+
{"version":3,"file":"imperative-api.d.ts","sourceRoot":"","sources":["../src/imperative-api.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,MAAM,EAAE,MAAM,SAAS,CAAC;AAEjC,eAAO,MAAM,MAAM,EAAE,MAMpB,CAAC"}
|
package/build/link/href.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"href.d.ts","sourceRoot":"","sources":["../../src/link/href.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,IAAI,GAAG,MAAM,GAAG,UAAU,CAAC;AAEvC,MAAM,WAAW,UAAU;IACzB,oDAAoD;IACpD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qCAAqC;IACrC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC9B;AAED,oEAAoE;AACpE,eAAO,MAAM,WAAW,SAAU,IAAI,KAAG,
|
|
1
|
+
{"version":3,"file":"href.d.ts","sourceRoot":"","sources":["../../src/link/href.ts"],"names":[],"mappings":"AAAA,MAAM,MAAM,IAAI,GAAG,MAAM,GAAG,UAAU,CAAC;AAEvC,MAAM,WAAW,UAAU;IACzB,oDAAoD;IACpD,QAAQ,CAAC,EAAE,MAAM,CAAC;IAClB,qCAAqC;IACrC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;CAC9B;AAED,oEAAoE;AACpE,eAAO,MAAM,WAAW,SAAU,IAAI,KAAG,MAaxC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Tutorial.d.ts","sourceRoot":"","sources":["../../src/onboard/Tutorial.tsx"],"names":[],"mappings":";AAqCA,wBAAgB,QAAQ,
|
|
1
|
+
{"version":3,"file":"Tutorial.d.ts","sourceRoot":"","sources":["../../src/onboard/Tutorial.tsx"],"names":[],"mappings":";AAqCA,wBAAgB,QAAQ,gBAqCvB"}
|
package/build/types.d.ts
CHANGED
|
@@ -18,6 +18,8 @@ export type Router = {
|
|
|
18
18
|
replace: (href: Href) => void;
|
|
19
19
|
/** Go back in the history. */
|
|
20
20
|
back: () => void;
|
|
21
|
+
/** If there's history that supports invoking the `back` function. */
|
|
22
|
+
canGoBack: () => boolean;
|
|
21
23
|
/** Update the current route query params. */
|
|
22
24
|
setParams: (params?: Record<string, string>) => void;
|
|
23
25
|
};
|
package/build/types.d.ts.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAGnC,MAAM,WAAW,cAAc;IAC7B,4CAA4C;IAC5C,IAAI,IAAI,MAAM,EAAE,CAAC;IACjB,CAAC,EAAE,EAAE,MAAM,GAAG,GAAG,CAAC;IAClB,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,GAAG,CAAC,CAAC;IACnB,0EAA0E;IAC1E,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,qEAAqE;IACrE,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,yFAAyF;AACzF,MAAM,MAAM,WAAW,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,CAAC,IAAI,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,GACxD,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AAEtB,MAAM,MAAM,MAAM,GAAG;IACnB,qCAAqC;IACrC,IAAI,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;IAC3B,0DAA0D;IAC1D,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;IAC9B,8BAA8B;IAC9B,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,6CAA6C;IAC7C,SAAS,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,IAAI,CAAC;CACtD,CAAC"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../src/types.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,IAAI,EAAE,MAAM,aAAa,CAAC;AAGnC,MAAM,WAAW,cAAc;IAC7B,4CAA4C;IAC5C,IAAI,IAAI,MAAM,EAAE,CAAC;IACjB,CAAC,EAAE,EAAE,MAAM,GAAG,GAAG,CAAC;IAClB,CAAC,CAAC,EAAE,EAAE,EAAE,MAAM,GAAG,CAAC,CAAC;IACnB,0EAA0E;IAC1E,OAAO,CAAC,EAAE,EAAE,MAAM,GAAG,MAAM,CAAC;IAC5B,qEAAqE;IACrE,EAAE,EAAE,MAAM,CAAC;CACZ;AAED,yFAAyF;AACzF,MAAM,MAAM,WAAW,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,CAAC,IAAI,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,GACxD,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AAEtB,MAAM,MAAM,MAAM,GAAG;IACnB,qCAAqC;IACrC,IAAI,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;IAC3B,0DAA0D;IAC1D,OAAO,EAAE,CAAC,IAAI,EAAE,IAAI,KAAK,IAAI,CAAC;IAC9B,8BAA8B;IAC9B,IAAI,EAAE,MAAM,IAAI,CAAC;IACjB,qEAAqE;IACrE,SAAS,EAAE,MAAM,OAAO,CAAC;IACzB,6CAA6C;IAC7C,SAAS,EAAE,CAAC,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,KAAK,IAAI,CAAC;CACtD,CAAC"}
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"useDeprecated.d.ts","sourceRoot":"","sources":["../src/useDeprecated.ts"],"names":[],"mappings":"AAaA,wBAAgB,WAAW,CACzB,OAAO,EAAE,MAAM,EACf,KAAK,GAAE,OAAc,EACrB,GAAG,SAAU,QAUd;AAED,wBAAgB,aAAa,CAC3B,OAAO,EAAE,MAAM,EACf,KAAK,GAAE,OAAc,EACrB,GAAG,SAAU,QAGd"}
|
package/build/useScreens.d.ts
CHANGED
|
@@ -13,6 +13,9 @@ export type ScreenProps<TOptions extends Record<string, any> = Record<string, an
|
|
|
13
13
|
};
|
|
14
14
|
options?: TOptions;
|
|
15
15
|
listeners?: any;
|
|
16
|
+
getId?: ({ params, }: {
|
|
17
|
+
params?: Record<string, any> | undefined;
|
|
18
|
+
}) => string | undefined;
|
|
16
19
|
};
|
|
17
20
|
/**
|
|
18
21
|
* @returns React Navigation screens sorted by the `route` property.
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"useScreens.d.ts","sourceRoot":"","sources":["../src/useScreens.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAIL,SAAS,EAGV,MAAM,SAAS,CAAC;AAOjB,MAAM,MAAM,WAAW,CACrB,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,IACxD;IACF,4DAA4D;IAC5D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,aAAa,CAAC,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;KAAE,CAAC;IACvC,OAAO,CAAC,EAAE,QAAQ,CAAC;IAGnB,SAAS,CAAC,EAAE,GAAG,CAAC;
|
|
1
|
+
{"version":3,"file":"useScreens.d.ts","sourceRoot":"","sources":["../src/useScreens.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAIL,SAAS,EAGV,MAAM,SAAS,CAAC;AAOjB,MAAM,MAAM,WAAW,CACrB,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,IACxD;IACF,4DAA4D;IAC5D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd;;;OAGG;IACH,QAAQ,CAAC,EAAE,OAAO,CAAC;IACnB,aAAa,CAAC,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;KAAE,CAAC;IACvC,OAAO,CAAC,EAAE,QAAQ,CAAC;IAGnB,SAAS,CAAC,EAAE,GAAG,CAAC;IAEhB,KAAK,CAAC,EAAE,CAAC,EACP,MAAM,GACP,EAAE;QACD,MAAM,CAAC,EAAE,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,SAAS,CAAC;KAC1C,KAAK,MAAM,GAAG,SAAS,CAAC;CAC1B,CAAC;AAiEF;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,WAAW,EAAE,GAAG,KAAK,CAAC,SAAS,EAAE,CAUxE;AAsCD,mFAAmF;AACnF,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,SAAS,kIAuE1D;AAED,oGAAoG;AACpG,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,IAAI,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC;;sCA0B5C"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"ErrorBoundary.d.ts","sourceRoot":"","sources":["../../src/views/ErrorBoundary.tsx"],"names":[],"mappings":";AAUA,OAAO,EAAE,kBAAkB,EAAE,MAAM,OAAO,CAAC;AAmC3C,wBAAgB,aAAa,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,kBAAkB,
|
|
1
|
+
{"version":3,"file":"ErrorBoundary.d.ts","sourceRoot":"","sources":["../../src/views/ErrorBoundary.tsx"],"names":[],"mappings":";AAUA,OAAO,EAAE,kBAAkB,EAAE,MAAM,OAAO,CAAC;AAmC3C,wBAAgB,aAAa,CAAC,EAAE,KAAK,EAAE,KAAK,EAAE,EAAE,kBAAkB,eAuDjE"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Screen.d.ts","sourceRoot":"","sources":["../../src/views/Screen.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Screen.d.ts","sourceRoot":"","sources":["../../src/views/Screen.tsx"],"names":[],"mappings":"AAKA,MAAM,MAAM,WAAW,CACrB,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,IACxD;IACF;;;;;;OAMG;IACH,IAAI,CAAC,EAAE,MAAM,CAAC;IAEd,6CAA6C;IAC7C,QAAQ,CAAC,EAAE,OAAO,CAAC;IAEnB,aAAa,CAAC,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;KAAE,CAAC;IACvC,OAAO,CAAC,EAAE,QAAQ,CAAC;CACpB,CAAC;AAKF,sEAAsE;AACtE,wBAAgB,MAAM,CAAC,QAAQ,SAAS,MAAM,GAAG,MAAM,EAAE,EACvD,IAAI,EACJ,QAAQ,EACR,OAAO,GACR,EAAE,WAAW,CAAC,QAAQ,CAAC,QAkCvB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Sitemap.d.ts","sourceRoot":"","sources":["../../src/views/Sitemap.tsx"],"names":[],"mappings":";
|
|
1
|
+
{"version":3,"file":"Sitemap.d.ts","sourceRoot":"","sources":["../../src/views/Sitemap.tsx"],"names":[],"mappings":";AACA,OAAO,EAAE,4BAA4B,EAAE,MAAM,gCAAgC,CAAC;AAkB9E,wBAAgB,aAAa,IAAI,4BAA4B,CAoB5D;AAED,wBAAgB,OAAO,gBA6BtB"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Splash.d.ts","sourceRoot":"","sources":["../../src/views/Splash.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"Splash.d.ts","sourceRoot":"","sources":["../../src/views/Splash.tsx"],"names":[],"mappings":"AASA;;;;;;;;;;;;;;;;;GAiBG;AACH,wBAAgB,YAAY,SAM3B;yBANe,YAAY;;;;;;AAmC5B,eAAO,MAAM,8BAA8B,YAe1C,CAAC;AAEF,eAAO,MAAM,wBAAwB,YAOpC,CAAC"}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Unmatched.d.ts","sourceRoot":"","sources":["../../src/views/Unmatched.tsx"],"names":[],"mappings":";AAwBA,2CAA2C;AAC3C,wBAAgB,SAAS,
|
|
1
|
+
{"version":3,"file":"Unmatched.d.ts","sourceRoot":"","sources":["../../src/views/Unmatched.tsx"],"names":[],"mappings":";AAwBA,2CAA2C;AAC3C,wBAAgB,SAAS,gBA4CxB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "expo-router",
|
|
3
|
-
"version": "2.0.
|
|
3
|
+
"version": "2.0.1",
|
|
4
4
|
"main": "src/index.tsx",
|
|
5
5
|
"types": "build/index.d.ts",
|
|
6
6
|
"files": [
|
|
@@ -61,7 +61,7 @@
|
|
|
61
61
|
},
|
|
62
62
|
"peerDependencies": {
|
|
63
63
|
"@react-navigation/drawer": "^6.5.8",
|
|
64
|
-
"expo": "^49.0.0
|
|
64
|
+
"expo": "^49.0.0",
|
|
65
65
|
"expo-constants": "*",
|
|
66
66
|
"expo-linking": "*",
|
|
67
67
|
"expo-status-bar": "*",
|
|
@@ -104,13 +104,13 @@
|
|
|
104
104
|
},
|
|
105
105
|
"dependencies": {
|
|
106
106
|
"@bacons/react-views": "^1.1.3",
|
|
107
|
-
"@expo/metro-runtime": "2.2.
|
|
107
|
+
"@expo/metro-runtime": "2.2.4",
|
|
108
108
|
"@radix-ui/react-slot": "1.0.1",
|
|
109
109
|
"@react-navigation/bottom-tabs": "~6.5.7",
|
|
110
110
|
"@react-navigation/native": "~6.1.6",
|
|
111
111
|
"@react-navigation/native-stack": "~6.9.12",
|
|
112
112
|
"expo-head": "0.0.11",
|
|
113
|
-
"expo-splash-screen": "
|
|
113
|
+
"expo-splash-screen": "~0.20.2",
|
|
114
114
|
"query-string": "7.1.3",
|
|
115
115
|
"react-helmet-async": "^1.3.0",
|
|
116
116
|
"schema-utils": "^4.0.1",
|
package/src/ExpoRoot.tsx
CHANGED
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import Constants from "expo-constants";
|
|
1
2
|
import { StatusBar } from "expo-status-bar";
|
|
2
3
|
import React, { FunctionComponent, ReactNode, Fragment } from "react";
|
|
3
4
|
import { Platform } from "react-native";
|
|
@@ -44,6 +45,11 @@ const INITIAL_METRICS = {
|
|
|
44
45
|
insets: { top: 0, left: 0, right: 0, bottom: 0 },
|
|
45
46
|
};
|
|
46
47
|
|
|
48
|
+
const hasViewControllerBasedStatusBarAppearance =
|
|
49
|
+
Platform.OS === "ios" &&
|
|
50
|
+
!!Constants.expoConfig?.ios?.infoPlist
|
|
51
|
+
?.UIViewControllerBasedStatusBarAppearance;
|
|
52
|
+
|
|
47
53
|
export function ExpoRoot({
|
|
48
54
|
wrapper: ParentWrapper = Fragment,
|
|
49
55
|
...props
|
|
@@ -64,7 +70,9 @@ export function ExpoRoot({
|
|
|
64
70
|
{children}
|
|
65
71
|
|
|
66
72
|
{/* Users can override this by adding another StatusBar element anywhere higher in the component tree. */}
|
|
67
|
-
|
|
73
|
+
{!hasViewControllerBasedStatusBarAppearance && (
|
|
74
|
+
<StatusBar style="auto" />
|
|
75
|
+
)}
|
|
68
76
|
</SafeAreaProvider>
|
|
69
77
|
</GestureHandlerRootView>
|
|
70
78
|
</ParentWrapper>
|
|
@@ -90,7 +98,11 @@ function ContextNavigator({
|
|
|
90
98
|
SplashScreen.hideAsync();
|
|
91
99
|
if (process.env.NODE_ENV === "development") {
|
|
92
100
|
const Tutorial = require("./onboard/Tutorial").Tutorial;
|
|
93
|
-
return
|
|
101
|
+
return (
|
|
102
|
+
<WrapperComponent>
|
|
103
|
+
<Tutorial />
|
|
104
|
+
</WrapperComponent>
|
|
105
|
+
);
|
|
94
106
|
} else {
|
|
95
107
|
// Ensure tutorial styles are stripped in production.
|
|
96
108
|
return null;
|
|
@@ -6,6 +6,7 @@ import type {
|
|
|
6
6
|
} from "@react-navigation/routers";
|
|
7
7
|
import escape from "escape-string-regexp";
|
|
8
8
|
import * as queryString from "query-string";
|
|
9
|
+
import URL from "url-parse";
|
|
9
10
|
|
|
10
11
|
import { RouteNode } from "../Route";
|
|
11
12
|
import { matchGroupName, stripGroupSegmentsFromPath } from "../matchers";
|
|
@@ -47,14 +48,18 @@ type ParsedRoute = {
|
|
|
47
48
|
params?: Record<string, any> | undefined;
|
|
48
49
|
};
|
|
49
50
|
|
|
50
|
-
function
|
|
51
|
-
const
|
|
52
|
-
|
|
53
|
-
.replace(/^\//, "") // Remove extra leading slash
|
|
54
|
-
.replace(/\?.*$/, ""); // Remove query params which we will handle later
|
|
51
|
+
export function getUrlWithReactNavigationConcessions(path: string) {
|
|
52
|
+
const parsed = new URL(path, "https://acme.com");
|
|
53
|
+
const pathname = parsed.pathname;
|
|
55
54
|
|
|
56
55
|
// Make sure there is a trailing slash
|
|
57
|
-
return
|
|
56
|
+
return {
|
|
57
|
+
// The slashes are at the end, not the beginning
|
|
58
|
+
nonstandardPathname:
|
|
59
|
+
pathname.replace(/^\/+/g, "").replace(/\/+$/g, "") + "/",
|
|
60
|
+
// React Navigation doesn't support hashes, so here
|
|
61
|
+
inputPathnameWithoutHash: path.replace(/#.*$/, ""),
|
|
62
|
+
};
|
|
58
63
|
}
|
|
59
64
|
|
|
60
65
|
/**
|
|
@@ -316,10 +321,15 @@ function getStateFromEmptyPathWithConfigs(
|
|
|
316
321
|
return undefined;
|
|
317
322
|
}
|
|
318
323
|
|
|
319
|
-
const routes = match.routeNames.map((name) =>
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
324
|
+
const routes = match.routeNames.map((name) => {
|
|
325
|
+
if (!match._route) {
|
|
326
|
+
return { name };
|
|
327
|
+
}
|
|
328
|
+
return {
|
|
329
|
+
name,
|
|
330
|
+
_route: match._route,
|
|
331
|
+
};
|
|
332
|
+
});
|
|
323
333
|
|
|
324
334
|
return createNestedStateObject(path, routes, configs, initialRoutes);
|
|
325
335
|
}
|
|
@@ -329,21 +339,33 @@ function getStateFromPathWithConfigs(
|
|
|
329
339
|
configs: RouteConfig[],
|
|
330
340
|
initialRoutes: InitialRouteConfig[]
|
|
331
341
|
): ResultState | undefined {
|
|
332
|
-
const
|
|
342
|
+
const formattedPaths = getUrlWithReactNavigationConcessions(path);
|
|
333
343
|
|
|
334
|
-
if (
|
|
335
|
-
return getStateFromEmptyPathWithConfigs(
|
|
344
|
+
if (formattedPaths.nonstandardPathname === "/") {
|
|
345
|
+
return getStateFromEmptyPathWithConfigs(
|
|
346
|
+
formattedPaths.inputPathnameWithoutHash,
|
|
347
|
+
configs,
|
|
348
|
+
initialRoutes
|
|
349
|
+
);
|
|
336
350
|
}
|
|
337
351
|
|
|
338
352
|
// We match the whole path against the regex instead of segments
|
|
339
353
|
// This makes sure matches such as wildcard will catch any unmatched routes, even if nested
|
|
340
|
-
const routes = matchAgainstConfigs(
|
|
354
|
+
const routes = matchAgainstConfigs(
|
|
355
|
+
formattedPaths.nonstandardPathname,
|
|
356
|
+
configs
|
|
357
|
+
);
|
|
341
358
|
|
|
342
359
|
if (routes == null) {
|
|
343
360
|
return undefined;
|
|
344
361
|
}
|
|
345
362
|
// This will always be empty if full path matched
|
|
346
|
-
return createNestedStateObject(
|
|
363
|
+
return createNestedStateObject(
|
|
364
|
+
formattedPaths.inputPathnameWithoutHash,
|
|
365
|
+
routes,
|
|
366
|
+
configs,
|
|
367
|
+
initialRoutes
|
|
368
|
+
);
|
|
347
369
|
}
|
|
348
370
|
|
|
349
371
|
const joinPaths = (...paths: string[]): string =>
|
|
@@ -424,10 +446,15 @@ function matchAgainstConfigs(
|
|
|
424
446
|
return { name };
|
|
425
447
|
};
|
|
426
448
|
|
|
427
|
-
routes = config.routeNames.map((name) =>
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
449
|
+
routes = config.routeNames.map((name) => {
|
|
450
|
+
if (!config._route) {
|
|
451
|
+
return { ...routeFromName(name) };
|
|
452
|
+
}
|
|
453
|
+
return {
|
|
454
|
+
...routeFromName(name),
|
|
455
|
+
_route: config._route,
|
|
456
|
+
};
|
|
457
|
+
});
|
|
431
458
|
|
|
432
459
|
// TODO(EvanBacon): Maybe we should warn / assert if multiple slugs use the same param name.
|
|
433
460
|
const combinedParams = routes.reduce<Record<string, any>>(
|
|
@@ -14,7 +14,7 @@ import { getRoutes } from "../getRoutes";
|
|
|
14
14
|
import { RequireContext } from "../types";
|
|
15
15
|
import { getQualifiedRouteComponent } from "../useScreens";
|
|
16
16
|
import { _internal_maybeHideAsync } from "../views/Splash";
|
|
17
|
-
import { goBack, linkTo, push, replace, setParams } from "./routing";
|
|
17
|
+
import { canGoBack, goBack, linkTo, push, replace, setParams } from "./routing";
|
|
18
18
|
import { getSortedRoutes } from "./sort-routes";
|
|
19
19
|
|
|
20
20
|
/**
|
|
@@ -27,6 +27,7 @@ export class RouterStore {
|
|
|
27
27
|
rootComponent!: ComponentType;
|
|
28
28
|
linking: ExpoLinkingOptions | undefined;
|
|
29
29
|
isReady: boolean = false;
|
|
30
|
+
private hasAttemptedToHideSplash: boolean = false;
|
|
30
31
|
|
|
31
32
|
initialState: ResultState | undefined;
|
|
32
33
|
rootState: ResultState | undefined;
|
|
@@ -42,6 +43,7 @@ export class RouterStore {
|
|
|
42
43
|
linkTo = linkTo.bind(this);
|
|
43
44
|
getSortedRoutes = getSortedRoutes.bind(this);
|
|
44
45
|
goBack = goBack.bind(this);
|
|
46
|
+
canGoBack = canGoBack.bind(this);
|
|
45
47
|
push = push.bind(this);
|
|
46
48
|
replace = replace.bind(this);
|
|
47
49
|
setParams = setParams.bind(this);
|
|
@@ -117,8 +119,16 @@ export class RouterStore {
|
|
|
117
119
|
(data) => {
|
|
118
120
|
const state = data.data.state as ResultState;
|
|
119
121
|
|
|
120
|
-
if (
|
|
121
|
-
this.
|
|
122
|
+
if (!this.isReady) {
|
|
123
|
+
if (!this.hasAttemptedToHideSplash) {
|
|
124
|
+
this.hasAttemptedToHideSplash = true;
|
|
125
|
+
// NOTE(EvanBacon): `navigationRef.isReady` is sometimes not true when state is called initially.
|
|
126
|
+
requestAnimationFrame(() => _internal_maybeHideAsync());
|
|
127
|
+
}
|
|
128
|
+
|
|
129
|
+
if (navigationRef.isReady()) {
|
|
130
|
+
this.onReady();
|
|
131
|
+
}
|
|
122
132
|
}
|
|
123
133
|
|
|
124
134
|
let shouldUpdateSubscribers = this.nextState === state;
|
|
@@ -178,9 +188,6 @@ export class RouterStore {
|
|
|
178
188
|
|
|
179
189
|
/** Make sure these are arrow functions so `this` is correctly bound */
|
|
180
190
|
onReady = () => {
|
|
181
|
-
if (!this.isReady) {
|
|
182
|
-
requestAnimationFrame(() => _internal_maybeHideAsync());
|
|
183
|
-
}
|
|
184
191
|
this.isReady = true;
|
|
185
192
|
};
|
|
186
193
|
subscribeToRootState = (subscriber: () => void) => {
|
|
@@ -20,7 +20,9 @@ import type { RouterStore } from "./router-store";
|
|
|
20
20
|
|
|
21
21
|
function assertIsReady(store: RouterStore) {
|
|
22
22
|
if (!store.isReady || !store.navigationRef.current) {
|
|
23
|
-
throw new Error(
|
|
23
|
+
throw new Error(
|
|
24
|
+
"Attempted to navigate before mounting the Root Layout component. Ensure the Root Layout component is rendering a Slot, or other navigator on the first render."
|
|
25
|
+
);
|
|
24
26
|
}
|
|
25
27
|
}
|
|
26
28
|
|
|
@@ -37,6 +39,11 @@ export function goBack(this: RouterStore) {
|
|
|
37
39
|
this.navigationRef?.current?.goBack();
|
|
38
40
|
}
|
|
39
41
|
|
|
42
|
+
export function canGoBack(this: RouterStore): boolean {
|
|
43
|
+
assertIsReady(this);
|
|
44
|
+
return this.navigationRef?.current?.canGoBack() ?? false;
|
|
45
|
+
}
|
|
46
|
+
|
|
40
47
|
export function setParams(
|
|
41
48
|
this: RouterStore,
|
|
42
49
|
params: Record<string, string | number> = {}
|
|
@@ -1,5 +1,4 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { matchGroupName } from "../matchers";
|
|
1
|
+
import { sortRoutes } from "../Route";
|
|
3
2
|
import type { RouterStore } from "./router-store";
|
|
4
3
|
|
|
5
4
|
export function getSortedRoutes(this: RouterStore) {
|
|
@@ -9,40 +8,5 @@ export function getSortedRoutes(this: RouterStore) {
|
|
|
9
8
|
|
|
10
9
|
return this.routeNode.children
|
|
11
10
|
.filter((route) => !route.internal)
|
|
12
|
-
.sort(
|
|
13
|
-
if (a.dynamic && !b.dynamic) {
|
|
14
|
-
return 1;
|
|
15
|
-
}
|
|
16
|
-
if (!a.dynamic && b.dynamic) {
|
|
17
|
-
return -1;
|
|
18
|
-
}
|
|
19
|
-
if (a.dynamic && b.dynamic) {
|
|
20
|
-
if (a.dynamic.length !== b.dynamic.length) {
|
|
21
|
-
return b.dynamic.length - a.dynamic.length;
|
|
22
|
-
}
|
|
23
|
-
for (let i = 0; i < a.dynamic.length; i++) {
|
|
24
|
-
const aDynamic = a.dynamic[i];
|
|
25
|
-
const bDynamic = b.dynamic[i];
|
|
26
|
-
if (aDynamic.deep && !bDynamic.deep) {
|
|
27
|
-
return 1;
|
|
28
|
-
}
|
|
29
|
-
if (!aDynamic.deep && bDynamic.deep) {
|
|
30
|
-
return -1;
|
|
31
|
-
}
|
|
32
|
-
}
|
|
33
|
-
return 0;
|
|
34
|
-
}
|
|
35
|
-
|
|
36
|
-
const aIndex = a.route === "index" || matchGroupName(a.route) != null;
|
|
37
|
-
const bIndex = b.route === "index" || matchGroupName(b.route) != null;
|
|
38
|
-
|
|
39
|
-
if (aIndex && !bIndex) {
|
|
40
|
-
return -1;
|
|
41
|
-
}
|
|
42
|
-
if (!aIndex && bIndex) {
|
|
43
|
-
return 1;
|
|
44
|
-
}
|
|
45
|
-
|
|
46
|
-
return a.route.length - b.route.length;
|
|
47
|
-
});
|
|
11
|
+
.sort(sortRoutes);
|
|
48
12
|
}
|
package/src/hooks.ts
CHANGED
|
@@ -11,6 +11,7 @@ import {
|
|
|
11
11
|
useStoreRouteInfo,
|
|
12
12
|
} from "./global-state/router-store";
|
|
13
13
|
import { Router } from "./types";
|
|
14
|
+
import { useDeprecated } from "./useDeprecated";
|
|
14
15
|
|
|
15
16
|
type SearchParams = Record<string, string | string[]>;
|
|
16
17
|
|
|
@@ -28,19 +29,22 @@ export function useRootNavigation() {
|
|
|
28
29
|
|
|
29
30
|
// Wraps useLinkTo to provide an API which is similar to the Link component.
|
|
30
31
|
export function useLink() {
|
|
31
|
-
|
|
32
|
+
useDeprecated("`useLink()` is deprecated in favor of `useRouter()`");
|
|
32
33
|
return useRouter();
|
|
33
34
|
}
|
|
34
35
|
|
|
35
36
|
export function useRouter(): Router {
|
|
36
|
-
return
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
37
|
+
return React.useMemo(
|
|
38
|
+
() => ({
|
|
39
|
+
push: store.push,
|
|
40
|
+
back: store.goBack,
|
|
41
|
+
replace: store.replace,
|
|
42
|
+
setParams: store.setParams,
|
|
43
|
+
canGoBack: store.canGoBack,
|
|
44
|
+
// TODO(EvanBacon): add `reload`
|
|
45
|
+
}),
|
|
46
|
+
[]
|
|
47
|
+
);
|
|
44
48
|
}
|
|
45
49
|
|
|
46
50
|
/**
|
package/src/imperative-api.ts
CHANGED
package/src/link/href.ts
CHANGED
|
@@ -19,10 +19,8 @@ export const resolveHref = (href: Href): string => {
|
|
|
19
19
|
const { pathname, params } = createQualifiedPathname(path, {
|
|
20
20
|
...href.params,
|
|
21
21
|
});
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
(Object.keys(params).length ? `?${createQueryParams(params)}` : "")
|
|
25
|
-
);
|
|
22
|
+
const paramsString = createQueryParams(params);
|
|
23
|
+
return pathname + (paramsString ? `?${paramsString}` : "");
|
|
26
24
|
};
|
|
27
25
|
|
|
28
26
|
function createQualifiedPathname(
|
|
@@ -54,7 +52,11 @@ function encodeParam(param: any): string {
|
|
|
54
52
|
}
|
|
55
53
|
|
|
56
54
|
function createQueryParams(params: Record<string, any>): string {
|
|
57
|
-
return
|
|
58
|
-
.
|
|
59
|
-
|
|
55
|
+
return (
|
|
56
|
+
Object.entries(params)
|
|
57
|
+
// Allow nullish params
|
|
58
|
+
.filter(([, value]) => value != null)
|
|
59
|
+
.map(([key, value]) => `${key}=${encodeURIComponent(value.toString())}`)
|
|
60
|
+
.join("&")
|
|
61
|
+
);
|
|
60
62
|
}
|
package/src/onboard/Tutorial.tsx
CHANGED
|
@@ -11,8 +11,8 @@ function Header() {
|
|
|
11
11
|
<Pressable>
|
|
12
12
|
{({ hovered }) => (
|
|
13
13
|
<Text
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
role="heading"
|
|
15
|
+
aria-level={1}
|
|
16
16
|
style={[styles.title, Platform.OS !== "web" && { textAlign: "left" }]}
|
|
17
17
|
>
|
|
18
18
|
Welcome to{" "}
|
|
@@ -62,11 +62,7 @@ export function Tutorial() {
|
|
|
62
62
|
<SafeAreaView style={styles.safeArea}>
|
|
63
63
|
<View style={styles.container}>
|
|
64
64
|
<Header />
|
|
65
|
-
<Text
|
|
66
|
-
accessibilityRole="header"
|
|
67
|
-
accessibilityLevel={2}
|
|
68
|
-
style={styles.subtitle}
|
|
69
|
-
>
|
|
65
|
+
<Text role="heading" aria-level={2} style={styles.subtitle}>
|
|
70
66
|
Start by creating a file{"\n"}in the{" "}
|
|
71
67
|
<Text style={{ fontWeight: "bold" }}>{getRootDir()}</Text>{" "}
|
|
72
68
|
directory.
|
|
@@ -122,10 +118,7 @@ function Button() {
|
|
|
122
118
|
},
|
|
123
119
|
]}
|
|
124
120
|
>
|
|
125
|
-
<Text
|
|
126
|
-
selectable={false}
|
|
127
|
-
style={[styles.code, hovered && { color: "black" }]}
|
|
128
|
-
>
|
|
121
|
+
<Text style={[styles.code, hovered && { color: "black" }]}>
|
|
129
122
|
<Text style={{ color: "#BCC3CD" }}>$</Text> touch {getRootDir()}
|
|
130
123
|
/index.js
|
|
131
124
|
</Text>
|
|
@@ -179,6 +172,7 @@ const styles = StyleSheet.create({
|
|
|
179
172
|
color: "black",
|
|
180
173
|
},
|
|
181
174
|
code: {
|
|
175
|
+
userSelect: "none",
|
|
182
176
|
fontSize: 18,
|
|
183
177
|
transitionDuration: "200ms",
|
|
184
178
|
fontWeight: "bold",
|
package/src/static/html.tsx
CHANGED
|
@@ -14,7 +14,7 @@ export function ScrollViewStyleReset() {
|
|
|
14
14
|
<style
|
|
15
15
|
id="expo-reset"
|
|
16
16
|
dangerouslySetInnerHTML={{
|
|
17
|
-
__html: `#root,body,html{height:100%}
|
|
17
|
+
__html: `#root,body{display:flex}#root,body,html{width:100%;-webkit-overflow-scrolling:touch;margin:0;padding:0;min-height:100%}#root{flex-shrink:0;flex-basis:auto;flex-grow:1;flex:1}html{scroll-behavior:smooth;-webkit-text-size-adjust:100%;height:calc(100% + env(safe-area-inset-top))}body{overflow-y:auto;overscroll-behavior-y:none;text-rendering:optimizeLegibility;-webkit-font-smoothing:antialiased;-moz-osx-font-smoothing:grayscale;-ms-overflow-style:scrollbar}`,
|
|
18
18
|
}}
|
|
19
19
|
/>
|
|
20
20
|
);
|
package/src/types.ts
CHANGED
|
@@ -23,6 +23,8 @@ export type Router = {
|
|
|
23
23
|
replace: (href: Href) => void;
|
|
24
24
|
/** Go back in the history. */
|
|
25
25
|
back: () => void;
|
|
26
|
+
/** If there's history that supports invoking the `back` function. */
|
|
27
|
+
canGoBack: () => boolean;
|
|
26
28
|
/** Update the current route query params. */
|
|
27
29
|
setParams: (params?: Record<string, string>) => void;
|
|
28
30
|
};
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
import { useLayoutEffect } from "react";
|
|
2
|
+
import { Platform } from "react-native";
|
|
3
|
+
|
|
4
|
+
// Node environment may render in multiple processes causing the warning to log mutiple times
|
|
5
|
+
// Hence we skip the warning in these environments.
|
|
6
|
+
const canWarn = Platform.select({
|
|
7
|
+
native: process.env.NODE_ENV !== "production",
|
|
8
|
+
default:
|
|
9
|
+
process.env.NODE_ENV !== "production" && typeof window !== "undefined",
|
|
10
|
+
});
|
|
11
|
+
|
|
12
|
+
const warned = new Set<string>();
|
|
13
|
+
|
|
14
|
+
export function useWarnOnce(
|
|
15
|
+
message: string,
|
|
16
|
+
guard: unknown = true,
|
|
17
|
+
key = message
|
|
18
|
+
) {
|
|
19
|
+
// useLayoutEffect typically doesn't run in node environments.
|
|
20
|
+
// Combined with skipWarn, this should prevent unwanted warnings
|
|
21
|
+
useLayoutEffect(() => {
|
|
22
|
+
if (guard && canWarn && !warned.has(key)) {
|
|
23
|
+
warned.add(key);
|
|
24
|
+
console.warn(message);
|
|
25
|
+
}
|
|
26
|
+
}, [guard]);
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
export function useDeprecated(
|
|
30
|
+
message: string,
|
|
31
|
+
guard: unknown = true,
|
|
32
|
+
key = message
|
|
33
|
+
) {
|
|
34
|
+
return useWarnOnce(key, guard, `Expo Router: ${message}`);
|
|
35
|
+
}
|
package/src/useScreens.tsx
CHANGED
|
@@ -29,6 +29,12 @@ export type ScreenProps<
|
|
|
29
29
|
|
|
30
30
|
// TODO: types
|
|
31
31
|
listeners?: any;
|
|
32
|
+
|
|
33
|
+
getId?: ({
|
|
34
|
+
params,
|
|
35
|
+
}: {
|
|
36
|
+
params?: Record<string, any> | undefined;
|
|
37
|
+
}) => string | undefined;
|
|
32
38
|
};
|
|
33
39
|
|
|
34
40
|
function getSortedChildren(
|
|
@@ -44,7 +50,7 @@ function getSortedChildren(
|
|
|
44
50
|
const entries = [...children];
|
|
45
51
|
|
|
46
52
|
const ordered = order
|
|
47
|
-
.map(({ name, redirect, initialParams, listeners, options }) => {
|
|
53
|
+
.map(({ name, redirect, initialParams, listeners, options, getId }) => {
|
|
48
54
|
if (!entries.length) {
|
|
49
55
|
console.warn(
|
|
50
56
|
`[Layout children]: Too many screens defined. Route "${name}" is extraneous.`
|
|
@@ -73,7 +79,10 @@ function getSortedChildren(
|
|
|
73
79
|
return null;
|
|
74
80
|
}
|
|
75
81
|
|
|
76
|
-
return {
|
|
82
|
+
return {
|
|
83
|
+
route: match,
|
|
84
|
+
props: { initialParams, listeners, options, getId },
|
|
85
|
+
};
|
|
77
86
|
}
|
|
78
87
|
})
|
|
79
88
|
.filter(Boolean) as {
|
|
@@ -62,11 +62,7 @@ export function ErrorBoundary({ error, retry }: ErrorBoundaryProps) {
|
|
|
62
62
|
alignItems: "center",
|
|
63
63
|
}}
|
|
64
64
|
>
|
|
65
|
-
<Text
|
|
66
|
-
accessibilityRole="header"
|
|
67
|
-
accessibilityLevel={1}
|
|
68
|
-
style={styles.title}
|
|
69
|
-
>
|
|
65
|
+
<Text role="heading" aria-level={1} style={styles.title}>
|
|
70
66
|
Something went wrong
|
|
71
67
|
</Text>
|
|
72
68
|
</View>
|
package/src/views/Screen.tsx
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
|
|
3
|
+
import { useDeprecated } from "../useDeprecated";
|
|
3
4
|
import { useNavigation } from "../useNavigation";
|
|
4
5
|
|
|
5
6
|
export type ScreenProps<
|
|
@@ -33,9 +34,24 @@ export function Screen<TOptions extends object = object>({
|
|
|
33
34
|
const navigation = useNavigation(name);
|
|
34
35
|
|
|
35
36
|
useLayoutEffect(() => {
|
|
36
|
-
|
|
37
|
+
if (
|
|
38
|
+
options &&
|
|
39
|
+
// React Navigation will infinitely loop in some cases if an empty object is passed to setOptions.
|
|
40
|
+
// https://github.com/expo/router/issues/452
|
|
41
|
+
Object.keys(options).length
|
|
42
|
+
) {
|
|
43
|
+
navigation.setOptions(options);
|
|
44
|
+
}
|
|
37
45
|
}, [navigation, options]);
|
|
38
46
|
|
|
47
|
+
if (process.env.NODE_ENV === "development") {
|
|
48
|
+
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
49
|
+
useDeprecated(
|
|
50
|
+
"The `redirect` prop on <Screen /> is deprecated and will be removed. Please use `router.redirect` instead",
|
|
51
|
+
redirect
|
|
52
|
+
);
|
|
53
|
+
}
|
|
54
|
+
|
|
39
55
|
if (process.env.NODE_ENV !== "production") {
|
|
40
56
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
41
57
|
React.useEffect(() => {
|
package/src/views/Sitemap.tsx
CHANGED
|
@@ -1,5 +1,4 @@
|
|
|
1
1
|
import { Image, Pressable, StyleSheet, Text, View } from "@bacons/react-views";
|
|
2
|
-
import { useNavigation } from "@react-navigation/native";
|
|
3
2
|
import { NativeStackNavigationOptions } from "@react-navigation/native-stack";
|
|
4
3
|
import React from "react";
|
|
5
4
|
import {
|
|
@@ -12,6 +11,7 @@ import { useSafeAreaInsets } from "react-native-safe-area-context";
|
|
|
12
11
|
|
|
13
12
|
import { RouteNode } from "../Route";
|
|
14
13
|
import { useExpoRouter } from "../global-state/router-store";
|
|
14
|
+
import { router } from "../imperative-api";
|
|
15
15
|
import { Link } from "../link/Link";
|
|
16
16
|
import { matchDeepDynamicRouteName } from "../matchers";
|
|
17
17
|
|
|
@@ -27,7 +27,6 @@ export function getNavOptions(): NativeStackNavigationOptions {
|
|
|
27
27
|
headerTitleStyle: {
|
|
28
28
|
color: "white",
|
|
29
29
|
},
|
|
30
|
-
|
|
31
30
|
headerTintColor: "white",
|
|
32
31
|
headerLargeTitleStyle: {
|
|
33
32
|
color: "white",
|
|
@@ -98,8 +97,6 @@ function FileItem({
|
|
|
98
97
|
}) {
|
|
99
98
|
const disabled = route.children.length > 0;
|
|
100
99
|
|
|
101
|
-
const navigation = useNavigation();
|
|
102
|
-
|
|
103
100
|
const segments = React.useMemo(
|
|
104
101
|
() => [...parents, ...route.route.split("/")],
|
|
105
102
|
[parents, route.route]
|
|
@@ -147,9 +144,9 @@ function FileItem({
|
|
|
147
144
|
accessibilityLabel={route.contextKey}
|
|
148
145
|
href={href}
|
|
149
146
|
onPress={() => {
|
|
150
|
-
if (Platform.OS !== "web") {
|
|
147
|
+
if (Platform.OS !== "web" && router.canGoBack()) {
|
|
151
148
|
// Ensure the modal pops
|
|
152
|
-
|
|
149
|
+
router.back();
|
|
153
150
|
}
|
|
154
151
|
}}
|
|
155
152
|
style={{ flex: 1, display: "flex" }}
|
package/src/views/Splash.tsx
CHANGED
|
@@ -3,6 +3,8 @@ import { nanoid } from "nanoid/non-secure";
|
|
|
3
3
|
import * as React from "react";
|
|
4
4
|
import { Platform } from "react-native";
|
|
5
5
|
|
|
6
|
+
import { useDeprecated } from "../useDeprecated";
|
|
7
|
+
|
|
6
8
|
const globalStack: string[] = [];
|
|
7
9
|
|
|
8
10
|
/**
|
|
@@ -25,11 +27,9 @@ const globalStack: string[] = [];
|
|
|
25
27
|
*/
|
|
26
28
|
export function SplashScreen() {
|
|
27
29
|
useGlobalSplash();
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
);
|
|
32
|
-
}, []);
|
|
30
|
+
useDeprecated(
|
|
31
|
+
"The <SplashScreen /> component is deprecated. Use `SplashScreen.preventAutoHideAsync()` and `SplashScreen.hideAsync` from `expo-router` instead."
|
|
32
|
+
);
|
|
33
33
|
return null;
|
|
34
34
|
}
|
|
35
35
|
|
package/src/views/Unmatched.tsx
CHANGED
|
@@ -37,23 +37,15 @@ export function Unmatched() {
|
|
|
37
37
|
|
|
38
38
|
return (
|
|
39
39
|
<View style={styles.container}>
|
|
40
|
-
<Text
|
|
41
|
-
accessibilityRole="header"
|
|
42
|
-
accessibilityLevel={1}
|
|
43
|
-
style={styles.title}
|
|
44
|
-
>
|
|
40
|
+
<Text role="heading" aria-level={1} style={styles.title}>
|
|
45
41
|
Unmatched Route
|
|
46
42
|
</Text>
|
|
47
|
-
<Text
|
|
48
|
-
accessibilityRole="header"
|
|
49
|
-
accessibilityLevel={2}
|
|
50
|
-
style={styles.subtitle}
|
|
51
|
-
>
|
|
43
|
+
<Text role="heading" aria-level={2} style={styles.subtitle}>
|
|
52
44
|
Page could not be found.{" "}
|
|
53
45
|
<Text
|
|
54
46
|
onPress={() => {
|
|
55
|
-
if (
|
|
56
|
-
|
|
47
|
+
if (router.canGoBack()) {
|
|
48
|
+
router.back();
|
|
57
49
|
} else {
|
|
58
50
|
router.replace("/");
|
|
59
51
|
}
|