expo-router 0.0.37 → 0.0.39

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.
@@ -1 +1 @@
1
- {"version":3,"file":"ContextNavigator.d.ts","sourceRoot":"","sources":["../src/ContextNavigator.tsx"],"names":[],"mappings":";AAMA,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAyBzC,wBAAgB,gBAAgB,CAAC,EAAE,OAAO,EAAE,EAAE;IAAE,OAAO,EAAE,cAAc,CAAA;CAAE,eAcxE"}
1
+ {"version":3,"file":"ContextNavigator.d.ts","sourceRoot":"","sources":["../src/ContextNavigator.tsx"],"names":[],"mappings":";AAOA,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAyBzC,wBAAgB,gBAAgB,CAAC,EAAE,OAAO,EAAE,EAAE;IAAE,OAAO,EAAE,cAAc,CAAA;CAAE,eAgBxE"}
@@ -3,6 +3,7 @@ import { ContextNavigationContainer } from "./ContextNavigationContainer";
3
3
  import { RootRouteNodeContext, useRootRouteNodeContext } from "./context";
4
4
  import { getRoutes } from "./getRoutes";
5
5
  import { useTutorial } from "./onboard/useTutorial";
6
+ import { InitialRootStateProvider } from "./rootStateContext";
6
7
  import { getQualifiedRouteComponent } from "./useScreens";
7
8
  import { SplashScreen } from "./views/Splash";
8
9
  function useContextModuleAsRoutes(context) {
@@ -22,7 +23,8 @@ export function ContextNavigator({ context }) {
22
23
  }
23
24
  return (React.createElement(RootRouteNodeProvider, { context: context },
24
25
  React.createElement(ContextNavigationContainer, null,
25
- React.createElement(RootRoute, null))));
26
+ React.createElement(InitialRootStateProvider, null,
27
+ React.createElement(RootRoute, null)))));
26
28
  }
27
29
  function RootRoute() {
28
30
  const root = useRootRouteNodeContext();
@@ -1 +1 @@
1
- {"version":3,"file":"ContextNavigator.js","sourceRoot":"","sources":["../src/ContextNavigator.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAEvC,OAAO,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAC;AAC1E,OAAO,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,MAAM,WAAW,CAAC;AAC1E,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AAEpD,OAAO,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,SAAS,wBAAwB,CAAC,OAAuB;IACvD,4CAA4C;IAC5C,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IACtD,OAAO,OAAO,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;AACnD,CAAC;AAED,SAAS,qBAAqB,CAAC,EAC7B,OAAO,EACP,QAAQ,GAIT;IACC,MAAM,MAAM,GAAG,wBAAwB,CAAC,OAAO,CAAC,CAAC;IACjD,OAAO,CACL,oBAAC,oBAAoB,CAAC,QAAQ,IAAC,KAAK,EAAE,MAAM,IACzC,QAAQ,CACqB,CACjC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,EAAE,OAAO,EAA+B;IACvE,MAAM,QAAQ,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;IACtC,IAAI,QAAQ,EAAE;QACZ,YAAY,CAAC,SAAS,EAAE,CAAC;QACzB,OAAO,oBAAC,QAAQ,OAAG,CAAC;KACrB;IAED,OAAO,CACL,oBAAC,qBAAqB,IAAC,OAAO,EAAE,OAAO;QACrC,oBAAC,0BAA0B;YACzB,oBAAC,SAAS,OAAG,CACc,CACP,CACzB,CAAC;AACJ,CAAC;AAED,SAAS,SAAS;IAChB,MAAM,IAAI,GAAG,uBAAuB,EAAE,CAAC;IAEvC,MAAM,SAAS,GAAG,0BAA0B,CAAC,IAAI,CAAC,CAAC;IACnD,0DAA0D;IAC1D,OAAO,oBAAC,SAAS,OAAG,CAAC;AACvB,CAAC","sourcesContent":["import React, { useMemo } from \"react\";\n\nimport { ContextNavigationContainer } from \"./ContextNavigationContainer\";\nimport { RootRouteNodeContext, useRootRouteNodeContext } from \"./context\";\nimport { getRoutes } from \"./getRoutes\";\nimport { useTutorial } from \"./onboard/useTutorial\";\nimport { RequireContext } from \"./types\";\nimport { getQualifiedRouteComponent } from \"./useScreens\";\nimport { SplashScreen } from \"./views/Splash\";\n\nfunction useContextModuleAsRoutes(context: RequireContext) {\n // TODO: Is this an optimal hook dependency?\n const keys = useMemo(() => context.keys(), [context]);\n return useMemo(() => getRoutes(context), [keys]);\n}\n\nfunction RootRouteNodeProvider({\n context,\n children,\n}: {\n context: RequireContext;\n children: React.ReactNode;\n}) {\n const routes = useContextModuleAsRoutes(context);\n return (\n <RootRouteNodeContext.Provider value={routes}>\n {children}\n </RootRouteNodeContext.Provider>\n );\n}\n\nexport function ContextNavigator({ context }: { context: RequireContext }) {\n const Tutorial = useTutorial(context);\n if (Tutorial) {\n SplashScreen.hideAsync();\n return <Tutorial />;\n }\n\n return (\n <RootRouteNodeProvider context={context}>\n <ContextNavigationContainer>\n <RootRoute />\n </ContextNavigationContainer>\n </RootRouteNodeProvider>\n );\n}\n\nfunction RootRoute() {\n const root = useRootRouteNodeContext();\n\n const Component = getQualifiedRouteComponent(root);\n // @ts-expect-error: TODO: Drop navigation and route props\n return <Component />;\n}\n"]}
1
+ {"version":3,"file":"ContextNavigator.js","sourceRoot":"","sources":["../src/ContextNavigator.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,OAAO,EAAE,MAAM,OAAO,CAAC;AAEvC,OAAO,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAC;AAC1E,OAAO,EAAE,oBAAoB,EAAE,uBAAuB,EAAE,MAAM,WAAW,CAAC;AAC1E,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,wBAAwB,EAAE,MAAM,oBAAoB,CAAC;AAE9D,OAAO,EAAE,0BAA0B,EAAE,MAAM,cAAc,CAAC;AAC1D,OAAO,EAAE,YAAY,EAAE,MAAM,gBAAgB,CAAC;AAE9C,SAAS,wBAAwB,CAAC,OAAuB;IACvD,4CAA4C;IAC5C,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IACtD,OAAO,OAAO,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;AACnD,CAAC;AAED,SAAS,qBAAqB,CAAC,EAC7B,OAAO,EACP,QAAQ,GAIT;IACC,MAAM,MAAM,GAAG,wBAAwB,CAAC,OAAO,CAAC,CAAC;IACjD,OAAO,CACL,oBAAC,oBAAoB,CAAC,QAAQ,IAAC,KAAK,EAAE,MAAM,IACzC,QAAQ,CACqB,CACjC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,EAAE,OAAO,EAA+B;IACvE,MAAM,QAAQ,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;IACtC,IAAI,QAAQ,EAAE;QACZ,YAAY,CAAC,SAAS,EAAE,CAAC;QACzB,OAAO,oBAAC,QAAQ,OAAG,CAAC;KACrB;IAED,OAAO,CACL,oBAAC,qBAAqB,IAAC,OAAO,EAAE,OAAO;QACrC,oBAAC,0BAA0B;YACzB,oBAAC,wBAAwB;gBACvB,oBAAC,SAAS,OAAG,CACY,CACA,CACP,CACzB,CAAC;AACJ,CAAC;AAED,SAAS,SAAS;IAChB,MAAM,IAAI,GAAG,uBAAuB,EAAE,CAAC;IACvC,MAAM,SAAS,GAAG,0BAA0B,CAAC,IAAI,CAAC,CAAC;IACnD,0DAA0D;IAC1D,OAAO,oBAAC,SAAS,OAAG,CAAC;AACvB,CAAC","sourcesContent":["import React, { useMemo } from \"react\";\n\nimport { ContextNavigationContainer } from \"./ContextNavigationContainer\";\nimport { RootRouteNodeContext, useRootRouteNodeContext } from \"./context\";\nimport { getRoutes } from \"./getRoutes\";\nimport { useTutorial } from \"./onboard/useTutorial\";\nimport { InitialRootStateProvider } from \"./rootStateContext\";\nimport { RequireContext } from \"./types\";\nimport { getQualifiedRouteComponent } from \"./useScreens\";\nimport { SplashScreen } from \"./views/Splash\";\n\nfunction useContextModuleAsRoutes(context: RequireContext) {\n // TODO: Is this an optimal hook dependency?\n const keys = useMemo(() => context.keys(), [context]);\n return useMemo(() => getRoutes(context), [keys]);\n}\n\nfunction RootRouteNodeProvider({\n context,\n children,\n}: {\n context: RequireContext;\n children: React.ReactNode;\n}) {\n const routes = useContextModuleAsRoutes(context);\n return (\n <RootRouteNodeContext.Provider value={routes}>\n {children}\n </RootRouteNodeContext.Provider>\n );\n}\n\nexport function ContextNavigator({ context }: { context: RequireContext }) {\n const Tutorial = useTutorial(context);\n if (Tutorial) {\n SplashScreen.hideAsync();\n return <Tutorial />;\n }\n\n return (\n <RootRouteNodeProvider context={context}>\n <ContextNavigationContainer>\n <InitialRootStateProvider>\n <RootRoute />\n </InitialRootStateProvider>\n </ContextNavigationContainer>\n </RootRouteNodeProvider>\n );\n}\n\nfunction RootRoute() {\n const root = useRootRouteNodeContext();\n const Component = getQualifiedRouteComponent(root);\n // @ts-expect-error: TODO: Drop navigation and route props\n return <Component />;\n}\n"]}
package/build/Route.d.ts CHANGED
@@ -1,6 +1,10 @@
1
1
  import { ReactNode } from "react";
2
2
  /** The list of input keys will become optional, everything else will remain the same. */
3
3
  export declare type PickPartial<T, K extends keyof T> = Omit<T, K> & Partial<Pick<T, K>>;
4
+ export declare type DynamicConvention = {
5
+ name: string;
6
+ deep: boolean;
7
+ };
4
8
  export declare type RouteNode = {
5
9
  /** Load a route into memory. Returns the exports from a route. */
6
10
  loadRoute: () => any;
@@ -9,10 +13,7 @@ export declare type RouteNode = {
9
13
  /** nested routes */
10
14
  children: RouteNode[];
11
15
  /** Is the route a dynamic path */
12
- dynamic: null | {
13
- name: string;
14
- deep: boolean;
15
- };
16
+ dynamic: null | DynamicConvention[];
16
17
  /** `index`, `error-boundary`, etc. */
17
18
  route: string;
18
19
  /** require.context key, used for matching children. */
@@ -1 +1 @@
1
- {"version":3,"file":"Route.d.ts","sourceRoot":"","sources":["../src/Route.tsx"],"names":[],"mappings":"AAAA,OAAc,EAAE,SAAS,EAAc,MAAM,OAAO,CAAC;AAKrD,yFAAyF;AACzF,oBAAY,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,oBAAY,SAAS,GAAG;IACtB,kEAAkE;IAClE,SAAS,EAAE,MAAM,GAAG,CAAC;IAErB,iCAAiC;IACjC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,oBAAoB;IACpB,QAAQ,EAAE,SAAS,EAAE,CAAC;IACtB,kCAAkC;IAClC,OAAO,EAAE,IAAI,GAAG;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,OAAO,CAAA;KAAE,CAAC;IAChD,sCAAsC;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,uDAAuD;IACvD,UAAU,EAAE,MAAM,CAAC;IACnB,sBAAsB;IACtB,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB,wFAAwF;IACxF,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAWF,+DAA+D;AAC/D,wBAAgB,YAAY,IAAI,SAAS,GAAG,IAAI,CAE/C;AAED,wBAAgB,aAAa,IAAI,MAAM,CAMtC;AAED,iEAAiE;AACjE,wBAAgB,KAAK,CAAC,EACpB,QAAQ,EACR,IAAI,GACL,EAAE;IACD,QAAQ,EAAE,SAAS,CAAC;IACpB,IAAI,EAAE,SAAS,CAAC;CACjB,eAkBA;AAED,wBAAgB,YAAY,IAAI,SAAS,GAAG,IAAI,CAE/C;AAED,wBAAgB,qBAAqB,CAAC,gBAAgB,CAAC,EAAE,MAAM,OAClD,SAAS,KAAK,SAAS,KAAG,MAAM,CAW5C;AACD,wBAAgB,UAAU,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,GAAG,MAAM,CA4B7D"}
1
+ {"version":3,"file":"Route.d.ts","sourceRoot":"","sources":["../src/Route.tsx"],"names":[],"mappings":"AAAA,OAAc,EAAE,SAAS,EAAc,MAAM,OAAO,CAAC;AAKrD,yFAAyF;AACzF,oBAAY,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,oBAAY,iBAAiB,GAAG;IAAE,IAAI,EAAE,MAAM,CAAC;IAAC,IAAI,EAAE,OAAO,CAAA;CAAE,CAAC;AAEhE,oBAAY,SAAS,GAAG;IACtB,kEAAkE;IAClE,SAAS,EAAE,MAAM,GAAG,CAAC;IAErB,iCAAiC;IACjC,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,oBAAoB;IACpB,QAAQ,EAAE,SAAS,EAAE,CAAC;IACtB,kCAAkC;IAClC,OAAO,EAAE,IAAI,GAAG,iBAAiB,EAAE,CAAC;IACpC,sCAAsC;IACtC,KAAK,EAAE,MAAM,CAAC;IACd,uDAAuD;IACvD,UAAU,EAAE,MAAM,CAAC;IACnB,sBAAsB;IACtB,SAAS,CAAC,EAAE,OAAO,CAAC;IAEpB,wFAAwF;IACxF,QAAQ,CAAC,EAAE,OAAO,CAAC;CACpB,CAAC;AAWF,+DAA+D;AAC/D,wBAAgB,YAAY,IAAI,SAAS,GAAG,IAAI,CAE/C;AAED,wBAAgB,aAAa,IAAI,MAAM,CAMtC;AAED,iEAAiE;AACjE,wBAAgB,KAAK,CAAC,EACpB,QAAQ,EACR,IAAI,GACL,EAAE;IACD,QAAQ,EAAE,SAAS,CAAC;IACpB,IAAI,EAAE,SAAS,CAAC;CACjB,eAkBA;AAED,wBAAgB,YAAY,IAAI,SAAS,GAAG,IAAI,CAE/C;AAED,wBAAgB,qBAAqB,CAAC,gBAAgB,CAAC,EAAE,MAAM,OAClD,SAAS,KAAK,SAAS,KAAG,MAAM,CAW5C;AAED,wBAAgB,UAAU,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,GAAG,MAAM,CAmC7D"}
package/build/Route.js CHANGED
@@ -56,11 +56,18 @@ export function sortRoutes(a, b) {
56
56
  return -1;
57
57
  }
58
58
  if (a.dynamic && b.dynamic) {
59
- if (a.dynamic.deep && !b.dynamic.deep) {
60
- return 1;
59
+ if (a.dynamic.length !== b.dynamic.length) {
60
+ return b.dynamic.length - a.dynamic.length;
61
61
  }
62
- if (!a.dynamic.deep && b.dynamic.deep) {
63
- return -1;
62
+ for (let i = 0; i < a.dynamic.length; i++) {
63
+ const aDynamic = a.dynamic[i];
64
+ const bDynamic = b.dynamic[i];
65
+ if (aDynamic.deep && !bDynamic.deep) {
66
+ return 1;
67
+ }
68
+ if (!aDynamic.deep && bDynamic.deep) {
69
+ return -1;
70
+ }
64
71
  }
65
72
  return 0;
66
73
  }
@@ -1 +1 @@
1
- {"version":3,"file":"Route.js","sourceRoot":"","sources":["../src/Route.tsx"],"names":[],"mappings":"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","sourcesContent":["import React, { ReactNode, useContext } from \"react\";\n\nimport { RootRouteNodeContext } from \"./context\";\nimport { getNameFromFilePath, matchFragmentName } from \"./matchers\";\n\n/** The list of input keys will become optional, everything else will remain the same. */\nexport type PickPartial<T, K extends keyof T> = Omit<T, K> &\n Partial<Pick<T, K>>;\n\nexport type RouteNode = {\n /** Load a route into memory. Returns the exports from a route. */\n loadRoute: () => any;\n\n /** Loaded initial route name. */\n initialRouteName?: string;\n /** nested routes */\n children: RouteNode[];\n /** Is the route a dynamic path */\n dynamic: null | { name: string; deep: boolean };\n /** `index`, `error-boundary`, etc. */\n route: string;\n /** require.context key, used for matching children. */\n contextKey: string;\n /** Added in-memory */\n generated?: boolean;\n\n /** Internal screens like the directory or the auto 404 should be marked as internal. */\n internal?: boolean;\n};\n\nconst CurrentRoutePathContext = React.createContext<string | null>(null);\n\nconst CurrentRouteContext = React.createContext<RouteNode | null>(null);\n\nif (process.env.NODE_ENV !== \"production\") {\n CurrentRoutePathContext.displayName = \"RoutePath\";\n CurrentRouteContext.displayName = \"Route\";\n}\n\n/** Return the RouteNode at the current contextual boundary. */\nexport function useRouteNode(): RouteNode | null {\n return useContext(CurrentRouteContext);\n}\n\nexport function useContextKey(): string {\n const filename = useContext(CurrentRoutePathContext);\n if (filename == null) {\n throw new Error(\"No filename found. This is likely a bug in expo-router.\");\n }\n return filename;\n}\n\n/** Provides the matching routes and filename to the children. */\nexport function Route({\n children,\n node,\n}: {\n children: ReactNode;\n node: RouteNode;\n}) {\n const normalName = React.useMemo(() => {\n // The root path is `` (empty string) so always prepend `/` to ensure\n // there is some value.\n const normal = \"/\" + getNameFromFilePath(node.contextKey);\n if (!normal.endsWith(\"_layout\")) {\n return normal;\n }\n return normal.replace(/\\/?_layout$/, \"\");\n }, [node.contextKey]);\n\n return (\n <CurrentRoutePathContext.Provider value={normalName}>\n <CurrentRouteContext.Provider value={node}>\n {children}\n </CurrentRouteContext.Provider>\n </CurrentRoutePathContext.Provider>\n );\n}\n\nexport function useRootRoute(): RouteNode | null {\n return useContext(RootRouteNodeContext);\n}\n\nexport function sortRoutesWithInitial(initialRouteName?: string) {\n return (a: RouteNode, b: RouteNode): number => {\n if (initialRouteName) {\n if (a.route === initialRouteName) {\n return -1;\n }\n if (b.route === initialRouteName) {\n return 1;\n }\n }\n return sortRoutes(a, b);\n };\n}\nexport function sortRoutes(a: RouteNode, b: RouteNode): number {\n if (a.dynamic && !b.dynamic) {\n return 1;\n }\n if (!a.dynamic && b.dynamic) {\n return -1;\n }\n if (a.dynamic && b.dynamic) {\n if (a.dynamic.deep && !b.dynamic.deep) {\n return 1;\n }\n if (!a.dynamic.deep && b.dynamic.deep) {\n return -1;\n }\n return 0;\n }\n\n const aIndex = a.route === \"index\" || matchFragmentName(a.route) != null;\n const bIndex = b.route === \"index\" || matchFragmentName(b.route) != null;\n\n if (aIndex && !bIndex) {\n return -1;\n }\n if (!aIndex && bIndex) {\n return 1;\n }\n\n return a.route.length - b.route.length;\n}\n"]}
1
+ {"version":3,"file":"Route.js","sourceRoot":"","sources":["../src/Route.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAa,UAAU,EAAE,MAAM,OAAO,CAAC;AAErD,OAAO,EAAE,oBAAoB,EAAE,MAAM,WAAW,CAAC;AACjD,OAAO,EAAE,mBAAmB,EAAE,iBAAiB,EAAE,MAAM,YAAY,CAAC;AA6BpE,MAAM,uBAAuB,GAAG,KAAK,CAAC,aAAa,CAAgB,IAAI,CAAC,CAAC;AAEzE,MAAM,mBAAmB,GAAG,KAAK,CAAC,aAAa,CAAmB,IAAI,CAAC,CAAC;AAExE,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,EAAE;IACzC,uBAAuB,CAAC,WAAW,GAAG,WAAW,CAAC;IAClD,mBAAmB,CAAC,WAAW,GAAG,OAAO,CAAC;CAC3C;AAED,+DAA+D;AAC/D,MAAM,UAAU,YAAY;IAC1B,OAAO,UAAU,CAAC,mBAAmB,CAAC,CAAC;AACzC,CAAC;AAED,MAAM,UAAU,aAAa;IAC3B,MAAM,QAAQ,GAAG,UAAU,CAAC,uBAAuB,CAAC,CAAC;IACrD,IAAI,QAAQ,IAAI,IAAI,EAAE;QACpB,MAAM,IAAI,KAAK,CAAC,yDAAyD,CAAC,CAAC;KAC5E;IACD,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,iEAAiE;AACjE,MAAM,UAAU,KAAK,CAAC,EACpB,QAAQ,EACR,IAAI,GAIL;IACC,MAAM,UAAU,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE;QACpC,qEAAqE;QACrE,uBAAuB;QACvB,MAAM,MAAM,GAAG,GAAG,GAAG,mBAAmB,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC;QAC1D,IAAI,CAAC,MAAM,CAAC,QAAQ,CAAC,SAAS,CAAC,EAAE;YAC/B,OAAO,MAAM,CAAC;SACf;QACD,OAAO,MAAM,CAAC,OAAO,CAAC,aAAa,EAAE,EAAE,CAAC,CAAC;IAC3C,CAAC,EAAE,CAAC,IAAI,CAAC,UAAU,CAAC,CAAC,CAAC;IAEtB,OAAO,CACL,oBAAC,uBAAuB,CAAC,QAAQ,IAAC,KAAK,EAAE,UAAU;QACjD,oBAAC,mBAAmB,CAAC,QAAQ,IAAC,KAAK,EAAE,IAAI,IACtC,QAAQ,CACoB,CACE,CACpC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,YAAY;IAC1B,OAAO,UAAU,CAAC,oBAAoB,CAAC,CAAC;AAC1C,CAAC;AAED,MAAM,UAAU,qBAAqB,CAAC,gBAAyB;IAC7D,OAAO,CAAC,CAAY,EAAE,CAAY,EAAU,EAAE;QAC5C,IAAI,gBAAgB,EAAE;YACpB,IAAI,CAAC,CAAC,KAAK,KAAK,gBAAgB,EAAE;gBAChC,OAAO,CAAC,CAAC,CAAC;aACX;YACD,IAAI,CAAC,CAAC,KAAK,KAAK,gBAAgB,EAAE;gBAChC,OAAO,CAAC,CAAC;aACV;SACF;QACD,OAAO,UAAU,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;IAC1B,CAAC,CAAC;AACJ,CAAC;AAED,MAAM,UAAU,UAAU,CAAC,CAAY,EAAE,CAAY;IACnD,IAAI,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,CAAC,OAAO,EAAE;QAC3B,OAAO,CAAC,CAAC;KACV;IACD,IAAI,CAAC,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,OAAO,EAAE;QAC3B,OAAO,CAAC,CAAC,CAAC;KACX;IACD,IAAI,CAAC,CAAC,OAAO,IAAI,CAAC,CAAC,OAAO,EAAE;QAC1B,IAAI,CAAC,CAAC,OAAO,CAAC,MAAM,KAAK,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE;YACzC,OAAO,CAAC,CAAC,OAAO,CAAC,MAAM,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,CAAC;SAC5C;QACD,KAAK,IAAI,CAAC,GAAG,CAAC,EAAE,CAAC,GAAG,CAAC,CAAC,OAAO,CAAC,MAAM,EAAE,CAAC,EAAE,EAAE;YACzC,MAAM,QAAQ,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;YAC9B,MAAM,QAAQ,GAAG,CAAC,CAAC,OAAO,CAAC,CAAC,CAAC,CAAC;YAC9B,IAAI,QAAQ,CAAC,IAAI,IAAI,CAAC,QAAQ,CAAC,IAAI,EAAE;gBACnC,OAAO,CAAC,CAAC;aACV;YACD,IAAI,CAAC,QAAQ,CAAC,IAAI,IAAI,QAAQ,CAAC,IAAI,EAAE;gBACnC,OAAO,CAAC,CAAC,CAAC;aACX;SACF;QACD,OAAO,CAAC,CAAC;KACV;IAED,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,KAAK,OAAO,IAAI,iBAAiB,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC;IACzE,MAAM,MAAM,GAAG,CAAC,CAAC,KAAK,KAAK,OAAO,IAAI,iBAAiB,CAAC,CAAC,CAAC,KAAK,CAAC,IAAI,IAAI,CAAC;IAEzE,IAAI,MAAM,IAAI,CAAC,MAAM,EAAE;QACrB,OAAO,CAAC,CAAC,CAAC;KACX;IACD,IAAI,CAAC,MAAM,IAAI,MAAM,EAAE;QACrB,OAAO,CAAC,CAAC;KACV;IAED,OAAO,CAAC,CAAC,KAAK,CAAC,MAAM,GAAG,CAAC,CAAC,KAAK,CAAC,MAAM,CAAC;AACzC,CAAC","sourcesContent":["import React, { ReactNode, useContext } from \"react\";\n\nimport { RootRouteNodeContext } from \"./context\";\nimport { getNameFromFilePath, matchFragmentName } from \"./matchers\";\n\n/** The list of input keys will become optional, everything else will remain the same. */\nexport type PickPartial<T, K extends keyof T> = Omit<T, K> &\n Partial<Pick<T, K>>;\n\nexport type DynamicConvention = { name: string; deep: boolean };\n\nexport type RouteNode = {\n /** Load a route into memory. Returns the exports from a route. */\n loadRoute: () => any;\n\n /** Loaded initial route name. */\n initialRouteName?: string;\n /** nested routes */\n children: RouteNode[];\n /** Is the route a dynamic path */\n dynamic: null | DynamicConvention[];\n /** `index`, `error-boundary`, etc. */\n route: string;\n /** require.context key, used for matching children. */\n contextKey: string;\n /** Added in-memory */\n generated?: boolean;\n\n /** Internal screens like the directory or the auto 404 should be marked as internal. */\n internal?: boolean;\n};\n\nconst CurrentRoutePathContext = React.createContext<string | null>(null);\n\nconst CurrentRouteContext = React.createContext<RouteNode | null>(null);\n\nif (process.env.NODE_ENV !== \"production\") {\n CurrentRoutePathContext.displayName = \"RoutePath\";\n CurrentRouteContext.displayName = \"Route\";\n}\n\n/** Return the RouteNode at the current contextual boundary. */\nexport function useRouteNode(): RouteNode | null {\n return useContext(CurrentRouteContext);\n}\n\nexport function useContextKey(): string {\n const filename = useContext(CurrentRoutePathContext);\n if (filename == null) {\n throw new Error(\"No filename found. This is likely a bug in expo-router.\");\n }\n return filename;\n}\n\n/** Provides the matching routes and filename to the children. */\nexport function Route({\n children,\n node,\n}: {\n children: ReactNode;\n node: RouteNode;\n}) {\n const normalName = React.useMemo(() => {\n // The root path is `` (empty string) so always prepend `/` to ensure\n // there is some value.\n const normal = \"/\" + getNameFromFilePath(node.contextKey);\n if (!normal.endsWith(\"_layout\")) {\n return normal;\n }\n return normal.replace(/\\/?_layout$/, \"\");\n }, [node.contextKey]);\n\n return (\n <CurrentRoutePathContext.Provider value={normalName}>\n <CurrentRouteContext.Provider value={node}>\n {children}\n </CurrentRouteContext.Provider>\n </CurrentRoutePathContext.Provider>\n );\n}\n\nexport function useRootRoute(): RouteNode | null {\n return useContext(RootRouteNodeContext);\n}\n\nexport function sortRoutesWithInitial(initialRouteName?: string) {\n return (a: RouteNode, b: RouteNode): number => {\n if (initialRouteName) {\n if (a.route === initialRouteName) {\n return -1;\n }\n if (b.route === initialRouteName) {\n return 1;\n }\n }\n return sortRoutes(a, b);\n };\n}\n\nexport function sortRoutes(a: RouteNode, b: RouteNode): number {\n if (a.dynamic && !b.dynamic) {\n return 1;\n }\n if (!a.dynamic && b.dynamic) {\n return -1;\n }\n if (a.dynamic && b.dynamic) {\n if (a.dynamic.length !== b.dynamic.length) {\n return b.dynamic.length - a.dynamic.length;\n }\n for (let i = 0; i < a.dynamic.length; i++) {\n const aDynamic = a.dynamic[i];\n const bDynamic = b.dynamic[i];\n if (aDynamic.deep && !bDynamic.deep) {\n return 1;\n }\n if (!aDynamic.deep && bDynamic.deep) {\n return -1;\n }\n }\n return 0;\n }\n\n const aIndex = a.route === \"index\" || matchFragmentName(a.route) != null;\n const bIndex = b.route === \"index\" || matchFragmentName(b.route) != null;\n\n if (aIndex && !bIndex) {\n return -1;\n }\n if (!aIndex && bIndex) {\n return 1;\n }\n\n return a.route.length - b.route.length;\n}\n"]}
@@ -242,16 +242,17 @@ function getPathFromResolvedState(state, configs, { preserveFragments, preserveD
242
242
  }
243
243
  else {
244
244
  // Finished crawling state.
245
+ const outputParams = preserveDynamicRoutes ? params : focusedParams;
245
246
  // Check for query params before exiting.
246
- if (focusedParams) {
247
- for (const param in focusedParams) {
247
+ if (outputParams) {
248
+ for (const param in outputParams) {
248
249
  // TODO: This is not good. We shouldn't squat strings named "undefined".
249
- if (focusedParams[param] === "undefined") {
250
+ if (outputParams[param] === "undefined") {
250
251
  // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
251
- delete focusedParams[param];
252
+ delete outputParams[param];
252
253
  }
253
254
  }
254
- const query = queryString.stringify(focusedParams, { sort: false });
255
+ const query = queryString.stringify(outputParams, { sort: false });
255
256
  if (query) {
256
257
  path += `?${query}`;
257
258
  }
@@ -1 +1 @@
1
- {"version":3,"file":"getPathFromState.js","sourceRoot":"","sources":["../../src/fork/getPathFromState.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n PathConfig,\n PathConfigMap,\n validatePathConfig,\n} from \"@react-navigation/core\";\nimport type {\n NavigationState,\n PartialState,\n Route,\n} from \"@react-navigation/routers\";\nimport * as queryString from \"query-string\";\n\nimport {\n matchDeepDynamicRouteName,\n matchDynamicName,\n matchFragmentName,\n} from \"../matchers\";\n\ntype Options<ParamList extends object> = {\n initialRouteName?: string;\n screens: PathConfigMap<ParamList>;\n};\n\nexport type State =\n | NavigationState\n | Omit<PartialState<NavigationState>, \"stale\">;\n\ntype StringifyConfig = Record<string, (value: any) => string>;\n\ntype ConfigItem = {\n pattern?: string;\n stringify?: StringifyConfig;\n screens?: Record<string, ConfigItem>;\n // Used as fallback for fragments\n initialRouteName?: string;\n};\n\ntype CustomRoute = Route<string> & {\n state?: State;\n};\n\nconst getActiveRoute = (state: State): { name: string; params?: object } => {\n const route =\n typeof state.index === \"number\"\n ? state.routes[state.index]\n : state.routes[state.routes.length - 1];\n\n if (route.state) {\n return getActiveRoute(route.state);\n }\n\n if (route && isInvalidParams(route.params)) {\n return getActiveRoute(createFakeState(route.params));\n }\n\n return route;\n};\n\nfunction createFakeState(params: StateAsParams) {\n return {\n stale: false,\n type: \"UNKNOWN\",\n key: \"UNKNOWN\",\n index: 0,\n routeNames: [],\n routes: [\n {\n key: \"UNKNOWN\",\n name: params.screen,\n params: params.params,\n path: params.path,\n },\n ],\n };\n}\n\nfunction segmentMatchesConvention(segment: string): boolean {\n return (\n segment === \"index\" ||\n matchDynamicName(segment) != null ||\n matchFragmentName(segment) != null ||\n matchDeepDynamicRouteName(segment) != null\n );\n}\n\nfunction encodeURIComponentPreservingBrackets(str: string) {\n return encodeURIComponent(str).replace(/%5B/g, \"[\").replace(/%5D/g, \"]\");\n}\n\n/**\n * Utility to serialize a navigation state object to a path string.\n *\n * @example\n * ```js\n * getPathFromState(\n * {\n * routes: [\n * {\n * name: 'Chat',\n * params: { author: 'Jane', id: 42 },\n * },\n * ],\n * },\n * {\n * screens: {\n * Chat: {\n * path: 'chat/:author/:id',\n * stringify: { author: author => author.toLowerCase() }\n * }\n * }\n * }\n * )\n * ```\n *\n * @param state Navigation state to serialize.\n * @param options Extra options to fine-tune how to serialize the path.\n * @returns Path representing the state, e.g. /foo/bar?count=42.\n */\nexport default function getPathFromState<ParamList extends object>(\n state: State,\n // @ts-expect-error: non-standard options\n _options?: Options<ParamList> & {\n preserveFragments?: boolean;\n preserveDynamicRoutes?: boolean;\n } = {}\n): string {\n if (state == null) {\n throw Error(\n \"Got 'undefined' for the navigation state. You must pass a valid state object.\"\n );\n }\n\n const { preserveFragments, preserveDynamicRoutes, ...options } = _options;\n\n if (_options) {\n validatePathConfig(options);\n }\n\n const screens = options?.screens;\n // Expo Router disallows usage without a linking config.\n if (!screens) {\n throw Error(\n \"You must pass a 'screens' object to 'getPathFromState' to generate a path.\"\n );\n }\n\n return getPathFromResolvedState(\n state,\n // Create a normalized configs object which will be easier to use\n createNormalizedConfigs(screens),\n { preserveFragments, preserveDynamicRoutes }\n );\n}\n\nfunction processParamsWithUserSettings(\n configItem: ConfigItem,\n params: Record<string, any>\n) {\n const stringify = configItem?.stringify;\n\n return Object.fromEntries(\n Object.entries(params).map(([key, value]) => [\n key,\n // TODO: Strip nullish values here.\n stringify?.[key] ? stringify[key](value) : String(value),\n ])\n );\n}\n\nfunction deepEqual(a: any, b: any) {\n if (a === b) {\n return true;\n }\n\n if (Array.isArray(a) && Array.isArray(b)) {\n if (a.length !== b.length) {\n return false;\n }\n\n for (let i = 0; i < a.length; i++) {\n if (!deepEqual(a[i], b[i])) {\n return false;\n }\n }\n\n return true;\n }\n\n if (typeof a === \"object\" && typeof b === \"object\") {\n const keysA = Object.keys(a);\n const keysB = Object.keys(b);\n\n if (keysA.length !== keysB.length) {\n return false;\n }\n\n for (const key of keysA) {\n if (!deepEqual(a[key], b[key])) {\n return false;\n }\n }\n\n return true;\n }\n\n return false;\n}\n\nfunction walkConfigItems(\n route: CustomRoute,\n focusedRoute: {\n name: string;\n params?: object;\n },\n configs: Record<string, ConfigItem>\n) {\n // NOTE(EvanBacon): Fill in current route using state that was passed as params.\n if (!route.state && isInvalidParams(route.params)) {\n route.state = createFakeState(route.params);\n }\n\n let pattern: string | null = null;\n let focusedParams: Record<string, any> | undefined;\n\n const collectedParams: Record<string, any> = {};\n\n while (route.name in configs) {\n const configItem = configs[route.name];\n const inputPattern = configItem.pattern;\n\n if (inputPattern == null) {\n // This should never happen in Expo Router.\n throw new Error(\"Unexpected: No pattern found for route \" + route.name);\n }\n pattern = inputPattern;\n\n if (route.params) {\n const params = processParamsWithUserSettings(configItem, route.params);\n\n // TODO: Does this need to be a null check?\n if (pattern) {\n Object.assign(collectedParams, params);\n }\n if (deepEqual(focusedRoute, route)) {\n // If this is the focused route, keep the params for later use\n // We save it here since it's been stringified already\n focusedParams = getParamsWithConventionsCollapsed({\n params,\n pattern,\n routeName: route.name,\n });\n }\n }\n\n if (!route.state && isInvalidParams(route.params)) {\n route.state = createFakeState(route.params);\n }\n\n // If there is no `screens` property or no nested state, we return pattern\n if (!configItem.screens || route.state === undefined) {\n if (\n configItem.initialRouteName &&\n configItem.screens &&\n configItem.initialRouteName in configItem.screens &&\n configItem.screens[configItem.initialRouteName]?.pattern\n ) {\n const initialRouteConfig =\n configItem.screens[configItem.initialRouteName];\n\n // NOTE(EvanBacon): Big hack to support initial route changes in tab bars.\n pattern = initialRouteConfig.pattern!;\n\n if (focusedParams) {\n // If this is the focused route, keep the params for later use\n // We save it here since it's been stringified already\n focusedParams = getParamsWithConventionsCollapsed({\n params: focusedParams,\n pattern,\n routeName: route.name,\n });\n }\n }\n break;\n }\n\n const index = route.state.index ?? route.state.routes.length - 1;\n\n const nextRoute = route.state.routes[index];\n const nestedScreens = configItem.screens;\n\n // if there is config for next route name, we go deeper\n if (nestedScreens && nextRoute.name in nestedScreens) {\n route = nextRoute as CustomRoute;\n configs = nestedScreens;\n } else {\n // If not, there is no sense in going deeper in config\n break;\n }\n }\n\n if (pattern && !focusedParams && focusedRoute.params) {\n // If this is the focused route, keep the params for later use\n // We save it here since it's been stringified already\n focusedParams = getParamsWithConventionsCollapsed({\n params: focusedRoute.params,\n pattern,\n routeName: route.name,\n });\n Object.assign(focusedParams, collectedParams);\n }\n\n if (pattern == null) {\n throw new Error(\n `No pattern found for route \"${route.name}\". Options are: ${Object.keys(\n configs\n ).join(\", \")}.`\n );\n }\n\n return {\n pattern,\n nextRoute: route,\n focusedParams,\n params: collectedParams,\n };\n}\n\nfunction getPathFromResolvedState(\n state: State,\n configs: Record<string, ConfigItem>,\n {\n preserveFragments,\n preserveDynamicRoutes,\n }: { preserveFragments?: boolean; preserveDynamicRoutes?: boolean }\n) {\n let path = \"\";\n let current: State = state;\n\n const allParams: Record<string, any> = {};\n\n while (current) {\n path += \"/\";\n\n const route = current.routes[current.index ?? 0] as CustomRoute;\n // NOTE(EvanBacon): Fill in current route using state that was passed as params.\n // if (isInvalidParams(route.params)) {\n if (!route.state && isInvalidParams(route.params)) {\n route.state = createFakeState(route.params);\n }\n\n const { pattern, params, nextRoute, focusedParams } = walkConfigItems(\n route,\n getActiveRoute(current),\n { ...configs }\n );\n\n Object.assign(allParams, params);\n\n path += getPathWithConventionsCollapsed({\n pattern,\n routePath: nextRoute.path,\n params: allParams,\n initialRouteName: configs[nextRoute.name]?.initialRouteName,\n preserveFragments,\n preserveDynamicRoutes,\n });\n\n if (nextRoute.state) {\n // Continue looping with the next state if available.\n current = nextRoute.state;\n } else {\n // Finished crawling state.\n\n // Check for query params before exiting.\n if (focusedParams) {\n for (const param in focusedParams) {\n // TODO: This is not good. We shouldn't squat strings named \"undefined\".\n if (focusedParams[param] === \"undefined\") {\n // eslint-disable-next-line @typescript-eslint/no-dynamic-delete\n delete focusedParams[param];\n }\n }\n\n const query = queryString.stringify(focusedParams, { sort: false });\n\n if (query) {\n path += `?${query}`;\n }\n }\n break;\n }\n }\n return basicSanitizePath(path);\n}\n\nfunction getPathWithConventionsCollapsed({\n pattern,\n routePath,\n params,\n preserveFragments,\n preserveDynamicRoutes,\n initialRouteName,\n}: {\n pattern: string;\n routePath?: string;\n params: Record<string, any>;\n preserveFragments?: boolean;\n preserveDynamicRoutes?: boolean;\n initialRouteName?: string;\n}) {\n const segments = pattern.split(\"/\");\n return segments\n .map((p, i) => {\n const name = getParamName(p);\n\n // We don't know what to show for wildcard patterns\n // Showing the route name seems ok, though whatever we show here will be incorrect\n // Since the page doesn't actually exist\n if (p === \"*\") {\n if (i === 0) {\n // This can occur when a wildcard matches all routes and the given path was `/`.\n return routePath;\n }\n // remove existing segments from route.path and return it\n // this is used for nested wildcard routes. Without this, the path would add\n // all nested segments to the beginning of the wildcard route.\n return routePath\n ?.split(\"/\")\n .slice(i + 1)\n .join(\"/\");\n }\n\n // If the path has a pattern for a param, put the param in the path\n if (p.startsWith(\":\")) {\n if (preserveDynamicRoutes) {\n return `[${name}]`;\n }\n // Optional params without value assigned in route.params should be ignored\n return params[name];\n }\n\n if (!preserveFragments && matchFragmentName(p) != null) {\n // When the last part is a fragment it could be a shared URL\n // if the route has an initialRouteName defined, then we should\n // use that as the component path as we can assume it will be shown.\n if (segments.length - 1 === i) {\n if (initialRouteName) {\n // Return an empty string if the init route is ambiguous.\n if (segmentMatchesConvention(initialRouteName)) {\n return \"\";\n }\n return encodeURIComponentPreservingBrackets(initialRouteName);\n }\n }\n return \"\";\n }\n // Preserve dynamic syntax for rehydration\n return encodeURIComponentPreservingBrackets(p);\n })\n .map((v) => v ?? \"\")\n .join(\"/\");\n}\n\n/** Given a set of query params and a pattern with possible conventions, collapse the conventions and return the remaining params. */\nfunction getParamsWithConventionsCollapsed({\n pattern,\n routeName,\n params,\n}: {\n pattern: string;\n /** Route name is required for matching the wildcard route. This is specific to Expo Router. */\n routeName: string;\n params: object;\n}): Record<string, string> {\n const processedParams = { ...params };\n\n // Remove the params present in the pattern since we'll only use the rest for query string\n\n const segments = pattern.split(\"/\");\n\n // Dynamic Routes\n segments\n .filter((segment) => segment.startsWith(\":\"))\n .forEach((segment) => {\n const name = getParamName(segment);\n delete processedParams[name];\n });\n\n // Deep Dynamic Routes\n if (segments.some((segment) => segment === \"*\")) {\n // NOTE(EvanBacon): Drop the param name matching the wildcard route name -- this is specific to Expo Router.\n const name = matchDeepDynamicRouteName(routeName) ?? routeName;\n delete processedParams[name];\n }\n\n return processedParams;\n}\n\n// Remove multiple as well as trailing slashes\nfunction basicSanitizePath(path: string) {\n // Remove duplicate slashes like `foo//bar` -> `foo/bar`\n const simplifiedPath = path.replace(/\\/+/g, \"/\");\n if (simplifiedPath.length <= 1) {\n return simplifiedPath;\n }\n // Remove trailing slash like `foo/bar/` -> `foo/bar`\n return simplifiedPath.replace(/\\/$/, \"\");\n}\n\ntype StateAsParams = {\n initial: boolean;\n path?: string;\n screen: string;\n params: Record<string, any>;\n};\n\n// TODO: Make StackRouter not do this...\n// Detect if the params came from StackRouter using `params` to pass around internal state.\nfunction isInvalidParams(\n params?: Record<string, any>\n): params is StateAsParams {\n if (!params) {\n return false;\n }\n\n if (\n \"params\" in params &&\n typeof params.params === \"object\" &&\n !!params.params\n ) {\n return true;\n }\n\n return (\n \"initial\" in params &&\n typeof params.initial === \"boolean\" &&\n // \"path\" in params &&\n \"screen\" in params\n );\n}\n\nconst getParamName = (pattern: string) =>\n pattern.replace(/^:/, \"\").replace(/\\?$/, \"\");\n\nconst joinPaths = (...paths: string[]): string =>\n ([] as string[])\n .concat(...paths.map((p) => p.split(\"/\")))\n .filter(Boolean)\n .join(\"/\");\n\nconst createConfigItem = (\n config: PathConfig<object> | string,\n parentPattern?: string\n): ConfigItem => {\n if (typeof config === \"string\") {\n // If a string is specified as the value of the key(e.g. Foo: '/path'), use it as the pattern\n const pattern = parentPattern ? joinPaths(parentPattern, config) : config;\n\n return { pattern };\n }\n\n if (config.exact && config.path === undefined) {\n throw new Error(\n \"A 'path' needs to be specified when specifying 'exact: true'. If you don't want this screen in the URL, specify it as empty string, e.g. `path: ''`.\"\n );\n }\n\n // If an object is specified as the value (e.g. Foo: { ... }),\n // It can have `path` property and `screens` prop which has nested configs\n const pattern =\n config.exact !== true\n ? joinPaths(parentPattern || \"\", config.path || \"\")\n : config.path || \"\";\n\n const screens = config.screens\n ? createNormalizedConfigs(config.screens, pattern)\n : undefined;\n\n return {\n // Normalize pattern to remove any leading, trailing slashes, duplicate slashes etc.\n pattern: pattern?.split(\"/\").filter(Boolean).join(\"/\"),\n stringify: config.stringify,\n screens,\n initialRouteName: config.initialRouteName,\n };\n};\n\nconst createNormalizedConfigs = (\n options: PathConfigMap<object>,\n pattern?: string\n): Record<string, ConfigItem> =>\n Object.fromEntries(\n Object.entries(options).map(([name, c]) => [\n name,\n createConfigItem(c, pattern),\n ])\n );\n"]}
1
+ {"version":3,"file":"getPathFromState.js","sourceRoot":"","sources":["../../src/fork/getPathFromState.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n PathConfig,\n PathConfigMap,\n validatePathConfig,\n} from \"@react-navigation/core\";\nimport type {\n NavigationState,\n PartialState,\n Route,\n} from \"@react-navigation/routers\";\nimport * as queryString from \"query-string\";\n\nimport {\n matchDeepDynamicRouteName,\n matchDynamicName,\n matchFragmentName,\n} from \"../matchers\";\n\ntype Options<ParamList extends object> = {\n initialRouteName?: string;\n screens: PathConfigMap<ParamList>;\n};\n\nexport type State =\n | NavigationState\n | Omit<PartialState<NavigationState>, \"stale\">;\n\ntype StringifyConfig = Record<string, (value: any) => string>;\n\ntype ConfigItem = {\n pattern?: string;\n stringify?: StringifyConfig;\n screens?: Record<string, ConfigItem>;\n // Used as fallback for fragments\n initialRouteName?: string;\n};\n\ntype CustomRoute = Route<string> & {\n state?: State;\n};\n\nconst getActiveRoute = (state: State): { name: string; params?: object } => {\n const route =\n typeof state.index === \"number\"\n ? state.routes[state.index]\n : state.routes[state.routes.length - 1];\n\n if (route.state) {\n return getActiveRoute(route.state);\n }\n\n if (route && isInvalidParams(route.params)) {\n return getActiveRoute(createFakeState(route.params));\n }\n\n return route;\n};\n\nfunction createFakeState(params: StateAsParams) {\n return {\n stale: false,\n type: \"UNKNOWN\",\n key: \"UNKNOWN\",\n index: 0,\n routeNames: [],\n routes: [\n {\n key: \"UNKNOWN\",\n name: params.screen,\n params: params.params,\n path: params.path,\n },\n ],\n };\n}\n\nfunction segmentMatchesConvention(segment: string): boolean {\n return (\n segment === \"index\" ||\n matchDynamicName(segment) != null ||\n matchFragmentName(segment) != null ||\n matchDeepDynamicRouteName(segment) != null\n );\n}\n\nfunction encodeURIComponentPreservingBrackets(str: string) {\n return encodeURIComponent(str).replace(/%5B/g, \"[\").replace(/%5D/g, \"]\");\n}\n\n/**\n * Utility to serialize a navigation state object to a path string.\n *\n * @example\n * ```js\n * getPathFromState(\n * {\n * routes: [\n * {\n * name: 'Chat',\n * params: { author: 'Jane', id: 42 },\n * },\n * ],\n * },\n * {\n * screens: {\n * Chat: {\n * path: 'chat/:author/:id',\n * stringify: { author: author => author.toLowerCase() }\n * }\n * }\n * }\n * )\n * ```\n *\n * @param state Navigation state to serialize.\n * @param options Extra options to fine-tune how to serialize the path.\n * @returns Path representing the state, e.g. /foo/bar?count=42.\n */\nexport default function getPathFromState<ParamList extends object>(\n state: State,\n // @ts-expect-error: non-standard options\n _options?: Options<ParamList> & {\n preserveFragments?: boolean;\n preserveDynamicRoutes?: boolean;\n } = {}\n): string {\n if (state == null) {\n throw Error(\n \"Got 'undefined' for the navigation state. You must pass a valid state object.\"\n );\n }\n\n const { preserveFragments, preserveDynamicRoutes, ...options } = _options;\n\n if (_options) {\n validatePathConfig(options);\n }\n\n const screens = options?.screens;\n // Expo Router disallows usage without a linking config.\n if (!screens) {\n throw Error(\n \"You must pass a 'screens' object to 'getPathFromState' to generate a path.\"\n );\n }\n\n return getPathFromResolvedState(\n state,\n // Create a normalized configs object which will be easier to use\n createNormalizedConfigs(screens),\n { preserveFragments, preserveDynamicRoutes }\n );\n}\n\nfunction processParamsWithUserSettings(\n configItem: ConfigItem,\n params: Record<string, any>\n) {\n const stringify = configItem?.stringify;\n\n return Object.fromEntries(\n Object.entries(params).map(([key, value]) => [\n key,\n // TODO: Strip nullish values here.\n stringify?.[key] ? stringify[key](value) : String(value),\n ])\n );\n}\n\nfunction deepEqual(a: any, b: any) {\n if (a === b) {\n return true;\n }\n\n if (Array.isArray(a) && Array.isArray(b)) {\n if (a.length !== b.length) {\n return false;\n }\n\n for (let i = 0; i < a.length; i++) {\n if (!deepEqual(a[i], b[i])) {\n return false;\n }\n }\n\n return true;\n }\n\n if (typeof a === \"object\" && typeof b === \"object\") {\n const keysA = Object.keys(a);\n const keysB = Object.keys(b);\n\n if (keysA.length !== keysB.length) {\n return false;\n }\n\n for (const key of keysA) {\n if (!deepEqual(a[key], b[key])) {\n return false;\n }\n }\n\n return true;\n }\n\n return false;\n}\n\nfunction walkConfigItems(\n route: CustomRoute,\n focusedRoute: {\n name: string;\n params?: object;\n },\n configs: Record<string, ConfigItem>\n) {\n // NOTE(EvanBacon): Fill in current route using state that was passed as params.\n if (!route.state && isInvalidParams(route.params)) {\n route.state = createFakeState(route.params);\n }\n\n let pattern: string | null = null;\n let focusedParams: Record<string, any> | undefined;\n\n const collectedParams: Record<string, any> = {};\n\n while (route.name in configs) {\n const configItem = configs[route.name];\n const inputPattern = configItem.pattern;\n\n if (inputPattern == null) {\n // This should never happen in Expo Router.\n throw new Error(\"Unexpected: No pattern found for route \" + route.name);\n }\n pattern = inputPattern;\n\n if (route.params) {\n const params = processParamsWithUserSettings(configItem, route.params);\n\n // TODO: Does this need to be a null check?\n if (pattern) {\n Object.assign(collectedParams, params);\n }\n if (deepEqual(focusedRoute, route)) {\n // If this is the focused route, keep the params for later use\n // We save it here since it's been stringified already\n focusedParams = getParamsWithConventionsCollapsed({\n params,\n pattern,\n routeName: route.name,\n });\n }\n }\n\n if (!route.state && isInvalidParams(route.params)) {\n route.state = createFakeState(route.params);\n }\n\n // If there is no `screens` property or no nested state, we return pattern\n if (!configItem.screens || route.state === undefined) {\n if (\n configItem.initialRouteName &&\n configItem.screens &&\n configItem.initialRouteName in configItem.screens &&\n configItem.screens[configItem.initialRouteName]?.pattern\n ) {\n const initialRouteConfig =\n configItem.screens[configItem.initialRouteName];\n\n // NOTE(EvanBacon): Big hack to support initial route changes in tab bars.\n pattern = initialRouteConfig.pattern!;\n\n if (focusedParams) {\n // If this is the focused route, keep the params for later use\n // We save it here since it's been stringified already\n focusedParams = getParamsWithConventionsCollapsed({\n params: focusedParams,\n pattern,\n routeName: route.name,\n });\n }\n }\n break;\n }\n\n const index = route.state.index ?? route.state.routes.length - 1;\n\n const nextRoute = route.state.routes[index];\n const nestedScreens = configItem.screens;\n\n // if there is config for next route name, we go deeper\n if (nestedScreens && nextRoute.name in nestedScreens) {\n route = nextRoute as CustomRoute;\n configs = nestedScreens;\n } else {\n // If not, there is no sense in going deeper in config\n break;\n }\n }\n\n if (pattern && !focusedParams && focusedRoute.params) {\n // If this is the focused route, keep the params for later use\n // We save it here since it's been stringified already\n focusedParams = getParamsWithConventionsCollapsed({\n params: focusedRoute.params,\n pattern,\n routeName: route.name,\n });\n Object.assign(focusedParams, collectedParams);\n }\n\n if (pattern == null) {\n throw new Error(\n `No pattern found for route \"${route.name}\". Options are: ${Object.keys(\n configs\n ).join(\", \")}.`\n );\n }\n\n return {\n pattern,\n nextRoute: route,\n focusedParams,\n params: collectedParams,\n };\n}\n\nfunction getPathFromResolvedState(\n state: State,\n configs: Record<string, ConfigItem>,\n {\n preserveFragments,\n preserveDynamicRoutes,\n }: { preserveFragments?: boolean; preserveDynamicRoutes?: boolean }\n) {\n let path = \"\";\n let current: State = state;\n\n const allParams: Record<string, any> = {};\n\n while (current) {\n path += \"/\";\n\n const route = current.routes[current.index ?? 0] as CustomRoute;\n // NOTE(EvanBacon): Fill in current route using state that was passed as params.\n // if (isInvalidParams(route.params)) {\n if (!route.state && isInvalidParams(route.params)) {\n route.state = createFakeState(route.params);\n }\n\n const { pattern, params, nextRoute, focusedParams } = walkConfigItems(\n route,\n getActiveRoute(current),\n { ...configs }\n );\n\n Object.assign(allParams, params);\n\n path += getPathWithConventionsCollapsed({\n pattern,\n routePath: nextRoute.path,\n params: allParams,\n initialRouteName: configs[nextRoute.name]?.initialRouteName,\n preserveFragments,\n preserveDynamicRoutes,\n });\n\n if (nextRoute.state) {\n // Continue looping with the next state if available.\n current = nextRoute.state;\n } else {\n // Finished crawling state.\n\n const outputParams = preserveDynamicRoutes ? params : focusedParams;\n // Check for query params before exiting.\n if (outputParams) {\n for (const param in outputParams) {\n // TODO: This is not good. We shouldn't squat strings named \"undefined\".\n if (outputParams[param] === \"undefined\") {\n // eslint-disable-next-line @typescript-eslint/no-dynamic-delete\n delete outputParams[param];\n }\n }\n\n const query = queryString.stringify(outputParams, { sort: false });\n\n if (query) {\n path += `?${query}`;\n }\n }\n break;\n }\n }\n return basicSanitizePath(path);\n}\n\nfunction getPathWithConventionsCollapsed({\n pattern,\n routePath,\n params,\n preserveFragments,\n preserveDynamicRoutes,\n initialRouteName,\n}: {\n pattern: string;\n routePath?: string;\n params: Record<string, any>;\n preserveFragments?: boolean;\n preserveDynamicRoutes?: boolean;\n initialRouteName?: string;\n}) {\n const segments = pattern.split(\"/\");\n return segments\n .map((p, i) => {\n const name = getParamName(p);\n\n // We don't know what to show for wildcard patterns\n // Showing the route name seems ok, though whatever we show here will be incorrect\n // Since the page doesn't actually exist\n if (p === \"*\") {\n if (i === 0) {\n // This can occur when a wildcard matches all routes and the given path was `/`.\n return routePath;\n }\n // remove existing segments from route.path and return it\n // this is used for nested wildcard routes. Without this, the path would add\n // all nested segments to the beginning of the wildcard route.\n return routePath\n ?.split(\"/\")\n .slice(i + 1)\n .join(\"/\");\n }\n\n // If the path has a pattern for a param, put the param in the path\n if (p.startsWith(\":\")) {\n if (preserveDynamicRoutes) {\n return `[${name}]`;\n }\n // Optional params without value assigned in route.params should be ignored\n return params[name];\n }\n\n if (!preserveFragments && matchFragmentName(p) != null) {\n // When the last part is a fragment it could be a shared URL\n // if the route has an initialRouteName defined, then we should\n // use that as the component path as we can assume it will be shown.\n if (segments.length - 1 === i) {\n if (initialRouteName) {\n // Return an empty string if the init route is ambiguous.\n if (segmentMatchesConvention(initialRouteName)) {\n return \"\";\n }\n return encodeURIComponentPreservingBrackets(initialRouteName);\n }\n }\n return \"\";\n }\n // Preserve dynamic syntax for rehydration\n return encodeURIComponentPreservingBrackets(p);\n })\n .map((v) => v ?? \"\")\n .join(\"/\");\n}\n\n/** Given a set of query params and a pattern with possible conventions, collapse the conventions and return the remaining params. */\nfunction getParamsWithConventionsCollapsed({\n pattern,\n routeName,\n params,\n}: {\n pattern: string;\n /** Route name is required for matching the wildcard route. This is specific to Expo Router. */\n routeName: string;\n params: object;\n}): Record<string, string> {\n const processedParams = { ...params };\n\n // Remove the params present in the pattern since we'll only use the rest for query string\n\n const segments = pattern.split(\"/\");\n\n // Dynamic Routes\n segments\n .filter((segment) => segment.startsWith(\":\"))\n .forEach((segment) => {\n const name = getParamName(segment);\n delete processedParams[name];\n });\n\n // Deep Dynamic Routes\n if (segments.some((segment) => segment === \"*\")) {\n // NOTE(EvanBacon): Drop the param name matching the wildcard route name -- this is specific to Expo Router.\n const name = matchDeepDynamicRouteName(routeName) ?? routeName;\n delete processedParams[name];\n }\n\n return processedParams;\n}\n\n// Remove multiple as well as trailing slashes\nfunction basicSanitizePath(path: string) {\n // Remove duplicate slashes like `foo//bar` -> `foo/bar`\n const simplifiedPath = path.replace(/\\/+/g, \"/\");\n if (simplifiedPath.length <= 1) {\n return simplifiedPath;\n }\n // Remove trailing slash like `foo/bar/` -> `foo/bar`\n return simplifiedPath.replace(/\\/$/, \"\");\n}\n\ntype StateAsParams = {\n initial: boolean;\n path?: string;\n screen: string;\n params: Record<string, any>;\n};\n\n// TODO: Make StackRouter not do this...\n// Detect if the params came from StackRouter using `params` to pass around internal state.\nfunction isInvalidParams(\n params?: Record<string, any>\n): params is StateAsParams {\n if (!params) {\n return false;\n }\n\n if (\n \"params\" in params &&\n typeof params.params === \"object\" &&\n !!params.params\n ) {\n return true;\n }\n\n return (\n \"initial\" in params &&\n typeof params.initial === \"boolean\" &&\n // \"path\" in params &&\n \"screen\" in params\n );\n}\n\nconst getParamName = (pattern: string) =>\n pattern.replace(/^:/, \"\").replace(/\\?$/, \"\");\n\nconst joinPaths = (...paths: string[]): string =>\n ([] as string[])\n .concat(...paths.map((p) => p.split(\"/\")))\n .filter(Boolean)\n .join(\"/\");\n\nconst createConfigItem = (\n config: PathConfig<object> | string,\n parentPattern?: string\n): ConfigItem => {\n if (typeof config === \"string\") {\n // If a string is specified as the value of the key(e.g. Foo: '/path'), use it as the pattern\n const pattern = parentPattern ? joinPaths(parentPattern, config) : config;\n\n return { pattern };\n }\n\n if (config.exact && config.path === undefined) {\n throw new Error(\n \"A 'path' needs to be specified when specifying 'exact: true'. If you don't want this screen in the URL, specify it as empty string, e.g. `path: ''`.\"\n );\n }\n\n // If an object is specified as the value (e.g. Foo: { ... }),\n // It can have `path` property and `screens` prop which has nested configs\n const pattern =\n config.exact !== true\n ? joinPaths(parentPattern || \"\", config.path || \"\")\n : config.path || \"\";\n\n const screens = config.screens\n ? createNormalizedConfigs(config.screens, pattern)\n : undefined;\n\n return {\n // Normalize pattern to remove any leading, trailing slashes, duplicate slashes etc.\n pattern: pattern?.split(\"/\").filter(Boolean).join(\"/\"),\n stringify: config.stringify,\n screens,\n initialRouteName: config.initialRouteName,\n };\n};\n\nconst createNormalizedConfigs = (\n options: PathConfigMap<object>,\n pattern?: string\n): Record<string, ConfigItem> =>\n Object.fromEntries(\n Object.entries(options).map(([name, c]) => [\n name,\n createConfigItem(c, pattern),\n ])\n );\n"]}
@@ -1,4 +1,4 @@
1
- import { RouteNode } from "./Route";
1
+ import { DynamicConvention, RouteNode } from "./Route";
2
2
  import { RequireContext } from "./types";
3
3
  export declare type FileNode = Pick<RouteNode, "contextKey" | "loadRoute"> & {
4
4
  /** Like `(tab)/index` */
@@ -13,10 +13,8 @@ declare type TreeNode = {
13
13
  };
14
14
  /** Convert a flat map of file nodes into a nested tree of files. */
15
15
  export declare function getRecursiveTree(files: FileNode[]): TreeNode;
16
- export declare function generateDynamic(name: string): {
17
- name: string;
18
- deep: boolean;
19
- } | null;
16
+ export declare function generateDynamicFromSegment(name: string): DynamicConvention | null;
17
+ export declare function generateDynamic(name: string): RouteNode["dynamic"];
20
18
  /** Given a Metro context module, return an array of nested routes. */
21
19
  export declare function getRoutes(contextModule: RequireContext): RouteNode | null;
22
20
  /**
@@ -1 +1 @@
1
- {"version":3,"file":"getRoutes.d.ts","sourceRoot":"","sources":["../src/getRoutes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAQpC,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAGzC,oBAAY,QAAQ,GAAG,IAAI,CAAC,SAAS,EAAE,YAAY,GAAG,WAAW,CAAC,GAAG;IACnE,yBAAyB;IACzB,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,aAAK,QAAQ,GAAG;IACd,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,QAAQ,EAAE,CAAC;IACrB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,8CAA8C;IAC9C,IAAI,EAAE,QAAQ,GAAG,IAAI,CAAC;CACvB,CAAC;AAEF,oEAAoE;AACpE,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,QAAQ,CA+C5D;AAsBD,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM;;;SAK3C;AA0LD,sEAAsE;AACtE,wBAAgB,SAAS,CAAC,aAAa,EAAE,cAAc,GAAG,SAAS,GAAG,IAAI,CAezE;AA4CD;;;GAGG;AACH,wBAAgB,8BAA8B,CAC5C,MAAM,EAAE,SAAS,GAChB,SAAS,GAAG,IAAI,CAgBlB"}
1
+ {"version":3,"file":"getRoutes.d.ts","sourceRoot":"","sources":["../src/getRoutes.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,iBAAiB,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAQvD,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAGzC,oBAAY,QAAQ,GAAG,IAAI,CAAC,SAAS,EAAE,YAAY,GAAG,WAAW,CAAC,GAAG;IACnE,yBAAyB;IACzB,cAAc,EAAE,MAAM,CAAC;CACxB,CAAC;AAEF,aAAK,QAAQ,GAAG;IACd,IAAI,EAAE,MAAM,CAAC;IACb,QAAQ,EAAE,QAAQ,EAAE,CAAC;IACrB,OAAO,EAAE,MAAM,EAAE,CAAC;IAClB,8CAA8C;IAC9C,IAAI,EAAE,QAAQ,GAAG,IAAI,CAAC;CACvB,CAAC;AAEF,oEAAoE;AACpE,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,QAAQ,EAAE,GAAG,QAAQ,CA+C5D;AAsBD,wBAAgB,0BAA0B,CACxC,IAAI,EAAE,MAAM,GACX,iBAAiB,GAAG,IAAI,CAK1B;AAED,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM,GAAG,SAAS,CAAC,SAAS,CAAC,CAMlE;AA0LD,sEAAsE;AACtE,wBAAgB,SAAS,CAAC,aAAa,EAAE,cAAc,GAAG,SAAS,GAAG,IAAI,CAezE;AA4CD;;;GAGG;AACH,wBAAgB,8BAA8B,CAC5C,MAAM,EAAE,SAAS,GAChB,SAAS,GAAG,IAAI,CAgBlB"}
@@ -57,11 +57,18 @@ function assertDeprecatedFormat(tree) {
57
57
  function getTreeNodesAsRouteNodes(nodes) {
58
58
  return nodes.map(treeNodeToRouteNode).flat().filter(Boolean);
59
59
  }
60
- export function generateDynamic(name) {
60
+ export function generateDynamicFromSegment(name) {
61
61
  const deepDynamicName = matchDeepDynamicRouteName(name);
62
62
  const dynamicName = deepDynamicName ?? matchDynamicName(name);
63
63
  return dynamicName ? { name: dynamicName, deep: !!deepDynamicName } : null;
64
64
  }
65
+ export function generateDynamic(name) {
66
+ const description = name
67
+ .split("/")
68
+ .map((segment) => generateDynamicFromSegment(segment))
69
+ .filter(Boolean);
70
+ return description.length === 0 ? null : description;
71
+ }
65
72
  function collapseRouteSegments(route) {
66
73
  return stripFragmentSegmentsFromPath(route.replace(/\/index$/, ""));
67
74
  }
@@ -250,7 +257,7 @@ function appendUnmatchedRoute(routes) {
250
257
  },
251
258
  route: "[...404]",
252
259
  contextKey: "./[...404].tsx",
253
- dynamic: { name: "404", deep: true },
260
+ dynamic: [{ name: "404", deep: true }],
254
261
  children: [],
255
262
  generated: true,
256
263
  internal: true,
@@ -1 +1 @@
1
- {"version":3,"file":"getRoutes.js","sourceRoot":"","sources":["../src/getRoutes.ts"],"names":[],"mappings":"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","sourcesContent":["import { RouteNode } from \"./Route\";\nimport {\n getNameFromFilePath,\n matchDeepDynamicRouteName,\n matchDynamicName,\n matchFragmentName,\n stripFragmentSegmentsFromPath,\n} from \"./matchers\";\nimport { RequireContext } from \"./types\";\nimport { DefaultLayout } from \"./views/Layout\";\n\nexport type FileNode = Pick<RouteNode, \"contextKey\" | \"loadRoute\"> & {\n /** Like `(tab)/index` */\n normalizedName: string;\n};\n\ntype TreeNode = {\n name: string;\n children: TreeNode[];\n parents: string[];\n /** null when there is no file in a folder. */\n node: FileNode | null;\n};\n\n/** Convert a flat map of file nodes into a nested tree of files. */\nexport function getRecursiveTree(files: FileNode[]): TreeNode {\n const tree = {\n name: \"\",\n children: [],\n parents: [],\n node: null,\n };\n\n for (const file of files) {\n // ['(tab)', 'settings', '[...another]']\n const parts = file.normalizedName.split(\"/\");\n let currentNode: TreeNode = tree;\n for (let i = 0; i < parts.length; i++) {\n const part = parts[i];\n\n if (i === parts.length - 1 && part === \"_layout\") {\n if (currentNode.node) {\n const overwritten = currentNode.node.contextKey;\n throw new Error(\n `Higher priority Layout Route \"${file.contextKey}\" overriding redundant Layout Route \"${overwritten}\". Remove the Layout Route \"${overwritten}\" to fix this.`\n );\n }\n continue;\n }\n\n const existing = currentNode.children.find((item) => item.name === part);\n if (existing) {\n currentNode = existing;\n } else {\n const newNode: TreeNode = {\n name: part,\n children: [],\n parents: [...currentNode.parents, currentNode.name],\n node: null,\n };\n currentNode.children.push(newNode);\n currentNode = newNode;\n }\n }\n currentNode.node = file;\n }\n\n if (process.env.NODE_ENV !== \"production\") {\n assertDeprecatedFormat(tree);\n }\n\n return tree;\n}\n\nfunction assertDeprecatedFormat(tree: TreeNode) {\n for (const child of tree.children) {\n if (\n child.node &&\n child.children.length &&\n !child.node.normalizedName.endsWith(\"_layout\")\n ) {\n const ext = child.node.contextKey.split(\".\").pop();\n throw new Error(\n `Using deprecated Layout Route format: Move \\`./app/${child.node.normalizedName}.${ext}\\` to \\`./app/${child.node.normalizedName}/_layout.${ext}\\``\n );\n }\n assertDeprecatedFormat(child);\n }\n}\n\nfunction getTreeNodesAsRouteNodes(nodes: TreeNode[]): RouteNode[] {\n return nodes.map(treeNodeToRouteNode).flat().filter(Boolean) as RouteNode[];\n}\n\nexport function generateDynamic(name: string) {\n const deepDynamicName = matchDeepDynamicRouteName(name);\n const dynamicName = deepDynamicName ?? matchDynamicName(name);\n\n return dynamicName ? { name: dynamicName, deep: !!deepDynamicName } : null;\n}\n\nfunction collapseRouteSegments(route: string) {\n return stripFragmentSegmentsFromPath(route.replace(/\\/index$/, \"\"));\n}\n\n/**\n * Given a route node and a name representing the fragment name,\n * find the nearest child matching the name.\n *\n * Doesn't support slashes in the name.\n * Routes like `explore/(something)/index` will be matched against `explore`.\n *\n */\nfunction getDefaultInitialRoute(node: RouteNode, name: string) {\n return node.children.find(\n (node) => collapseRouteSegments(node.route) === name\n );\n}\n\nfunction applyDefaultInitialRouteName(node: RouteNode): RouteNode {\n const fragmentName = matchFragmentName(node.route);\n if (!node.children || !fragmentName) {\n return node;\n }\n\n // Guess at the initial route based on the fragment name.\n // TODO(EvanBacon): Perhaps we should attempt to warn when the fragment doesn't match any child routes.\n const initialRouteName = getDefaultInitialRoute(node, fragmentName)?.route;\n const route = {\n ...node,\n loadRoute() {\n const { unstable_settings, ...route } = node.loadRoute();\n return {\n ...route,\n unstable_settings: {\n initialRouteName:\n unstable_settings?.initialRouteName ?? initialRouteName,\n // Allow overriding the initial route name using the layout settings.\n ...unstable_settings,\n },\n };\n },\n };\n if (initialRouteName != null) {\n route.initialRouteName = initialRouteName;\n }\n return route;\n}\n\nfunction cloneFragmentRoute(\n node: RouteNode,\n { name: nextName }: { name: string }\n): RouteNode {\n const fragmentName = `(${nextName})`;\n const parts = node.contextKey.split(\"/\");\n parts[parts.length - 2] = fragmentName;\n\n return {\n ...node,\n route: fragmentName,\n contextKey: parts.join(\"/\"),\n };\n}\n\nfunction treeNodeToRouteNode({\n name,\n node,\n children,\n}: TreeNode): RouteNode[] | null {\n const dynamic = generateDynamic(name);\n\n if (node) {\n const fragmentName = matchFragmentName(name);\n const multiFragment = fragmentName?.includes(\",\");\n\n const clones = multiFragment\n ? fragmentName!.split(\",\").map((v) => ({ name: v.trim() }))\n : null;\n\n const output = {\n loadRoute: node.loadRoute,\n route: name,\n contextKey: node.contextKey,\n children: getTreeNodesAsRouteNodes(children),\n dynamic,\n };\n\n if (Array.isArray(clones)) {\n return clones.map((clone) =>\n applyDefaultInitialRouteName(cloneFragmentRoute({ ...output }, clone))\n );\n }\n\n return [\n applyDefaultInitialRouteName({\n loadRoute: node.loadRoute,\n route: name,\n contextKey: node.contextKey,\n children: getTreeNodesAsRouteNodes(children),\n dynamic,\n }),\n ];\n }\n\n // Empty folder, skip it.\n if (!children.length) {\n return null;\n }\n\n // When there's a directory, but no layout route file (with valid export), the child routes won't be grouped.\n // This pushes all children into the nearest layout route.\n return getTreeNodesAsRouteNodes(\n children.map((child) => {\n return {\n ...child,\n name: [name, child.name].filter(Boolean).join(\"/\"),\n };\n })\n );\n}\n\nfunction contextModuleToFileNodes(contextModule: RequireContext): FileNode[] {\n const nodes = contextModule.keys().map((key) => {\n // In development, check if the file exports a default component\n // this helps keep things snappy when creating files. In production we load all screens lazily.\n try {\n if (!contextModule(key)?.default) {\n return null;\n }\n } catch (error) {\n // Probably this won't stop metro from freaking out but it's worth a try.\n console.warn('Error loading route \"' + key + '\"', error);\n return null;\n }\n\n const node: FileNode = {\n loadRoute: () => contextModule(key),\n normalizedName: getNameFromFilePath(key),\n contextKey: key,\n };\n\n return node;\n });\n\n return nodes.filter(Boolean) as FileNode[];\n}\n\nfunction hasCustomRootLayoutNode(routes: RouteNode[]) {\n if (routes.length !== 1) {\n return false;\n }\n // This could either be the root _layout or an app with a single file.\n const route = routes[0];\n\n if (\n route.route === \"\" &&\n route.contextKey.match(/^\\.\\/_layout\\.([jt]sx?)$/)\n ) {\n return true;\n }\n return false;\n}\n\nfunction treeNodesToRootRoute(treeNode: TreeNode): RouteNode | null {\n const routes = treeNodeToRouteNode(treeNode);\n\n if (!routes?.length) {\n return null;\n }\n\n if (hasCustomRootLayoutNode(routes)) {\n return routes[0];\n }\n\n return {\n loadRoute: () => ({ default: DefaultLayout }),\n // Generate a fake file name for the directory\n contextKey: \"./_layout.tsx\",\n route: \"\",\n generated: true,\n dynamic: null,\n children: routes,\n };\n}\n\n/** Given a Metro context module, return an array of nested routes. */\nexport function getRoutes(contextModule: RequireContext): RouteNode | null {\n const files = contextModuleToFileNodes(contextModule);\n const treeNodes = getRecursiveTree(files);\n const route = treeNodesToRootRoute(treeNodes);\n\n if (!route) {\n return null;\n }\n\n appendSitemapRoute(route);\n\n // Auto add not found route if it doesn't exist\n appendUnmatchedRoute(route);\n\n return route;\n}\n\nfunction appendSitemapRoute(routes: RouteNode) {\n if (\n !routes.children.length ||\n // Allow overriding the sitemap route\n routes.children.some((route) => route.route === \"_sitemap\")\n ) {\n return routes;\n }\n const { Sitemap, getNavOptions } = require(\"./views/Sitemap\");\n routes.children.push({\n loadRoute() {\n return { default: Sitemap, getNavOptions };\n },\n route: \"_sitemap\",\n contextKey: \"./_sitemap.tsx\",\n generated: true,\n internal: true,\n dynamic: null,\n children: [],\n });\n return routes;\n}\n\nfunction appendUnmatchedRoute(routes: RouteNode) {\n // Auto add not found route if it doesn't exist\n const userDefinedDynamicRoute = getUserDefinedDeepDynamicRoute(routes);\n if (!userDefinedDynamicRoute) {\n routes.children.push({\n loadRoute() {\n return { default: require(\"./views/Unmatched\").Unmatched };\n },\n route: \"[...404]\",\n contextKey: \"./[...404].tsx\",\n dynamic: { name: \"404\", deep: true },\n children: [],\n generated: true,\n internal: true,\n });\n }\n return routes;\n}\n\n/**\n * Exposed for testing.\n * @returns a top-level deep dynamic route if it exists, otherwise null.\n */\nexport function getUserDefinedDeepDynamicRoute(\n routes: RouteNode\n): RouteNode | null {\n // Auto add not found route if it doesn't exist\n for (const route of routes.children ?? []) {\n const isDeepDynamic = matchDeepDynamicRouteName(route.route);\n if (isDeepDynamic) {\n return route;\n }\n // Recurse through fragment routes\n if (matchFragmentName(route.route)) {\n const child = getUserDefinedDeepDynamicRoute(route);\n if (child) {\n return child;\n }\n }\n }\n return null;\n}\n"]}
1
+ {"version":3,"file":"getRoutes.js","sourceRoot":"","sources":["../src/getRoutes.ts"],"names":[],"mappings":"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","sourcesContent":["import { DynamicConvention, RouteNode } from \"./Route\";\nimport {\n getNameFromFilePath,\n matchDeepDynamicRouteName,\n matchDynamicName,\n matchFragmentName,\n stripFragmentSegmentsFromPath,\n} from \"./matchers\";\nimport { RequireContext } from \"./types\";\nimport { DefaultLayout } from \"./views/Layout\";\n\nexport type FileNode = Pick<RouteNode, \"contextKey\" | \"loadRoute\"> & {\n /** Like `(tab)/index` */\n normalizedName: string;\n};\n\ntype TreeNode = {\n name: string;\n children: TreeNode[];\n parents: string[];\n /** null when there is no file in a folder. */\n node: FileNode | null;\n};\n\n/** Convert a flat map of file nodes into a nested tree of files. */\nexport function getRecursiveTree(files: FileNode[]): TreeNode {\n const tree = {\n name: \"\",\n children: [],\n parents: [],\n node: null,\n };\n\n for (const file of files) {\n // ['(tab)', 'settings', '[...another]']\n const parts = file.normalizedName.split(\"/\");\n let currentNode: TreeNode = tree;\n for (let i = 0; i < parts.length; i++) {\n const part = parts[i];\n\n if (i === parts.length - 1 && part === \"_layout\") {\n if (currentNode.node) {\n const overwritten = currentNode.node.contextKey;\n throw new Error(\n `Higher priority Layout Route \"${file.contextKey}\" overriding redundant Layout Route \"${overwritten}\". Remove the Layout Route \"${overwritten}\" to fix this.`\n );\n }\n continue;\n }\n\n const existing = currentNode.children.find((item) => item.name === part);\n if (existing) {\n currentNode = existing;\n } else {\n const newNode: TreeNode = {\n name: part,\n children: [],\n parents: [...currentNode.parents, currentNode.name],\n node: null,\n };\n currentNode.children.push(newNode);\n currentNode = newNode;\n }\n }\n currentNode.node = file;\n }\n\n if (process.env.NODE_ENV !== \"production\") {\n assertDeprecatedFormat(tree);\n }\n\n return tree;\n}\n\nfunction assertDeprecatedFormat(tree: TreeNode) {\n for (const child of tree.children) {\n if (\n child.node &&\n child.children.length &&\n !child.node.normalizedName.endsWith(\"_layout\")\n ) {\n const ext = child.node.contextKey.split(\".\").pop();\n throw new Error(\n `Using deprecated Layout Route format: Move \\`./app/${child.node.normalizedName}.${ext}\\` to \\`./app/${child.node.normalizedName}/_layout.${ext}\\``\n );\n }\n assertDeprecatedFormat(child);\n }\n}\n\nfunction getTreeNodesAsRouteNodes(nodes: TreeNode[]): RouteNode[] {\n return nodes.map(treeNodeToRouteNode).flat().filter(Boolean) as RouteNode[];\n}\n\nexport function generateDynamicFromSegment(\n name: string\n): DynamicConvention | null {\n const deepDynamicName = matchDeepDynamicRouteName(name);\n const dynamicName = deepDynamicName ?? matchDynamicName(name);\n\n return dynamicName ? { name: dynamicName, deep: !!deepDynamicName } : null;\n}\n\nexport function generateDynamic(name: string): RouteNode[\"dynamic\"] {\n const description = name\n .split(\"/\")\n .map((segment) => generateDynamicFromSegment(segment))\n .filter(Boolean) as DynamicConvention[];\n return description.length === 0 ? null : description;\n}\n\nfunction collapseRouteSegments(route: string) {\n return stripFragmentSegmentsFromPath(route.replace(/\\/index$/, \"\"));\n}\n\n/**\n * Given a route node and a name representing the fragment name,\n * find the nearest child matching the name.\n *\n * Doesn't support slashes in the name.\n * Routes like `explore/(something)/index` will be matched against `explore`.\n *\n */\nfunction getDefaultInitialRoute(node: RouteNode, name: string) {\n return node.children.find(\n (node) => collapseRouteSegments(node.route) === name\n );\n}\n\nfunction applyDefaultInitialRouteName(node: RouteNode): RouteNode {\n const fragmentName = matchFragmentName(node.route);\n if (!node.children || !fragmentName) {\n return node;\n }\n\n // Guess at the initial route based on the fragment name.\n // TODO(EvanBacon): Perhaps we should attempt to warn when the fragment doesn't match any child routes.\n const initialRouteName = getDefaultInitialRoute(node, fragmentName)?.route;\n const route = {\n ...node,\n loadRoute() {\n const { unstable_settings, ...route } = node.loadRoute();\n return {\n ...route,\n unstable_settings: {\n initialRouteName:\n unstable_settings?.initialRouteName ?? initialRouteName,\n // Allow overriding the initial route name using the layout settings.\n ...unstable_settings,\n },\n };\n },\n };\n if (initialRouteName != null) {\n route.initialRouteName = initialRouteName;\n }\n return route;\n}\n\nfunction cloneFragmentRoute(\n node: RouteNode,\n { name: nextName }: { name: string }\n): RouteNode {\n const fragmentName = `(${nextName})`;\n const parts = node.contextKey.split(\"/\");\n parts[parts.length - 2] = fragmentName;\n\n return {\n ...node,\n route: fragmentName,\n contextKey: parts.join(\"/\"),\n };\n}\n\nfunction treeNodeToRouteNode({\n name,\n node,\n children,\n}: TreeNode): RouteNode[] | null {\n const dynamic = generateDynamic(name);\n\n if (node) {\n const fragmentName = matchFragmentName(name);\n const multiFragment = fragmentName?.includes(\",\");\n\n const clones = multiFragment\n ? fragmentName!.split(\",\").map((v) => ({ name: v.trim() }))\n : null;\n\n const output = {\n loadRoute: node.loadRoute,\n route: name,\n contextKey: node.contextKey,\n children: getTreeNodesAsRouteNodes(children),\n dynamic,\n };\n\n if (Array.isArray(clones)) {\n return clones.map((clone) =>\n applyDefaultInitialRouteName(cloneFragmentRoute({ ...output }, clone))\n );\n }\n\n return [\n applyDefaultInitialRouteName({\n loadRoute: node.loadRoute,\n route: name,\n contextKey: node.contextKey,\n children: getTreeNodesAsRouteNodes(children),\n dynamic,\n }),\n ];\n }\n\n // Empty folder, skip it.\n if (!children.length) {\n return null;\n }\n\n // When there's a directory, but no layout route file (with valid export), the child routes won't be grouped.\n // This pushes all children into the nearest layout route.\n return getTreeNodesAsRouteNodes(\n children.map((child) => {\n return {\n ...child,\n name: [name, child.name].filter(Boolean).join(\"/\"),\n };\n })\n );\n}\n\nfunction contextModuleToFileNodes(contextModule: RequireContext): FileNode[] {\n const nodes = contextModule.keys().map((key) => {\n // In development, check if the file exports a default component\n // this helps keep things snappy when creating files. In production we load all screens lazily.\n try {\n if (!contextModule(key)?.default) {\n return null;\n }\n } catch (error) {\n // Probably this won't stop metro from freaking out but it's worth a try.\n console.warn('Error loading route \"' + key + '\"', error);\n return null;\n }\n\n const node: FileNode = {\n loadRoute: () => contextModule(key),\n normalizedName: getNameFromFilePath(key),\n contextKey: key,\n };\n\n return node;\n });\n\n return nodes.filter(Boolean) as FileNode[];\n}\n\nfunction hasCustomRootLayoutNode(routes: RouteNode[]) {\n if (routes.length !== 1) {\n return false;\n }\n // This could either be the root _layout or an app with a single file.\n const route = routes[0];\n\n if (\n route.route === \"\" &&\n route.contextKey.match(/^\\.\\/_layout\\.([jt]sx?)$/)\n ) {\n return true;\n }\n return false;\n}\n\nfunction treeNodesToRootRoute(treeNode: TreeNode): RouteNode | null {\n const routes = treeNodeToRouteNode(treeNode);\n\n if (!routes?.length) {\n return null;\n }\n\n if (hasCustomRootLayoutNode(routes)) {\n return routes[0];\n }\n\n return {\n loadRoute: () => ({ default: DefaultLayout }),\n // Generate a fake file name for the directory\n contextKey: \"./_layout.tsx\",\n route: \"\",\n generated: true,\n dynamic: null,\n children: routes,\n };\n}\n\n/** Given a Metro context module, return an array of nested routes. */\nexport function getRoutes(contextModule: RequireContext): RouteNode | null {\n const files = contextModuleToFileNodes(contextModule);\n const treeNodes = getRecursiveTree(files);\n const route = treeNodesToRootRoute(treeNodes);\n\n if (!route) {\n return null;\n }\n\n appendSitemapRoute(route);\n\n // Auto add not found route if it doesn't exist\n appendUnmatchedRoute(route);\n\n return route;\n}\n\nfunction appendSitemapRoute(routes: RouteNode) {\n if (\n !routes.children.length ||\n // Allow overriding the sitemap route\n routes.children.some((route) => route.route === \"_sitemap\")\n ) {\n return routes;\n }\n const { Sitemap, getNavOptions } = require(\"./views/Sitemap\");\n routes.children.push({\n loadRoute() {\n return { default: Sitemap, getNavOptions };\n },\n route: \"_sitemap\",\n contextKey: \"./_sitemap.tsx\",\n generated: true,\n internal: true,\n dynamic: null,\n children: [],\n });\n return routes;\n}\n\nfunction appendUnmatchedRoute(routes: RouteNode) {\n // Auto add not found route if it doesn't exist\n const userDefinedDynamicRoute = getUserDefinedDeepDynamicRoute(routes);\n if (!userDefinedDynamicRoute) {\n routes.children.push({\n loadRoute() {\n return { default: require(\"./views/Unmatched\").Unmatched };\n },\n route: \"[...404]\",\n contextKey: \"./[...404].tsx\",\n dynamic: [{ name: \"404\", deep: true }],\n children: [],\n generated: true,\n internal: true,\n });\n }\n return routes;\n}\n\n/**\n * Exposed for testing.\n * @returns a top-level deep dynamic route if it exists, otherwise null.\n */\nexport function getUserDefinedDeepDynamicRoute(\n routes: RouteNode\n): RouteNode | null {\n // Auto add not found route if it doesn't exist\n for (const route of routes.children ?? []) {\n const isDeepDynamic = matchDeepDynamicRouteName(route.route);\n if (isDeepDynamic) {\n return route;\n }\n // Recurse through fragment routes\n if (matchFragmentName(route.route)) {\n const child = getUserDefinedDeepDynamicRoute(route);\n if (child) {\n return child;\n }\n }\n }\n return null;\n}\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"useHref.d.ts","sourceRoot":"","sources":["../../src/link/useHref.ts"],"names":[],"mappings":"AAIA,OAAO,gBAA2B,MAAM,0BAA0B,CAAC;AACnE,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAGpC,aAAK,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC,GAAG;IACrD,qFAAqF;IACrF,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAgDF,wBAAgB,OAAO,IAAI,SAAS,CAgCnC;AAED,wBAAgB,mBAAmB,YAIvB,WAAW,uBAAuB,CAAC,CAAC,CAAC,CAAC,UAAU,OAAO,YAclE"}
1
+ {"version":3,"file":"useHref.d.ts","sourceRoot":"","sources":["../../src/link/useHref.ts"],"names":[],"mappings":"AAIA,OAAO,gBAA2B,MAAM,0BAA0B,CAAC;AAEnE,OAAO,EAAE,UAAU,EAAE,MAAM,QAAQ,CAAC;AAGpC,aAAK,SAAS,GAAG,IAAI,CAAC,QAAQ,CAAC,UAAU,CAAC,EAAE,OAAO,CAAC,GAAG;IACrD,qFAAqF;IACrF,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAqCF,wBAAgB,OAAO,IAAI,SAAS,CA+CnC;AAED,wBAAgB,mBAAmB,YAIvB,WAAW,uBAAuB,CAAC,CAAC,CAAC,CAAC,UAAU,OAAO,YAUlE"}
@@ -1,20 +1,12 @@
1
1
  import * as queryString from "query-string";
2
2
  import React from "react";
3
3
  import { RootContainer } from "../ContextNavigationContainer";
4
+ import { useInitialRootStateContext } from "../rootStateContext";
4
5
  import { useLinkingContext } from "./useLinkingContext";
5
6
  function getRouteInfoFromState(getPathFromState, state) {
6
- if (!state) {
7
- return {
8
- href: "",
9
- pathname: "",
10
- params: {},
11
- };
12
- }
13
- const pathname = getNormalizedStatePath(getPathFromState(state, true));
14
- const href = getPathFromState(state, false);
15
7
  return {
16
- href,
17
- ...pathname,
8
+ href: getPathFromState(state, false),
9
+ ...getNormalizedStatePath(getPathFromState(state, true)),
18
10
  };
19
11
  }
20
12
  function compareShallowRecords(a, b) {
@@ -36,35 +28,41 @@ function compareRouteInfo(a, b) {
36
28
  compareShallowRecords(a.params, b.params));
37
29
  }
38
30
  export function useHref() {
31
+ const initialRootState = useInitialRootStateContext();
39
32
  const getPathFromState = useGetPathFromState();
40
- const navigation = RootContainer.getRef();
41
- const [routeInfo, setRouteInfo] = React.useState(getRouteInfoFromState(getPathFromState, navigation?.getRootState()));
33
+ const [routeInfo, setRouteInfo] = React.useState(getRouteInfoFromState(getPathFromState,
34
+ // If the root state (from upstream) is not ready, use the hacky initial state.
35
+ // Initial state can be generate because it assumes the linking configuration never changes.
36
+ RootContainer.getRef().getRootState() ?? initialRootState));
37
+ const routeInfoRef = React.useRef(routeInfo);
38
+ React.useEffect(() => {
39
+ routeInfoRef.current = routeInfo;
40
+ }, [routeInfo]);
42
41
  const maybeUpdateRouteInfo = React.useCallback((state) => {
43
42
  // Prevent unnecessary updates
44
43
  const newRouteInfo = getRouteInfoFromState(getPathFromState, state);
45
- if (!compareRouteInfo(routeInfo, newRouteInfo)) {
44
+ if (!compareRouteInfo(routeInfoRef.current, newRouteInfo)) {
46
45
  setRouteInfo(newRouteInfo);
47
46
  }
48
- }, [getPathFromState, routeInfo]);
47
+ }, [
48
+ // TODO: This probably never changes
49
+ getPathFromState,
50
+ ]);
49
51
  React.useEffect(() => {
50
- if (navigation) {
51
- maybeUpdateRouteInfo(navigation.getRootState());
52
- const unsubscribe = navigation.addListener("state", ({ data }) => {
53
- const navigationState = data.state;
54
- maybeUpdateRouteInfo(navigationState);
55
- });
56
- return unsubscribe;
57
- }
58
- return undefined;
59
- }, [maybeUpdateRouteInfo, navigation]);
52
+ const rootNavigation = RootContainer.getRef();
53
+ return rootNavigation.addListener("state", ({ data }) => {
54
+ // Attempt to use the complete state from the root, otherwise this will default to
55
+ // sending events from the nearest layout.
56
+ const navigationState = rootNavigation.getRootState() ?? data.state;
57
+ // NOTE(EvanBacon): It's probably worth asserting if the root state is missing here.
58
+ maybeUpdateRouteInfo(navigationState);
59
+ });
60
+ }, [maybeUpdateRouteInfo]);
60
61
  return routeInfo;
61
62
  }
62
63
  export function useGetPathFromState() {
63
64
  const linking = useLinkingContext();
64
65
  return React.useCallback((state, asPath) => {
65
- if (!state) {
66
- return "";
67
- }
68
66
  return linking.getPathFromState(state, {
69
67
  ...linking.config,
70
68
  // @ts-expect-error
@@ -1 +1 @@
1
- {"version":3,"file":"useHref.js","sourceRoot":"","sources":["../../src/link/useHref.ts"],"names":[],"mappings":"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","sourcesContent":["import * as queryString from \"query-string\";\nimport React from \"react\";\n\nimport { RootContainer } from \"../ContextNavigationContainer\";\nimport getPathFromState, { State } from \"../fork/getPathFromState\";\nimport { HrefObject } from \"./href\";\nimport { useLinkingContext } from \"./useLinkingContext\";\n\ntype RouteInfo = Omit<Required<HrefObject>, \"query\"> & {\n /** Normalized path representing the selected route `/[id]?id=normal` -> `/normal` */\n href: string;\n};\n\nfunction getRouteInfoFromState(\n getPathFromState: (state: State, asPath: boolean) => string,\n state?: State | null\n): RouteInfo {\n if (!state) {\n return {\n href: \"\",\n pathname: \"\",\n params: {},\n };\n }\n\n const pathname = getNormalizedStatePath(getPathFromState(state, true));\n const href = getPathFromState(state, false);\n\n return {\n href,\n ...pathname,\n };\n}\n\nfunction compareShallowRecords(a: Record<string, any>, b: Record<string, any>) {\n const aKeys = Object.keys(a);\n const bKeys = Object.keys(b);\n\n if (aKeys.length !== bKeys.length) {\n return false;\n }\n\n for (const key of aKeys) {\n if (a[key] !== b[key]) {\n return false;\n }\n }\n\n return true;\n}\n\nfunction compareRouteInfo(a: RouteInfo, b: RouteInfo) {\n return (\n a.href === b.href &&\n a.pathname === b.pathname &&\n compareShallowRecords(a.params, b.params)\n );\n}\n\nexport function useHref(): RouteInfo {\n const getPathFromState = useGetPathFromState();\n\n const navigation = RootContainer.getRef();\n const [routeInfo, setRouteInfo] = React.useState<RouteInfo>(\n getRouteInfoFromState(getPathFromState, navigation?.getRootState())\n );\n\n const maybeUpdateRouteInfo = React.useCallback(\n (state: State | null) => {\n // Prevent unnecessary updates\n const newRouteInfo = getRouteInfoFromState(getPathFromState, state);\n if (!compareRouteInfo(routeInfo, newRouteInfo)) {\n setRouteInfo(newRouteInfo);\n }\n },\n [getPathFromState, routeInfo]\n );\n\n React.useEffect(() => {\n if (navigation) {\n maybeUpdateRouteInfo(navigation.getRootState());\n const unsubscribe = navigation.addListener(\"state\", ({ data }) => {\n const navigationState = data.state as unknown as State;\n maybeUpdateRouteInfo(navigationState);\n });\n return unsubscribe;\n }\n return undefined;\n }, [maybeUpdateRouteInfo, navigation]);\n\n return routeInfo;\n}\n\nexport function useGetPathFromState() {\n const linking = useLinkingContext();\n\n return React.useCallback(\n (state: Parameters<typeof getPathFromState>[0], asPath: boolean) => {\n if (!state) {\n return \"\";\n }\n\n return linking.getPathFromState(state, {\n ...linking.config,\n // @ts-expect-error\n preserveDynamicRoutes: asPath,\n preserveFragments: asPath,\n });\n },\n [linking]\n );\n}\n\n// TODO: Split up getPathFromState to return all this info at once.\nfunction getNormalizedStatePath(statePath: string): {\n pathname: string;\n params: queryString.ParsedQuery<string>;\n} {\n const [pathname, querystring] = statePath.split(\"?\");\n\n return {\n pathname,\n // TODO: This is not efficient, we should generate based on the state instead\n // of converting to string then back to object\n params: querystring ? queryString.parse(querystring) : {},\n };\n}\n"]}
1
+ {"version":3,"file":"useHref.js","sourceRoot":"","sources":["../../src/link/useHref.ts"],"names":[],"mappings":"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","sourcesContent":["import * as queryString from \"query-string\";\nimport React from \"react\";\n\nimport { RootContainer } from \"../ContextNavigationContainer\";\nimport getPathFromState, { State } from \"../fork/getPathFromState\";\nimport { useInitialRootStateContext } from \"../rootStateContext\";\nimport { HrefObject } from \"./href\";\nimport { useLinkingContext } from \"./useLinkingContext\";\n\ntype RouteInfo = Omit<Required<HrefObject>, \"query\"> & {\n /** Normalized path representing the selected route `/[id]?id=normal` -> `/normal` */\n href: string;\n};\n\nfunction getRouteInfoFromState(\n getPathFromState: (state: State, asPath: boolean) => string,\n state: State\n): RouteInfo {\n return {\n href: getPathFromState(state, false),\n ...getNormalizedStatePath(getPathFromState(state, true)),\n };\n}\n\nfunction compareShallowRecords(a: Record<string, any>, b: Record<string, any>) {\n const aKeys = Object.keys(a);\n const bKeys = Object.keys(b);\n\n if (aKeys.length !== bKeys.length) {\n return false;\n }\n\n for (const key of aKeys) {\n if (a[key] !== b[key]) {\n return false;\n }\n }\n\n return true;\n}\n\nfunction compareRouteInfo(a: RouteInfo, b: RouteInfo) {\n return (\n a.href === b.href &&\n a.pathname === b.pathname &&\n compareShallowRecords(a.params, b.params)\n );\n}\n\nexport function useHref(): RouteInfo {\n const initialRootState = useInitialRootStateContext();\n const getPathFromState = useGetPathFromState();\n\n const [routeInfo, setRouteInfo] = React.useState<RouteInfo>(\n getRouteInfoFromState(\n getPathFromState,\n // If the root state (from upstream) is not ready, use the hacky initial state.\n // Initial state can be generate because it assumes the linking configuration never changes.\n RootContainer.getRef().getRootState() ?? initialRootState\n )\n );\n\n const routeInfoRef = React.useRef(routeInfo);\n\n React.useEffect(() => {\n routeInfoRef.current = routeInfo;\n }, [routeInfo]);\n\n const maybeUpdateRouteInfo = React.useCallback(\n (state: State) => {\n // Prevent unnecessary updates\n const newRouteInfo = getRouteInfoFromState(getPathFromState, state);\n if (!compareRouteInfo(routeInfoRef.current, newRouteInfo)) {\n setRouteInfo(newRouteInfo);\n }\n },\n [\n // TODO: This probably never changes\n getPathFromState,\n ]\n );\n\n React.useEffect(() => {\n const rootNavigation = RootContainer.getRef();\n\n return rootNavigation.addListener(\"state\", ({ data }) => {\n // Attempt to use the complete state from the root, otherwise this will default to\n // sending events from the nearest layout.\n const navigationState =\n rootNavigation.getRootState() ?? (data.state as unknown as State);\n // NOTE(EvanBacon): It's probably worth asserting if the root state is missing here.\n maybeUpdateRouteInfo(navigationState);\n });\n }, [maybeUpdateRouteInfo]);\n\n return routeInfo;\n}\n\nexport function useGetPathFromState() {\n const linking = useLinkingContext();\n\n return React.useCallback(\n (state: Parameters<typeof getPathFromState>[0], asPath: boolean) => {\n return linking.getPathFromState(state, {\n ...linking.config,\n // @ts-expect-error\n preserveDynamicRoutes: asPath,\n preserveFragments: asPath,\n });\n },\n [linking]\n );\n}\n\n// TODO: Split up getPathFromState to return all this info at once.\nfunction getNormalizedStatePath(statePath: string): {\n pathname: string;\n params: queryString.ParsedQuery<string>;\n} {\n const [pathname, querystring] = statePath.split(\"?\");\n\n return {\n pathname,\n // TODO: This is not efficient, we should generate based on the state instead\n // of converting to string then back to object\n params: querystring ? queryString.parse(querystring) : {},\n };\n}\n"]}
@@ -0,0 +1,8 @@
1
+ import React from "react";
2
+ import { State } from "./fork/getPathFromState";
3
+ export declare const InitialRootStateContext: React.Context<State | null>;
4
+ export declare function useInitialRootStateContext(): State;
5
+ export declare function InitialRootStateProvider({ children, }: {
6
+ children: React.ReactNode;
7
+ }): JSX.Element | null;
8
+ //# sourceMappingURL=rootStateContext.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rootStateContext.d.ts","sourceRoot":"","sources":["../src/rootStateContext.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAyD,MAAM,OAAO,CAAC;AAG9E,OAAO,EAAE,KAAK,EAAE,MAAM,yBAAyB,CAAC;AAiChD,eAAO,MAAM,uBAAuB,6BAAoC,CAAC;AAMzE,wBAAgB,0BAA0B,UAQzC;AAED,wBAAgB,wBAAwB,CAAC,EACvC,QAAQ,GACT,EAAE;IACD,QAAQ,EAAE,KAAK,CAAC,SAAS,CAAC;CAC3B,sBAcA"}
@@ -0,0 +1,47 @@
1
+ import React, { createContext, useContext, useEffect, useState } from "react";
2
+ import URL from "url-parse";
3
+ import { useLinkingContext } from "./link/useLinkingContext";
4
+ function useResolvedPromise(promise) {
5
+ const [resolved, setResolved] = useState();
6
+ useEffect(() => {
7
+ if (promise) {
8
+ promise.then(setResolved);
9
+ }
10
+ }, [promise]);
11
+ return resolved;
12
+ }
13
+ function useHackInitialRootState() {
14
+ const linking = useLinkingContext();
15
+ const url = useResolvedPromise(linking.getInitialURL());
16
+ const [state, setState] = useState(null);
17
+ useEffect(() => {
18
+ if (url) {
19
+ const parsed = URL(url);
20
+ // TODO: Add hashes to the path
21
+ const urlWithoutOrigin = parsed.pathname + parsed.query;
22
+ setState(linking.getStateFromPath(urlWithoutOrigin, linking.config));
23
+ }
24
+ }, [url, linking]);
25
+ return state;
26
+ }
27
+ export const InitialRootStateContext = createContext(null);
28
+ if (process.env.NODE_ENV !== "production") {
29
+ InitialRootStateContext.displayName = "InitialRootStateContext";
30
+ }
31
+ export function useInitialRootStateContext() {
32
+ const state = useContext(InitialRootStateContext);
33
+ if (!state) {
34
+ throw new Error("useInitialRootStateContext is being used outside of InitialRootStateContext.Provider");
35
+ }
36
+ return state;
37
+ }
38
+ export function InitialRootStateProvider({ children, }) {
39
+ const state = useHackInitialRootState();
40
+ // Prevent all rendering until we have the initial root state.
41
+ // Probably React Navigation should be doing this for us.
42
+ if (!state) {
43
+ return null;
44
+ }
45
+ return (React.createElement(InitialRootStateContext.Provider, { value: state }, children));
46
+ }
47
+ //# sourceMappingURL=rootStateContext.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"rootStateContext.js","sourceRoot":"","sources":["../src/rootStateContext.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,aAAa,EAAE,UAAU,EAAE,SAAS,EAAE,QAAQ,EAAE,MAAM,OAAO,CAAC;AAC9E,OAAO,GAAG,MAAM,WAAW,CAAC;AAG5B,OAAO,EAAE,iBAAiB,EAAE,MAAM,0BAA0B,CAAC;AAE7D,SAAS,kBAAkB,CAAI,OAA+B;IAC5D,MAAM,CAAC,QAAQ,EAAE,WAAW,CAAC,GAAG,QAAQ,EAAiB,CAAC;IAE1D,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,OAAO,EAAE;YACX,OAAO,CAAC,IAAI,CAAC,WAAW,CAAC,CAAC;SAC3B;IACH,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IAEd,OAAO,QAAQ,CAAC;AAClB,CAAC;AAED,SAAS,uBAAuB;IAC9B,MAAM,OAAO,GAAG,iBAAiB,EAAE,CAAC;IACpC,MAAM,GAAG,GAAG,kBAAkB,CAAC,OAAO,CAAC,aAAa,EAAqB,CAAC,CAAC;IAC3E,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,QAAQ,CAAe,IAAI,CAAC,CAAC;IAEvD,SAAS,CAAC,GAAG,EAAE;QACb,IAAI,GAAG,EAAE;YACP,MAAM,MAAM,GAAG,GAAG,CAAC,GAAG,CAAC,CAAC;YACxB,+BAA+B;YAC/B,MAAM,gBAAgB,GAAG,MAAM,CAAC,QAAQ,GAAG,MAAM,CAAC,KAAK,CAAC;YAExD,QAAQ,CAAC,OAAO,CAAC,gBAAgB,CAAC,gBAAgB,EAAE,OAAO,CAAC,MAAM,CAAE,CAAC,CAAC;SACvE;IACH,CAAC,EAAE,CAAC,GAAG,EAAE,OAAO,CAAC,CAAC,CAAC;IAEnB,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,CAAC,MAAM,uBAAuB,GAAG,aAAa,CAAe,IAAI,CAAC,CAAC;AAEzE,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,EAAE;IACzC,uBAAuB,CAAC,WAAW,GAAG,yBAAyB,CAAC;CACjE;AAED,MAAM,UAAU,0BAA0B;IACxC,MAAM,KAAK,GAAG,UAAU,CAAC,uBAAuB,CAAC,CAAC;IAClD,IAAI,CAAC,KAAK,EAAE;QACV,MAAM,IAAI,KAAK,CACb,sFAAsF,CACvF,CAAC;KACH;IACD,OAAO,KAAK,CAAC;AACf,CAAC;AAED,MAAM,UAAU,wBAAwB,CAAC,EACvC,QAAQ,GAGT;IACC,MAAM,KAAK,GAAG,uBAAuB,EAAE,CAAC;IAExC,8DAA8D;IAC9D,yDAAyD;IACzD,IAAI,CAAC,KAAK,EAAE;QACV,OAAO,IAAI,CAAC;KACb;IAED,OAAO,CACL,oBAAC,uBAAuB,CAAC,QAAQ,IAAC,KAAK,EAAE,KAAK,IAC3C,QAAQ,CACwB,CACpC,CAAC;AACJ,CAAC","sourcesContent":["import React, { createContext, useContext, useEffect, useState } from \"react\";\nimport URL from \"url-parse\";\n\nimport { State } from \"./fork/getPathFromState\";\nimport { useLinkingContext } from \"./link/useLinkingContext\";\n\nfunction useResolvedPromise<T>(promise: Promise<T> | undefined) {\n const [resolved, setResolved] = useState<T | undefined>();\n\n useEffect(() => {\n if (promise) {\n promise.then(setResolved);\n }\n }, [promise]);\n\n return resolved;\n}\n\nfunction useHackInitialRootState() {\n const linking = useLinkingContext();\n const url = useResolvedPromise(linking.getInitialURL() as Promise<string>);\n const [state, setState] = useState<State | null>(null);\n\n useEffect(() => {\n if (url) {\n const parsed = URL(url);\n // TODO: Add hashes to the path\n const urlWithoutOrigin = parsed.pathname + parsed.query;\n\n setState(linking.getStateFromPath(urlWithoutOrigin, linking.config)!);\n }\n }, [url, linking]);\n\n return state;\n}\n\nexport const InitialRootStateContext = createContext<State | null>(null);\n\nif (process.env.NODE_ENV !== \"production\") {\n InitialRootStateContext.displayName = \"InitialRootStateContext\";\n}\n\nexport function useInitialRootStateContext() {\n const state = useContext(InitialRootStateContext);\n if (!state) {\n throw new Error(\n \"useInitialRootStateContext is being used outside of InitialRootStateContext.Provider\"\n );\n }\n return state;\n}\n\nexport function InitialRootStateProvider({\n children,\n}: {\n children: React.ReactNode;\n}) {\n const state = useHackInitialRootState();\n\n // Prevent all rendering until we have the initial root state.\n // Probably React Navigation should be doing this for us.\n if (!state) {\n return null;\n }\n\n return (\n <InitialRootStateContext.Provider value={state}>\n {children}\n </InitialRootStateContext.Provider>\n );\n}\n"]}
@@ -25,5 +25,5 @@ export declare function getQualifiedRouteComponent(value: RouteNode): React.Comp
25
25
  /** @returns a function which provides a screen id that matches the dynamic route name in params. */
26
26
  export declare function createGetIdForRoute(route: Pick<RouteNode, "dynamic" | "route">): (({ params }: {
27
27
  params: any;
28
- }) => any) | undefined;
28
+ }) => string | undefined) | undefined;
29
29
  //# sourceMappingURL=useScreens.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"useScreens.d.ts","sourceRoot":"","sources":["../src/useScreens.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAS,SAAS,EAAuC,MAAM,SAAS,CAAC;AAIhF,oBAAY,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,GAAG,MAAM,CAAC;IAC5B,aAAa,CAAC,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;KAAE,CAAC;IACvC,OAAO,CAAC,EAAE,QAAQ,CAAC;CACpB,CAAC;AA8DF;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,WAAW,EAAE,GAAG,KAAK,CAAC,SAAS,EAAE,CAUxE;AAMD,mFAAmF;AACnF,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,SAAS;WAQtC,GAAG;gBAAc,GAAG;kCAwBxC;AAED,oGAAoG;AACpG,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,IAAI,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC;;uBAuB5C"}
1
+ {"version":3,"file":"useScreens.d.ts","sourceRoot":"","sources":["../src/useScreens.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAGL,SAAS,EAGV,MAAM,SAAS,CAAC;AAIjB,oBAAY,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,GAAG,MAAM,CAAC;IAC5B,aAAa,CAAC,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;KAAE,CAAC;IACvC,OAAO,CAAC,EAAE,QAAQ,CAAC;CACpB,CAAC;AA8DF;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,WAAW,EAAE,GAAG,KAAK,CAAC,SAAS,EAAE,CAUxE;AAMD,mFAAmF;AACnF,wBAAgB,0BAA0B,CAAC,KAAK,EAAE,SAAS;WAQtC,GAAG;gBAAc,GAAG;kCAwBxC;AAED,oGAAoG;AACpG,wBAAgB,mBAAmB,CACjC,KAAK,EAAE,IAAI,CAAC,SAAS,EAAE,SAAS,GAAG,OAAO,CAAC;;sCA0B5C"}
@@ -1,5 +1,5 @@
1
1
  import React from "react";
2
- import { Route, sortRoutesWithInitial, useRouteNode } from "./Route";
2
+ import { Route, sortRoutesWithInitial, useRouteNode, } from "./Route";
3
3
  import { Screen } from "./primitives";
4
4
  import { Try } from "./views/Try";
5
5
  function getSortedChildren(children, order, initialRouteName) {
@@ -77,24 +77,30 @@ export function getQualifiedRouteComponent(value) {
77
77
  }
78
78
  /** @returns a function which provides a screen id that matches the dynamic route name in params. */
79
79
  export function createGetIdForRoute(route) {
80
- if (!route.dynamic) {
80
+ if (!route.dynamic?.length) {
81
81
  return undefined;
82
82
  }
83
- const dynamicName = route.dynamic.name;
84
- const routeName = route.route;
85
83
  return ({ params }) => {
86
- // Params can be undefined when there are no params in the route.
87
- const preferredId = params?.[dynamicName];
88
- // If the route has a dynamic segment, use the matching parameter
89
- // as the screen id. This enables pushing a screen like `/[user]` multiple times
90
- // when the user is different.
91
- if (preferredId) {
92
- // Deep dynamic routes will return as an array, so we'll join them to create a
93
- // fully qualified string.
94
- return ((Array.isArray(preferredId) ? preferredId.join("/") : preferredId) ||
95
- routeName);
96
- }
97
- return routeName;
84
+ const getPreferredId = (segment) => {
85
+ // Params can be undefined when there are no params in the route.
86
+ const preferredId = params?.[segment.name];
87
+ // If the route has a dynamic segment, use the matching parameter
88
+ // as the screen id. This enables pushing a screen like `/[user]` multiple times
89
+ // when the user is different.
90
+ if (preferredId) {
91
+ if (!Array.isArray(preferredId)) {
92
+ return preferredId;
93
+ }
94
+ else if (preferredId.length) {
95
+ // Deep dynamic routes will return as an array, so we'll join them to create a
96
+ // fully qualified string.
97
+ return preferredId.join("/");
98
+ }
99
+ // Empty arrays...
100
+ }
101
+ return segment.deep ? `[...${segment.name}]` : `[${segment.name}]`;
102
+ };
103
+ return route.dynamic?.map((segment) => getPreferredId(segment)).join("/");
98
104
  };
99
105
  }
100
106
  function routeToScreen(route, { options, ...props } = {}) {
@@ -1 +1 @@
1
- {"version":3,"file":"useScreens.js","sourceRoot":"","sources":["../src/useScreens.tsx"],"names":[],"mappings":"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","sourcesContent":["import React from \"react\";\n\nimport { Route, RouteNode, sortRoutesWithInitial, useRouteNode } from \"./Route\";\nimport { Screen } from \"./primitives\";\nimport { Try } from \"./views/Try\";\n\nexport type ScreenProps<\n TOptions extends Record<string, any> = Record<string, any>\n> = {\n /** Name is required when used inside a Layout component. */\n name?: string;\n /**\n * Redirect to the nearest or provided 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 | string;\n initialParams?: { [key: string]: any };\n options?: TOptions;\n};\n\nfunction getSortedChildren(\n children: RouteNode[],\n order?: ScreenProps[],\n initialRouteName?: string\n): { route: RouteNode; props: any }[] {\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(({ name, redirect, initialParams, options }) => {\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(\n `Redirecting to a specific route is not supported yet.`\n );\n }\n return null;\n }\n\n return { route: match, props: { initialParams, options } };\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\n .sort(sortRoutesWithInitial(initialRouteName))\n .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(order: ScreenProps[]): 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 () => sorted.map((value) => routeToScreen(value.route, value.props)),\n [sorted]\n );\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 const { default: Component, ErrorBoundary } = value.loadRoute();\n\n const QualifiedRoute = React.forwardRef(\n (props: { route: any; navigation: any }, ref: any) => {\n const children = React.createElement(Component, {\n ...props,\n ref,\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\n const errorBoundary = ErrorBoundary ? (\n <Try catch={ErrorBoundary}>{children}</Try>\n ) : (\n children\n );\n\n return <Route node={value}>{errorBoundary}</Route>;\n }\n );\n\n QualifiedRoute.displayName = `Route(${\n Component.displayName || Component.name || value.route\n })`;\n qualifiedStore.set(value, QualifiedRoute);\n return QualifiedRoute;\n}\n\n/** @returns a function which provides a screen id that matches the dynamic route name in params. */\nexport function createGetIdForRoute(\n route: Pick<RouteNode, \"dynamic\" | \"route\">\n) {\n if (!route.dynamic) {\n return undefined;\n }\n const dynamicName = route.dynamic.name;\n const routeName = route.route;\n return ({ params }) => {\n // Params can be undefined when there are no params in the route.\n const preferredId = params?.[dynamicName];\n // If the route has a dynamic segment, use the matching parameter\n // as the screen id. This enables pushing a screen like `/[user]` multiple times\n // when the user is different.\n if (preferredId) {\n // Deep dynamic routes will return as an array, so we'll join them to create a\n // fully qualified string.\n return (\n (Array.isArray(preferredId) ? preferredId.join(\"/\") : preferredId) ||\n routeName\n );\n }\n return routeName;\n };\n}\n\nfunction routeToScreen(\n route: RouteNode,\n { options, ...props }: Partial<ScreenProps> = {}\n) {\n return (\n <Screen\n // Users can override the screen getId function.\n getId={createGetIdForRoute(route)}\n {...props}\n name={route.route}\n key={route.route}\n options={(args) => {\n // Only eager load generated components\n const staticOptions = route.generated\n ? route.loadRoute()?.getNavOptions\n : null;\n const staticResult =\n typeof staticOptions === \"function\"\n ? staticOptions(args)\n : staticOptions;\n const dynamicResult =\n typeof options === \"function\" ? options?.(args) : options;\n return {\n ...staticResult,\n ...dynamicResult,\n };\n }}\n getComponent={() => getQualifiedRouteComponent(route)}\n />\n );\n}\n"]}
1
+ {"version":3,"file":"useScreens.js","sourceRoot":"","sources":["../src/useScreens.tsx"],"names":[],"mappings":"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","sourcesContent":["import React from \"react\";\n\nimport {\n DynamicConvention,\n Route,\n RouteNode,\n sortRoutesWithInitial,\n useRouteNode,\n} from \"./Route\";\nimport { Screen } from \"./primitives\";\nimport { Try } from \"./views/Try\";\n\nexport type ScreenProps<\n TOptions extends Record<string, any> = Record<string, any>\n> = {\n /** Name is required when used inside a Layout component. */\n name?: string;\n /**\n * Redirect to the nearest or provided 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 | string;\n initialParams?: { [key: string]: any };\n options?: TOptions;\n};\n\nfunction getSortedChildren(\n children: RouteNode[],\n order?: ScreenProps[],\n initialRouteName?: string\n): { route: RouteNode; props: any }[] {\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(({ name, redirect, initialParams, options }) => {\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(\n `Redirecting to a specific route is not supported yet.`\n );\n }\n return null;\n }\n\n return { route: match, props: { initialParams, options } };\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\n .sort(sortRoutesWithInitial(initialRouteName))\n .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(order: ScreenProps[]): 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 () => sorted.map((value) => routeToScreen(value.route, value.props)),\n [sorted]\n );\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 const { default: Component, ErrorBoundary } = value.loadRoute();\n\n const QualifiedRoute = React.forwardRef(\n (props: { route: any; navigation: any }, ref: any) => {\n const children = React.createElement(Component, {\n ...props,\n ref,\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\n const errorBoundary = ErrorBoundary ? (\n <Try catch={ErrorBoundary}>{children}</Try>\n ) : (\n children\n );\n\n return <Route node={value}>{errorBoundary}</Route>;\n }\n );\n\n QualifiedRoute.displayName = `Route(${\n Component.displayName || Component.name || value.route\n })`;\n qualifiedStore.set(value, QualifiedRoute);\n return QualifiedRoute;\n}\n\n/** @returns a function which provides a screen id that matches the dynamic route name in params. */\nexport function createGetIdForRoute(\n route: Pick<RouteNode, \"dynamic\" | \"route\">\n) {\n if (!route.dynamic?.length) {\n return undefined;\n }\n return ({ params }) => {\n const getPreferredId = (segment: DynamicConvention) => {\n // Params can be undefined when there are no params in the route.\n const preferredId = params?.[segment.name];\n // If the route has a dynamic segment, use the matching parameter\n // as the screen id. This enables pushing a screen like `/[user]` multiple times\n // when the user is different.\n if (preferredId) {\n if (!Array.isArray(preferredId)) {\n return preferredId;\n } else if (preferredId.length) {\n // Deep dynamic routes will return as an array, so we'll join them to create a\n // fully qualified string.\n return preferredId.join(\"/\");\n }\n // Empty arrays...\n }\n return segment.deep ? `[...${segment.name}]` : `[${segment.name}]`;\n };\n return route.dynamic?.map((segment) => getPreferredId(segment)).join(\"/\");\n };\n}\n\nfunction routeToScreen(\n route: RouteNode,\n { options, ...props }: Partial<ScreenProps> = {}\n) {\n return (\n <Screen\n // Users can override the screen getId function.\n getId={createGetIdForRoute(route)}\n {...props}\n name={route.route}\n key={route.route}\n options={(args) => {\n // Only eager load generated components\n const staticOptions = route.generated\n ? route.loadRoute()?.getNavOptions\n : null;\n const staticResult =\n typeof staticOptions === \"function\"\n ? staticOptions(args)\n : staticOptions;\n const dynamicResult =\n typeof options === \"function\" ? options?.(args) : options;\n return {\n ...staticResult,\n ...dynamicResult,\n };\n }}\n getComponent={() => getQualifiedRouteComponent(route)}\n />\n );\n}\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-router",
3
- "version": "0.0.37",
3
+ "version": "0.0.39",
4
4
  "main": "build/index.js",
5
5
  "files": [
6
6
  "entry.js",