expo-router 0.0.4 → 0.0.5

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.
@@ -28,6 +28,6 @@ export declare const ContextNavigationContainer: React.ForwardRefExoticComponent
28
28
  } & {
29
29
  ref?: React.Ref<import("@react-navigation/native").NavigationContainerRef<{}>> | undefined;
30
30
  }, keyof import("@react-navigation/native").NavigationContainerProps | "theme" | "linking" | "fallback" | "documentTitle" | "onReady"> & React.RefAttributes<import("@react-navigation/native").NavigationContainerRef<{}>>>;
31
- export declare function RootContainer(props: Omit<NavigationContainerProps, 'children' | 'linking'>): null;
31
+ export declare function RootContainer({ documentTitle, fallback, initialState, onStateChange, onUnhandledAction, theme }: Omit<NavigationContainerProps, 'independent' | 'onReady' | 'ref' | 'children' | 'linking'>): null;
32
32
  export {};
33
33
  //# sourceMappingURL=ContextNavigationContainer.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"ContextNavigationContainer.d.ts","sourceRoot":"","sources":["../src/ContextNavigationContainer.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/E,OAAO,KAA+B,MAAM,OAAO,CAAC;AAIpD,aAAK,wBAAwB,GAAG,KAAK,CAAC,cAAc,CAChD,OAAO,mBAAmB,CAC7B,CAAC;AASF,wBAAgB,6BAA6B;;;;;;;;;;;;;;;;aAQ5C;AAUD,8GAA8G;AAC9G,eAAO,MAAM,0BAA0B;;;;;;;;4NA6BtC,CAAC;AAgBF,wBAAgB,aAAa,CAAC,KAAK,EAAE,IAAI,CAAC,wBAAwB,EAAE,UAAU,GAAG,SAAS,CAAC,QAQ1F"}
1
+ {"version":3,"file":"ContextNavigationContainer.d.ts","sourceRoot":"","sources":["../src/ContextNavigationContainer.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/E,OAAO,KAA+B,MAAM,OAAO,CAAC;AAIpD,aAAK,wBAAwB,GAAG,KAAK,CAAC,cAAc,CAChD,OAAO,mBAAmB,CAC7B,CAAC;AASF,wBAAgB,6BAA6B;;;;;;;;;;;;;;;;aAQ5C;AAUD,8GAA8G;AAC9G,eAAO,MAAM,0BAA0B;;;;;;;;4NA6BtC,CAAC;AAgBF,wBAAgB,aAAa,CAAC,EAAE,aAAa,EAAE,QAAQ,EAAE,YAAY,EAAE,aAAa,EAAE,iBAAiB,EAAE,KAAK,EAAE,EAAE,IAAI,CAAC,wBAAwB,EAAE,aAAa,GAAG,SAAS,GAAG,KAAK,GAAG,UAAU,GAAG,SAAS,CAAC,QAQ3M"}
@@ -49,11 +49,11 @@ const InternalContextNavigationContainer = React.forwardRef((props, ref) => {
49
49
  // @ts-expect-error: children are required
50
50
  React.createElement(NavigationContainer, { ref: ref, ...props, ...contextProps }));
51
51
  });
52
- export function RootContainer(props) {
52
+ export function RootContainer({ documentTitle, fallback, initialState, onStateChange, onUnhandledAction, theme }) {
53
53
  const [, setProps] = useNavigationContainerContext();
54
54
  React.useEffect(() => {
55
- setProps(props);
56
- }, [props]);
55
+ setProps({ documentTitle, fallback, initialState, onStateChange, onUnhandledAction, theme });
56
+ }, [documentTitle, fallback, initialState, onStateChange, onUnhandledAction, theme]);
57
57
  return null;
58
58
  }
59
59
  //# sourceMappingURL=ContextNavigationContainer.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"ContextNavigationContainer.js","sourceRoot":"","sources":["../src/ContextNavigationContainer.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAkB,mBAAmB,EAAE,MAAM,0BAA0B,CAAC;AAC/E,OAAO,KAAK,EAAE,EAAE,OAAO,EAAE,WAAW,EAAE,MAAM,OAAO,CAAC;AACpD,OAAO,EAAE,gBAAgB,EAAE,MAAM,WAAW,CAAC;AAC7C,OAAO,EAAE,gBAAgB,EAAE,MAAM,oBAAoB,CAAC;AAMtD,SAAS,gBAAgB;IACrB,MAAM,MAAM,GAAG,gBAAgB,EAAE,CAAC;IAClC,OAAO,OAAO,CAAC,GAAG,EAAE,CAAC,gBAAgB,CAAC,MAAM,CAAC,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;AAC7D,CAAC;AAED,MAAM,0BAA0B,GAAG,KAAK,CAAC,aAAa,CAA0F,CAAC,EAAE,EAAE,cAAc,CAAC,CAAC,CAAC,CAAC;AAEvK,MAAM,UAAU,6BAA6B;IACzC,MAAM,OAAO,GAAG,KAAK,CAAC,UAAU,CAAC,0BAA0B,CAAC,CAAC;IAC7D,IAAI,CAAC,OAAO,EAAE;QACV,MAAM,IAAI,KAAK,CACX,gFAAgF,CACnF,CAAC;KACL;IACD,OAAO,OAAO,CAAC;AACnB,CAAC;AAED,IAAI,SAA6C,CAAC;AAClD,IAAI;IACA,SAAS;QACJ,OAAO,CAAC,oBAAoB,CAAyC,CAAC,SAAS,CAAC;IACrF,oFAAoF;CACvF;AAAC,MAAM,GAAG;AAGX,8GAA8G;AAC9G,MAAM,CAAC,MAAM,0BAA0B,GAAG,KAAK,CAAC,UAAU,CACtD,CAAC,KAA+B,EAAE,GAAoC,EAAE,EAAE;IACtE,MAAM,CAAC,KAAK,EAAE,QAAQ,CAAC,GAAG,KAAK,CAAC,QAAQ,CAAoC,EAAE,CAAC,CAAC;IAEhF,MAAM,OAAO,GAAG,gBAAgB,EAAE,CAAC;IACnC,OAAO,CAAC,GAAG,CAAC,SAAS,EAAE,OAAO,CAAC,CAAC;IAChC,MAAM,OAAO,GAAG,WAAW,CAAC,GAAG,EAAE;QAC7B,KAAK,CAAC,OAAO,EAAE,EAAE,CAAC;QAClB,IAAI,SAAS,EAAE;YACX,SAAS,EAAE,CAAC;SACf;IACL,CAAC,EAAE,CAAC,KAAK,CAAC,OAAO,CAAC,CAAC,CAAC;IAEpB,OAAO,CACH,oBAAC,0BAA0B,CAAC,QAAQ,IAAC,KAAK,EAAE;YACxC;gBACI,GAAG,KAAK;gBACR,OAAO;gBACP,OAAO;gBACP,GAAG,KAAK;aACX;YACD,QAAQ;SACX;QACG,oBAAC,kCAAkC,IAC/B,GAAG,EAAE,GAAG,GACV,CACgC,CACzC,CAAC;AACN,CAAC,CACJ,CAAC;AAEF,MAAM,kCAAkC,GAAG,KAAK,CAAC,UAAU,CACvD,CAAC,KAAS,EAAE,GAAoC,EAAE,EAAE;IAChD,MAAM,CAAC,YAAY,CAAC,GAAG,6BAA6B,EAAE,CAAC;IACvD,OAAO;IACH,0CAA0C;IAC1C,oBAAC,mBAAmB,IAChB,GAAG,EAAE,GAAG,KACJ,KAAK,KACL,YAAY,GAClB,CACL,CAAC;AACN,CAAC,CACJ,CAAC;AAEF,MAAM,UAAU,aAAa,CAAC,KAA6D;IACvF,MAAM,CAAC,EAAE,QAAQ,CAAC,GAAG,6BAA6B,EAAE,CAAC;IAErD,KAAK,CAAC,SAAS,CAAC,GAAG,EAAE;QACjB,QAAQ,CAAC,KAAK,CAAC,CAAC;IACpB,CAAC,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;IAEZ,OAAO,IAAI,CAAC;AAChB,CAAC","sourcesContent":["import { LinkingOptions, NavigationContainer } from \"@react-navigation/native\";\nimport React, { useMemo, useCallback } from \"react\";\nimport { useRoutesContext } from \"./context\";\nimport { getLinkingConfig } from \"./getLinkingConfig\";\n\ntype NavigationContainerProps = React.ComponentProps<\n typeof NavigationContainer\n>;\n\nfunction useLinkingConfig(): LinkingOptions<{}> {\n const routes = useRoutesContext();\n return useMemo(() => getLinkingConfig(routes), [routes]);\n}\n\nconst NavigationContainerContext = React.createContext<[Partial<NavigationContainerProps>, (props: Partial<NavigationContainerProps>) => void]>([{}, function () { }]);\n\nexport function useNavigationContainerContext() {\n const context = React.useContext(NavigationContainerContext);\n if (!context) {\n throw new Error(\n \"useNavigationContainerContext must be used within a NavigationContainerContext\"\n );\n }\n return context;\n}\n\nlet hideAsync: () => Promise<boolean> | undefined;\ntry {\n hideAsync =\n (require(\"expo-splash-screen\") as typeof import(\"expo-splash-screen\")).hideAsync;\n // Automatically handle hiding the splash screen if expo-splash-screen is installed.\n} catch { }\n\n\n/** react-navigation `NavigationContainer` with automatic `linking` prop generated from the routes context. */\nexport const ContextNavigationContainer = React.forwardRef(\n (props: NavigationContainerProps, ref: NavigationContainerProps[\"ref\"]) => {\n const [state, setState] = React.useState<Partial<NavigationContainerProps>>({});\n\n const linking = useLinkingConfig();\n console.log('linking', linking);\n const onReady = useCallback(() => {\n props.onReady?.();\n if (hideAsync) {\n hideAsync();\n }\n }, [props.onReady]);\n\n return (\n <NavigationContainerContext.Provider value={[\n {\n ...props,\n linking,\n onReady,\n ...state,\n },\n setState,\n ]}>\n <InternalContextNavigationContainer\n ref={ref}\n />\n </NavigationContainerContext.Provider>\n );\n }\n);\n\nconst InternalContextNavigationContainer = React.forwardRef(\n (props: {}, ref: NavigationContainerProps[\"ref\"]) => {\n const [contextProps] = useNavigationContainerContext();\n return (\n // @ts-expect-error: children are required\n <NavigationContainer\n ref={ref}\n {...props}\n {...contextProps}\n />\n );\n }\n);\n\nexport function RootContainer(props: Omit<NavigationContainerProps, 'children' | 'linking'>) {\n const [, setProps] = useNavigationContainerContext();\n\n React.useEffect(() => {\n setProps(props);\n }, [props]);\n\n return null;\n}"]}
1
+ {"version":3,"file":"ContextNavigationContainer.js","sourceRoot":"","sources":["../src/ContextNavigationContainer.tsx"],"names":[],"mappings":"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","sourcesContent":["import { LinkingOptions, NavigationContainer } from \"@react-navigation/native\";\nimport React, { useMemo, useCallback } from \"react\";\nimport { useRoutesContext } from \"./context\";\nimport { getLinkingConfig } from \"./getLinkingConfig\";\n\ntype NavigationContainerProps = React.ComponentProps<\n typeof NavigationContainer\n>;\n\nfunction useLinkingConfig(): LinkingOptions<{}> {\n const routes = useRoutesContext();\n return useMemo(() => getLinkingConfig(routes), [routes]);\n}\n\nconst NavigationContainerContext = React.createContext<[Partial<NavigationContainerProps>, (props: Partial<NavigationContainerProps>) => void]>([{}, function () { }]);\n\nexport function useNavigationContainerContext() {\n const context = React.useContext(NavigationContainerContext);\n if (!context) {\n throw new Error(\n \"useNavigationContainerContext must be used within a NavigationContainerContext\"\n );\n }\n return context;\n}\n\nlet hideAsync: () => Promise<boolean> | undefined;\ntry {\n hideAsync =\n (require(\"expo-splash-screen\") as typeof import(\"expo-splash-screen\")).hideAsync;\n // Automatically handle hiding the splash screen if expo-splash-screen is installed.\n} catch { }\n\n\n/** react-navigation `NavigationContainer` with automatic `linking` prop generated from the routes context. */\nexport const ContextNavigationContainer = React.forwardRef(\n (props: NavigationContainerProps, ref: NavigationContainerProps[\"ref\"]) => {\n const [state, setState] = React.useState<Partial<NavigationContainerProps>>({});\n\n const linking = useLinkingConfig();\n console.log('linking', linking);\n const onReady = useCallback(() => {\n props.onReady?.();\n if (hideAsync) {\n hideAsync();\n }\n }, [props.onReady]);\n\n return (\n <NavigationContainerContext.Provider value={[\n {\n ...props,\n linking,\n onReady,\n ...state,\n },\n setState,\n ]}>\n <InternalContextNavigationContainer\n ref={ref}\n />\n </NavigationContainerContext.Provider>\n );\n }\n);\n\nconst InternalContextNavigationContainer = React.forwardRef(\n (props: {}, ref: NavigationContainerProps[\"ref\"]) => {\n const [contextProps] = useNavigationContainerContext();\n return (\n // @ts-expect-error: children are required\n <NavigationContainer\n ref={ref}\n {...props}\n {...contextProps}\n />\n );\n }\n);\n\nexport function RootContainer({ documentTitle, fallback, initialState, onStateChange, onUnhandledAction, theme }: Omit<NavigationContainerProps, 'independent' | 'onReady' | 'ref' | 'children' | 'linking'>) {\n const [, setProps] = useNavigationContainerContext();\n\n React.useEffect(() => {\n setProps({ documentTitle, fallback, initialState, onStateChange, onUnhandledAction, theme });\n }, [documentTitle, fallback, initialState, onStateChange, onUnhandledAction, theme]);\n\n return null;\n}"]}
@@ -1 +1 @@
1
- {"version":3,"file":"ContextNavigator.d.ts","sourceRoot":"","sources":["../src/ContextNavigator.tsx"],"names":[],"mappings":";AAOA,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAyDzC,wBAAgB,gBAAgB,CAAC,EAAE,OAAO,EAAE,EAAE;IAAE,OAAO,EAAE,cAAc,CAAA;CAAE,eAkBxE"}
1
+ {"version":3,"file":"ContextNavigator.d.ts","sourceRoot":"","sources":["../src/ContextNavigator.tsx"],"names":[],"mappings":";AAOA,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AA0DzC,wBAAgB,gBAAgB,CAAC,EAAE,OAAO,EAAE,EAAE;IAAE,OAAO,EAAE,cAAc,CAAA;CAAE,eAsBxE"}
@@ -6,7 +6,8 @@ import { NativeStack } from './layouts/NativeStack';
6
6
  import { Route } from './Route';
7
7
  function useContextModuleAsRoutes(context) {
8
8
  // TODO: Is this an optimal hook dependency?
9
- return useMemo(() => getRoutes(context), [context]);
9
+ const keys = useMemo(() => context.keys(), [context]);
10
+ return useMemo(() => getRoutes(context), [keys]);
10
11
  }
11
12
  function RoutesContextProvider({ context, children, }) {
12
13
  const routes = useContextModuleAsRoutes(context);
@@ -44,9 +45,9 @@ export function ContextNavigator({ context }) {
44
45
  if (Tutorial) {
45
46
  return React.createElement(Tutorial, null);
46
47
  }
47
- return (React.createElement(RoutesContextProvider, { context: context },
48
- React.createElement(Route, { filename: "./" },
49
- React.createElement(ContextNavigationContainer, null,
50
- React.createElement(NativeStack, { screenOptions: { animation: "none", headerShown: false } })))));
48
+ const children = useMemo(() => (React.createElement(Route, { filename: "./" },
49
+ React.createElement(ContextNavigationContainer, null,
50
+ React.createElement(NativeStack, { screenOptions: { animation: "none", headerShown: false } })))), []);
51
+ return (React.createElement(RoutesContextProvider, { context: context }, children));
51
52
  }
52
53
  //# sourceMappingURL=ContextNavigator.js.map
@@ -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,aAAa,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAC;AAC1E,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAIhC,SAAS,wBAAwB,CAAC,OAAuB;IACrD,4CAA4C;IAC5C,OAAO,OAAO,CAAC,GAAG,EAAE,CAAC,SAAS,CAAC,OAAO,CAAC,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;AACxD,CAAC;AAED,SAAS,qBAAqB,CAAC,EAC3B,OAAO,EACP,QAAQ,GAIX;IACG,MAAM,MAAM,GAAG,wBAAwB,CAAC,OAAO,CAAC,CAAC;IACjD,OAAO,CACH,oBAAC,aAAa,CAAC,QAAQ,IAAC,KAAK,EAAE,MAAM,IAAG,QAAQ,CAA0B,CAC7E,CAAC;AACN,CAAC;AAED,SAAS,0BAA0B,CAC/B,SAAc;IAEd,OAAO,CACH,CAAC,CAAC,SAAS;QACX,CAAC,OAAO,SAAS,KAAK,UAAU;YAC5B,SAAS,EAAE,SAAS,EAAE,gBAAgB;YACtC,SAAS,CAAC,QAAQ,KAAK,MAAM,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC,CAC9D,CAAC;AACN,CAAC;AAED,yIAAyI;AACzI,SAAS,WAAW,CAAC,OAAuB;IACxC,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,EAAE;QACvC,OAAO,IAAI,CAAC;KACf;IAED,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IACtD,MAAM,oBAAoB,GAAG,OAAO,CAAC,GAAG,EAAE;QACtC,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE;YACpB,2FAA2F;YAC3F,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC;YACxC,IAAI,0BAA0B,CAAC,SAAS,CAAC,EAAE;gBACvC,OAAO,IAAI,CAAC;aACf;SACJ;QACD,OAAO,KAAK,CAAC;IACjB,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAEX,IAAI,oBAAoB,EAAE;QACtB,OAAO,IAAI,CAAC;KACf;IAED,OAAO,OAAO,CAAC,oBAAoB,CAAC,CAAC,QAAQ,CAAC;AAClD,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,EAAE,OAAO,EAA+B;IACrE,MAAM,QAAQ,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;IACtC,IAAI,QAAQ,EAAE;QACV,OAAO,oBAAC,QAAQ,OAAG,CAAC;KACvB;IAED,OAAO,CACH,oBAAC,qBAAqB,IAAC,OAAO,EAAE,OAAO;QACnC,oBAAC,KAAK,IAAC,QAAQ,EAAC,IAAI;YAChB,oBAAC,0BAA0B;gBAEvB,oBAAC,WAAW,IACR,aAAa,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,GAC1D,CACuB,CACzB,CACY,CAC3B,CAAC;AACN,CAAC","sourcesContent":["import React, { useMemo } from 'react';\n\nimport { RoutesContext } from './context';\nimport { ContextNavigationContainer } from './ContextNavigationContainer';\nimport { getRoutes } from './getRoutes';\nimport { NativeStack } from './layouts/NativeStack';\nimport { Route } from './Route';\nimport { RequireContext } from './types';\n\n\nfunction useContextModuleAsRoutes(context: RequireContext) {\n // TODO: Is this an optimal hook dependency?\n return useMemo(() => getRoutes(context), [context]);\n}\n\nfunction RoutesContextProvider({\n context,\n children,\n}: {\n context: RequireContext;\n children: React.ReactNode;\n}) {\n const routes = useContextModuleAsRoutes(context);\n return (\n <RoutesContext.Provider value={routes}>{children}</RoutesContext.Provider>\n );\n}\n\nfunction isFunctionOrReactComponent(\n Component: any\n): Component is React.ComponentType {\n return (\n !!Component &&\n (typeof Component === \"function\" ||\n Component?.prototype?.isReactComponent ||\n Component.$$typeof === Symbol.for(\"react.forward_ref\"))\n );\n}\n\n/** Returns the Tutorial component if there are no React components exported as default from any files in the provided context module. */\nfunction useTutorial(context: RequireContext) {\n if (process.env.NODE_ENV === \"production\") {\n return null;\n }\n\n const keys = useMemo(() => context.keys(), [context]);\n const hasAnyValidComponent = useMemo(() => {\n for (const key of keys) {\n // NOTE(EvanBacon): This should only ever occur in development as it breaks lazily loading.\n const component = context(key)?.default;\n if (isFunctionOrReactComponent(component)) {\n return true;\n }\n }\n return false;\n }, [keys]);\n\n if (hasAnyValidComponent) {\n return null;\n }\n\n return require(\"./onboard/Tutorial\").Tutorial;\n}\n\nexport function ContextNavigator({ context }: { context: RequireContext }) {\n const Tutorial = useTutorial(context);\n if (Tutorial) {\n return <Tutorial />;\n }\n\n return (\n <RoutesContextProvider context={context}>\n <Route filename=\"./\">\n <ContextNavigationContainer>\n {/* Using a switch navigator at the root to host all pages. */}\n <NativeStack\n screenOptions={{ animation: \"none\", headerShown: false }}\n />\n </ContextNavigationContainer>\n </Route>\n </RoutesContextProvider>\n );\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,aAAa,EAAE,MAAM,WAAW,CAAC;AAC1C,OAAO,EAAE,0BAA0B,EAAE,MAAM,8BAA8B,CAAC;AAC1E,OAAO,EAAE,SAAS,EAAE,MAAM,aAAa,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAIhC,SAAS,wBAAwB,CAAC,OAAuB;IACrD,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;AACrD,CAAC;AAED,SAAS,qBAAqB,CAAC,EAC3B,OAAO,EACP,QAAQ,GAIX;IACG,MAAM,MAAM,GAAG,wBAAwB,CAAC,OAAO,CAAC,CAAC;IACjD,OAAO,CACH,oBAAC,aAAa,CAAC,QAAQ,IAAC,KAAK,EAAE,MAAM,IAAG,QAAQ,CAA0B,CAC7E,CAAC;AACN,CAAC;AAED,SAAS,0BAA0B,CAC/B,SAAc;IAEd,OAAO,CACH,CAAC,CAAC,SAAS;QACX,CAAC,OAAO,SAAS,KAAK,UAAU;YAC5B,SAAS,EAAE,SAAS,EAAE,gBAAgB;YACtC,SAAS,CAAC,QAAQ,KAAK,MAAM,CAAC,GAAG,CAAC,mBAAmB,CAAC,CAAC,CAC9D,CAAC;AACN,CAAC;AAED,yIAAyI;AACzI,SAAS,WAAW,CAAC,OAAuB;IACxC,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,EAAE;QACvC,OAAO,IAAI,CAAC;KACf;IAED,MAAM,IAAI,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,OAAO,CAAC,IAAI,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,CAAC;IACtD,MAAM,oBAAoB,GAAG,OAAO,CAAC,GAAG,EAAE;QACtC,KAAK,MAAM,GAAG,IAAI,IAAI,EAAE;YACpB,2FAA2F;YAC3F,MAAM,SAAS,GAAG,OAAO,CAAC,GAAG,CAAC,EAAE,OAAO,CAAC;YACxC,IAAI,0BAA0B,CAAC,SAAS,CAAC,EAAE;gBACvC,OAAO,IAAI,CAAC;aACf;SACJ;QACD,OAAO,KAAK,CAAC;IACjB,CAAC,EAAE,CAAC,IAAI,CAAC,CAAC,CAAC;IAEX,IAAI,oBAAoB,EAAE;QACtB,OAAO,IAAI,CAAC;KACf;IAED,OAAO,OAAO,CAAC,oBAAoB,CAAC,CAAC,QAAQ,CAAC;AAClD,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,EAAE,OAAO,EAA+B;IACrE,MAAM,QAAQ,GAAG,WAAW,CAAC,OAAO,CAAC,CAAC;IACtC,IAAI,QAAQ,EAAE;QACV,OAAO,oBAAC,QAAQ,OAAG,CAAC;KACvB;IAED,MAAM,QAAQ,GAAG,OAAO,CAAC,GAAG,EAAE,CAAC,CAC3B,oBAAC,KAAK,IAAC,QAAQ,EAAC,IAAI;QAChB,oBAAC,0BAA0B;YAEvB,oBAAC,WAAW,IACR,aAAa,EAAE,EAAE,SAAS,EAAE,MAAM,EAAE,WAAW,EAAE,KAAK,EAAE,GAC1D,CACuB,CACzB,CACX,EAAE,EAAE,CAAC,CAAC;IAEP,OAAO,CACH,oBAAC,qBAAqB,IAAC,OAAO,EAAE,OAAO,IAClC,QAAQ,CACW,CAC3B,CAAC;AACN,CAAC","sourcesContent":["import React, { useMemo } from 'react';\n\nimport { RoutesContext } from './context';\nimport { ContextNavigationContainer } from './ContextNavigationContainer';\nimport { getRoutes } from './getRoutes';\nimport { NativeStack } from './layouts/NativeStack';\nimport { Route } from './Route';\nimport { RequireContext } from './types';\n\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 RoutesContextProvider({\n context,\n children,\n}: {\n context: RequireContext;\n children: React.ReactNode;\n}) {\n const routes = useContextModuleAsRoutes(context);\n return (\n <RoutesContext.Provider value={routes}>{children}</RoutesContext.Provider>\n );\n}\n\nfunction isFunctionOrReactComponent(\n Component: any\n): Component is React.ComponentType {\n return (\n !!Component &&\n (typeof Component === \"function\" ||\n Component?.prototype?.isReactComponent ||\n Component.$$typeof === Symbol.for(\"react.forward_ref\"))\n );\n}\n\n/** Returns the Tutorial component if there are no React components exported as default from any files in the provided context module. */\nfunction useTutorial(context: RequireContext) {\n if (process.env.NODE_ENV === \"production\") {\n return null;\n }\n\n const keys = useMemo(() => context.keys(), [context]);\n const hasAnyValidComponent = useMemo(() => {\n for (const key of keys) {\n // NOTE(EvanBacon): This should only ever occur in development as it breaks lazily loading.\n const component = context(key)?.default;\n if (isFunctionOrReactComponent(component)) {\n return true;\n }\n }\n return false;\n }, [keys]);\n\n if (hasAnyValidComponent) {\n return null;\n }\n\n return require(\"./onboard/Tutorial\").Tutorial;\n}\n\nexport function ContextNavigator({ context }: { context: RequireContext }) {\n const Tutorial = useTutorial(context);\n if (Tutorial) {\n return <Tutorial />;\n }\n\n const children = useMemo(() => (\n <Route filename=\"./\">\n <ContextNavigationContainer>\n {/* Using a switch navigator at the root to host all pages. */}\n <NativeStack\n screenOptions={{ animation: \"none\", headerShown: false }}\n />\n </ContextNavigationContainer>\n </Route>\n ), []);\n\n return (\n <RoutesContextProvider context={context}>\n {children}\n </RoutesContextProvider>\n );\n}\n\n"]}
package/build/Route.d.ts CHANGED
@@ -21,14 +21,14 @@ export declare type RouteNode = {
21
21
  generated?: boolean;
22
22
  /** Internal screens like the directory or the auto 404 should be marked as internal. */
23
23
  internal?: boolean;
24
- /** React Navigation screen name. */
25
- screenName: string;
26
24
  };
27
25
  /** Return all the routes for the current boundary. */
28
26
  export declare function useRoutes(): RouteNode[];
27
+ export declare function useContextKey(): string;
29
28
  /** Provides the matching routes and filename to the children. */
30
29
  export declare function Route({ filename, children, }: {
31
30
  filename: string;
32
31
  children: ReactNode;
33
32
  }): JSX.Element;
33
+ export declare function sortRoutes(a: RouteNode, b: RouteNode): number;
34
34
  //# sourceMappingURL=Route.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Route.d.ts","sourceRoot":"","sources":["../src/Route.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAE,SAAS,EAAc,MAAM,OAAO,CAAC;AAIrD,yFAAyF;AACzF,oBAAY,WAAW,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,CAAC,IAAI,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,GACtD,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AAExB,oBAAY,SAAS,GAAG;IACpB,oBAAoB;IACpB,QAAQ,EAAE,SAAS,EAAE,CAAC;IACtB,qCAAqC;IACrC,YAAY,EAAE,MAAM,KAAK,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;IAC7C,kCAAkC;IAClC,OAAO,EAAE,IAAI,GAAG;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,OAAO,CAAA;KAAE,CAAC;IAChD,wCAAwC;IACxC,SAAS,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACrC,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;IAEnB,oCAAoC;IACpC,UAAU,EAAE,MAAM,CAAC;CACtB,CAAC;AAkBF,sDAAsD;AACtD,wBAAgB,SAAS,IAAI,SAAS,EAAE,CAQvC;AAED,iEAAiE;AACjE,wBAAgB,KAAK,CAAC,EAClB,QAAQ,EACR,QAAQ,GACX,EAAE;IACC,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,SAAS,CAAC;CACvB,eAUA"}
1
+ {"version":3,"file":"Route.d.ts","sourceRoot":"","sources":["../src/Route.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,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,GACtD,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AAExB,oBAAY,SAAS,GAAG;IACpB,oBAAoB;IACpB,QAAQ,EAAE,SAAS,EAAE,CAAC;IACtB,qCAAqC;IACrC,YAAY,EAAE,MAAM,KAAK,CAAC,aAAa,CAAC,GAAG,CAAC,CAAC;IAC7C,kCAAkC;IAClC,OAAO,EAAE,IAAI,GAAG;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,IAAI,EAAE,OAAO,CAAA;KAAE,CAAC;IAChD,wCAAwC;IACxC,SAAS,EAAE,MAAM,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,CAAC;IACrC,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;CACtB,CAAC;AAWF,sDAAsD;AACtD,wBAAgB,SAAS,IAAI,SAAS,EAAE,CAEvC;AAED,wBAAgB,aAAa,IAAI,MAAM,CAMtC;AAED,iEAAiE;AACjE,wBAAgB,KAAK,CAAC,EAClB,QAAQ,EACR,QAAQ,GACX,EAAE;IACC,QAAQ,EAAE,MAAM,CAAC;IACjB,QAAQ,EAAE,SAAS,CAAC;CACvB,eAcA;AA+BD,wBAAgB,UAAU,CAAC,CAAC,EAAE,SAAS,EAAE,CAAC,EAAE,SAAS,GAAG,MAAM,CA4B7D"}
package/build/Route.js CHANGED
@@ -1,29 +1,28 @@
1
1
  import React, { useContext } from 'react';
2
- import { getNameFromFilePath } from './matchers';
3
2
  import { RoutesContext } from './context';
4
- const CurrentRouteContext = React.createContext({
5
- filename: null,
6
- routes: [],
7
- // siblings: [],
8
- // parent: null,
9
- });
10
- if (process.env.NODE_ENV === "development") {
3
+ import { getNameFromFilePath, matchFragmentName } from './matchers';
4
+ const CurrentRoutePathContext = React.createContext(null);
5
+ const CurrentRouteContext = React.createContext([]);
6
+ if (process.env.NODE_ENV !== "production") {
7
+ CurrentRoutePathContext.displayName = "RoutePath";
11
8
  CurrentRouteContext.displayName = "Route";
12
9
  }
13
10
  /** Return all the routes for the current boundary. */
14
11
  export function useRoutes() {
15
- const { filename, routes } = useContext(CurrentRouteContext);
16
- if (process.env.NODE_ENV === "development") {
17
- if (!filename) {
18
- throw new Error("No filename found. This is likely a bug in expo-router.");
19
- }
12
+ return useContext(CurrentRouteContext);
13
+ }
14
+ export function useContextKey() {
15
+ const filename = useContext(CurrentRoutePathContext);
16
+ if (!filename) {
17
+ throw new Error("No filename found. This is likely a bug in expo-router.");
20
18
  }
21
- return routes;
19
+ return filename;
22
20
  }
23
21
  /** Provides the matching routes and filename to the children. */
24
22
  export function Route({ filename, children, }) {
25
23
  const routes = useRoutesAtPath(filename);
26
- return (React.createElement(CurrentRouteContext.Provider, { value: { filename, routes } }, children));
24
+ return (React.createElement(CurrentRoutePathContext.Provider, { value: filename },
25
+ React.createElement(CurrentRouteContext.Provider, { value: routes }, children)));
27
26
  }
28
27
  function useRoutesAtPath(filename) {
29
28
  const normalName = React.useMemo(() => getNameFromFilePath(filename), [filename]);
@@ -31,9 +30,6 @@ function useRoutesAtPath(filename) {
31
30
  const keys = React.useMemo(() => routes.keys(), [routes]);
32
31
  const family = React.useMemo(() => {
33
32
  let children = routes;
34
- let current = null;
35
- // let siblings: RouteNode[] = [];
36
- // let parent: RouteNode | null = null;
37
33
  // Skip root directory
38
34
  if (normalName) {
39
35
  // split and search
@@ -43,14 +39,37 @@ function useRoutesAtPath(filename) {
43
39
  if (!next?.children) {
44
40
  return [];
45
41
  }
46
- // parent = current;
47
- // siblings = children;
48
- current = next;
49
42
  children = next?.children;
50
43
  }
51
44
  }
52
- return children;
45
+ return children.sort(sortRoutes);
53
46
  }, [normalName, keys]);
54
47
  return family;
55
48
  }
49
+ export function sortRoutes(a, b) {
50
+ if (a.dynamic && !b.dynamic) {
51
+ return 1;
52
+ }
53
+ if (!a.dynamic && b.dynamic) {
54
+ return -1;
55
+ }
56
+ if (a.dynamic && b.dynamic) {
57
+ if (a.dynamic.deep && !b.dynamic.deep) {
58
+ return 1;
59
+ }
60
+ if (!a.dynamic.deep && b.dynamic.deep) {
61
+ return -1;
62
+ }
63
+ return 0;
64
+ }
65
+ const aIndex = a.route === "index" || matchFragmentName(a.route) != null;
66
+ const bIndex = b.route === "index" || matchFragmentName(b.route) != null;
67
+ if (aIndex && !bIndex) {
68
+ return -1;
69
+ }
70
+ if (!aIndex && bIndex) {
71
+ return 1;
72
+ }
73
+ return a.route.length - b.route.length;
74
+ }
56
75
  //# sourceMappingURL=Route.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Route.js","sourceRoot":"","sources":["../src/Route.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,EAAa,UAAU,EAAE,MAAM,OAAO,CAAC;AACrD,OAAO,EAAE,mBAAmB,EAAE,MAAM,YAAY,CAAC;AACjD,OAAO,EAAE,aAAa,EAAE,MAAM,WAAW,CAAC;AA6B1C,MAAM,mBAAmB,GAAG,KAAK,CAAC,aAAa,CAK5C;IACC,QAAQ,EAAE,IAAI;IACd,MAAM,EAAE,EAAE;IACV,gBAAgB;IAChB,gBAAgB;CACnB,CAAC,CAAC;AAEH,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,aAAa,EAAE;IACxC,mBAAmB,CAAC,WAAW,GAAG,OAAO,CAAC;CAC7C;AAED,sDAAsD;AACtD,MAAM,UAAU,SAAS;IACrB,MAAM,EAAE,QAAQ,EAAE,MAAM,EAAE,GAAG,UAAU,CAAC,mBAAmB,CAAC,CAAC;IAC7D,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,aAAa,EAAE;QACxC,IAAI,CAAC,QAAQ,EAAE;YACX,MAAM,IAAI,KAAK,CAAC,yDAAyD,CAAC,CAAC;SAC9E;KACJ;IACD,OAAO,MAAM,CAAC;AAClB,CAAC;AAED,iEAAiE;AACjE,MAAM,UAAU,KAAK,CAAC,EAClB,QAAQ,EACR,QAAQ,GAIX;IACG,MAAM,MAAM,GAAG,eAAe,CAAC,QAAQ,CAAC,CAAC;IAEzC,OAAO,CACH,oBAAC,mBAAmB,CAAC,QAAQ,IACzB,KAAK,EAAE,EAAE,QAAQ,EAAE,MAAM,EAAE,IAE1B,QAAQ,CACkB,CAClC,CAAC;AACN,CAAC;AAED,SAAS,eAAe,CAAC,QAAgB;IACrC,MAAM,UAAU,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,mBAAmB,CAAC,QAAQ,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;IAClF,MAAM,MAAM,GAAG,UAAU,CAAC,aAAa,CAAC,CAAC;IACzC,MAAM,IAAI,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,IAAI,EAAE,EAAE,CAAC,MAAM,CAAC,CAAC,CAAC;IAE1D,MAAM,MAAM,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE;QAC9B,IAAI,QAAQ,GAAgB,MAAM,CAAC;QACnC,IAAI,OAAO,GAAqB,IAAI,CAAC;QACrC,kCAAkC;QAClC,uCAAuC;QAEvC,sBAAsB;QACtB,IAAI,UAAU,EAAE;YACZ,mBAAmB;YACnB,MAAM,KAAK,GAAG,UAAU,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC;YACpC,KAAK,MAAM,IAAI,IAAI,KAAK,EAAE;gBACtB,MAAM,IAAI,GAAG,QAAQ,CAAC,IAAI,CAAC,CAAC,EAAE,KAAK,EAAE,EAAE,EAAE,CAAC,KAAK,KAAK,IAAI,CAAC,CAAC;gBAE1D,IAAI,CAAC,IAAI,EAAE,QAAQ,EAAE;oBACjB,OAAO,EAAE,CAAC;iBACb;gBAED,oBAAoB;gBACpB,uBAAuB;gBACvB,OAAO,GAAG,IAAI,CAAC;gBACf,QAAQ,GAAG,IAAI,EAAE,QAAQ,CAAC;aAC7B;SACJ;QAED,OAAO,QAAQ,CAAA;IACnB,CAAC,EAAE,CAAC,UAAU,EAAE,IAAI,CAAC,CAAC,CAAC;IAEvB,OAAO,MAAM,CAAC;AAClB,CAAC","sourcesContent":["import React, { ReactNode, useContext } from 'react';\nimport { getNameFromFilePath } from './matchers';\nimport { RoutesContext } from './context';\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 /** nested routes */\n children: RouteNode[];\n /** Lazily get the React component */\n getComponent: () => React.ComponentType<any>;\n /** Is the route a dynamic path */\n dynamic: null | { name: string; deep: boolean };\n /** All static exports from the file. */\n getExtras: () => Record<string, any>;\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 /** React Navigation screen name. */\n screenName: string;\n};\n\nconst CurrentRouteContext = React.createContext<{\n filename: string | null;\n routes: RouteNode[];\n // siblings: RouteNode[];\n // parent: RouteNode | null;\n}>({\n filename: null,\n routes: [],\n // siblings: [],\n // parent: null,\n});\n\nif (process.env.NODE_ENV === \"development\") {\n CurrentRouteContext.displayName = \"Route\";\n}\n\n/** Return all the routes for the current boundary. */\nexport function useRoutes(): RouteNode[] {\n const { filename, routes } = useContext(CurrentRouteContext);\n if (process.env.NODE_ENV === \"development\") {\n if (!filename) {\n throw new Error(\"No filename found. This is likely a bug in expo-router.\");\n }\n }\n return routes;\n}\n\n/** Provides the matching routes and filename to the children. */\nexport function Route({\n filename,\n children,\n}: {\n filename: string;\n children: ReactNode;\n}) {\n const routes = useRoutesAtPath(filename);\n\n return (\n <CurrentRouteContext.Provider\n value={{ filename, routes }}\n >\n {children}\n </CurrentRouteContext.Provider>\n );\n}\n\nfunction useRoutesAtPath(filename: string): RouteNode[] {\n const normalName = React.useMemo(() => getNameFromFilePath(filename), [filename]);\n const routes = useContext(RoutesContext);\n const keys = React.useMemo(() => routes.keys(), [routes]);\n\n const family = React.useMemo(() => {\n let children: RouteNode[] = routes;\n let current: RouteNode | null = null;\n // let siblings: RouteNode[] = [];\n // let parent: RouteNode | null = null;\n\n // Skip root directory\n if (normalName) {\n // split and search\n const parts = normalName.split(\"/\");\n for (const part of parts) {\n const next = children.find(({ route }) => route === part);\n\n if (!next?.children) {\n return [];\n }\n\n // parent = current;\n // siblings = children;\n current = next;\n children = next?.children;\n }\n }\n\n return children\n }, [normalName, keys]);\n\n return family;\n}\n"]}
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 { RoutesContext } 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 /** nested routes */\n children: RouteNode[];\n /** Lazily get the React component */\n getComponent: () => React.ComponentType<any>;\n /** Is the route a dynamic path */\n dynamic: null | { name: string; deep: boolean };\n /** All static exports from the file. */\n getExtras: () => Record<string, any>;\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[]>([]);\n\nif (process.env.NODE_ENV !== \"production\") {\n CurrentRoutePathContext.displayName = \"RoutePath\";\n CurrentRouteContext.displayName = \"Route\";\n}\n\n/** Return all the routes for the current boundary. */\nexport function useRoutes(): RouteNode[] {\n return useContext(CurrentRouteContext);\n}\n\nexport function useContextKey(): string {\n const filename = useContext(CurrentRoutePathContext);\n if (!filename) {\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 filename,\n children,\n}: {\n filename: string;\n children: ReactNode;\n}) {\n const routes = useRoutesAtPath(filename);\n\n return (\n <CurrentRoutePathContext.Provider\n value={filename}\n >\n <CurrentRouteContext.Provider\n value={routes}\n >\n {children}\n </CurrentRouteContext.Provider>\n </CurrentRoutePathContext.Provider>\n );\n}\n\nfunction useRoutesAtPath(filename: string): RouteNode[] {\n const normalName = React.useMemo(() => getNameFromFilePath(filename), [filename]);\n const routes = useContext(RoutesContext);\n const keys = React.useMemo(() => routes.keys(), [routes]);\n\n const family = React.useMemo(() => {\n let children: RouteNode[] = routes;\n\n // Skip root directory\n if (normalName) {\n // split and search\n const parts = normalName.split(\"/\");\n for (const part of parts) {\n const next = children.find(({ route }) => route === part);\n\n if (!next?.children) {\n return [];\n }\n\n children = next?.children;\n }\n }\n\n return children.sort(sortRoutes)\n }, [normalName, keys]);\n\n return family;\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}"]}
@@ -1 +1 @@
1
- {"version":3,"file":"getLinkingConfig.d.ts","sourceRoot":"","sources":["../src/getLinkingConfig.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAWzE,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAqBpC,wBAAgB,kCAAkC,CAChD,KAAK,EAAE,SAAS,EAAE,EAClB,OAAO,GAAE,MAAM,EAAO,GACrB,aAAa,CAAC,EAAE,CAAC,CA0BnB;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,cAAc,CAAC,EAAE,CAAC,CAgBxE"}
1
+ {"version":3,"file":"getLinkingConfig.d.ts","sourceRoot":"","sources":["../src/getLinkingConfig.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,cAAc,EAAE,aAAa,EAAE,MAAM,0BAA0B,CAAC;AAWzE,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AAqBpC,wBAAgB,kCAAkC,CAChD,KAAK,EAAE,SAAS,EAAE,EAClB,OAAO,GAAE,MAAM,EAAO,GACrB,aAAa,CAAC,EAAE,CAAC,CAwBnB;AAED,wBAAgB,gBAAgB,CAAC,MAAM,EAAE,SAAS,EAAE,GAAG,cAAc,CAAC,EAAE,CAAC,CAgBxE"}
@@ -23,22 +23,18 @@ export function treeToReactNavigationLinkingRoutes(nodes, parents = []) {
23
23
  // Our warnings can be more helpful than upstream since we know the associated file name.
24
24
  const firstPass = nodes
25
25
  .map((node) => {
26
- let path = convertDynamicRouteToReactNavigation(node.route);
27
- return [
28
- node.screenName,
29
- {
30
- path: path,
31
- screens: node.children.length
32
- ? treeToReactNavigationLinkingRoutes(node.children, [
33
- ...parents,
34
- path,
35
- ])
36
- : undefined,
37
- },
38
- ];
26
+ const path = convertDynamicRouteToReactNavigation(node.route);
27
+ if (!node.children.length) {
28
+ return [node.route, path];
29
+ }
30
+ const screens = treeToReactNavigationLinkingRoutes(node.children, [
31
+ ...parents,
32
+ path,
33
+ ]);
34
+ return [node.route, { path, screens }];
39
35
  })
40
- .reduce((acc, [screenName, current]) => {
41
- acc[screenName] = current;
36
+ .reduce((acc, [route, current]) => {
37
+ acc[route] = current;
42
38
  return acc;
43
39
  }, {});
44
40
  return firstPass;
@@ -1 +1 @@
1
- {"version":3,"file":"getLinkingConfig.js","sourceRoot":"","sources":["../src/getLinkingConfig.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,OAAO,MAAM,cAAc,CAAC;AAExC,OAAO,EAAE,kBAAkB,EAAE,MAAM,QAAQ,CAAC;AAC5C,OAAO,gBAAgB,MAAM,yBAAyB,CAAC;AACvD,OAAO,gBAAgB,MAAM,yBAAyB,CAAC;AACvD,OAAO,EACL,yBAAyB,EACzB,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,YAAY,CAAC;AAGpB,sBAAsB;AACtB,mBAAmB;AACnB,SAAS,oCAAoC,CAAC,IAAY;IACxD,IAAI,yBAAyB,CAAC,IAAI,CAAC,EAAE;QACnC,OAAO,GAAG,CAAC;KACZ;IACD,MAAM,WAAW,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;IAE3C,IAAI,WAAW,EAAE;QACf,OAAO,IAAI,WAAW,EAAE,CAAC;KAC1B;IAED,IAAI,IAAI,KAAK,OAAO,IAAI,iBAAiB,CAAC,IAAI,CAAC,EAAE;QAC/C,OAAO,EAAE,CAAC;KACX;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,kCAAkC,CAChD,KAAkB,EAClB,UAAoB,EAAE;IAEtB,kEAAkE;IAClE,yFAAyF;IACzF,MAAM,SAAS,GAAG,KAAK;SACpB,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QACZ,IAAI,IAAI,GAAG,oCAAoC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAE5D,OAAO;YACL,IAAI,CAAC,UAAU;YACf;gBACE,IAAI,EAAE,IAAI;gBACV,OAAO,EAAE,IAAI,CAAC,QAAQ,CAAC,MAAM;oBAC3B,CAAC,CAAC,kCAAkC,CAAC,IAAI,CAAC,QAAQ,EAAE;wBAChD,GAAG,OAAO;wBACV,IAAI;qBACL,CAAC;oBACJ,CAAC,CAAC,SAAS;aACd;SACO,CAAC;IACb,CAAC,CAAC;SACD,MAAM,CAAoB,CAAC,GAAG,EAAE,CAAC,UAAU,EAAE,OAAO,CAAC,EAAE,EAAE;QACxD,GAAG,CAAC,UAAU,CAAC,GAAG,OAAO,CAAC;QAC1B,OAAO,GAAG,CAAC;IACb,CAAC,EAAE,EAAE,CAAC,CAAC;IAET,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,MAAmB;IAClD,OAAO;QACL,QAAQ,EAAE;YACR,2BAA2B;YAC3B,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC;YAEtB,4FAA4F;YAC5F,0BAA0B;YAC1B,GAAG,kBAAkB,EAAE;SACxB;QACD,MAAM,EAAE;YACN,OAAO,EAAE,kCAAkC,CAAC,MAAM,CAAC;SACpD;QACD,gBAAgB;QAChB,gBAAgB;KACjB,CAAC;AACJ,CAAC","sourcesContent":["import { LinkingOptions, PathConfigMap } from \"@react-navigation/native\";\nimport * as Linking from \"expo-linking\";\n\nimport { getAllWebRedirects } from \"./aasa\";\nimport getPathFromState from \"./fork/getPathFromState\";\nimport getStateFromPath from \"./fork/getStateFromPath\";\nimport {\n matchDeepDynamicRouteName,\n matchDynamicName,\n matchFragmentName,\n} from \"./matchers\";\nimport { RouteNode } from \"./Route\";\n\n// `[page]` -> `:page`\n// `page` -> `page`\nfunction convertDynamicRouteToReactNavigation(name: string) {\n if (matchDeepDynamicRouteName(name)) {\n return \"*\";\n }\n const dynamicName = matchDynamicName(name);\n\n if (dynamicName) {\n return `:${dynamicName}`;\n }\n\n if (name === \"index\" || matchFragmentName(name)) {\n return \"\";\n }\n\n return name;\n}\n\nexport function treeToReactNavigationLinkingRoutes(\n nodes: RouteNode[],\n parents: string[] = []\n): PathConfigMap<{}> {\n // TODO: Intercept errors, strip invalid routes, and warn instead.\n // Our warnings can be more helpful than upstream since we know the associated file name.\n const firstPass = nodes\n .map((node) => {\n let path = convertDynamicRouteToReactNavigation(node.route);\n\n return [\n node.screenName,\n {\n path: path,\n screens: node.children.length\n ? treeToReactNavigationLinkingRoutes(node.children, [\n ...parents,\n path,\n ])\n : undefined,\n },\n ] as const;\n })\n .reduce<PathConfigMap<{}>>((acc, [screenName, current]) => {\n acc[screenName] = current;\n return acc;\n }, {});\n\n return firstPass;\n}\n\nexport function getLinkingConfig(routes: RouteNode[]): LinkingOptions<{}> {\n return {\n prefixes: [\n /* your linking prefixes */\n Linking.createURL(\"/\"),\n\n // This ensures that we can redirect correctly when the user comes from an associated domain\n // i.e. iOS Safari banner.\n ...getAllWebRedirects(),\n ],\n config: {\n screens: treeToReactNavigationLinkingRoutes(routes),\n },\n getStateFromPath,\n getPathFromState,\n };\n}\n"]}
1
+ {"version":3,"file":"getLinkingConfig.js","sourceRoot":"","sources":["../src/getLinkingConfig.ts"],"names":[],"mappings":"AACA,OAAO,KAAK,OAAO,MAAM,cAAc,CAAC;AAExC,OAAO,EAAE,kBAAkB,EAAE,MAAM,QAAQ,CAAC;AAC5C,OAAO,gBAAgB,MAAM,yBAAyB,CAAC;AACvD,OAAO,gBAAgB,MAAM,yBAAyB,CAAC;AACvD,OAAO,EACL,yBAAyB,EACzB,gBAAgB,EAChB,iBAAiB,GAClB,MAAM,YAAY,CAAC;AAGpB,sBAAsB;AACtB,mBAAmB;AACnB,SAAS,oCAAoC,CAAC,IAAY;IACxD,IAAI,yBAAyB,CAAC,IAAI,CAAC,EAAE;QACnC,OAAO,GAAG,CAAC;KACZ;IACD,MAAM,WAAW,GAAG,gBAAgB,CAAC,IAAI,CAAC,CAAC;IAE3C,IAAI,WAAW,EAAE;QACf,OAAO,IAAI,WAAW,EAAE,CAAC;KAC1B;IAED,IAAI,IAAI,KAAK,OAAO,IAAI,iBAAiB,CAAC,IAAI,CAAC,EAAE;QAC/C,OAAO,EAAE,CAAC;KACX;IAED,OAAO,IAAI,CAAC;AACd,CAAC;AAED,MAAM,UAAU,kCAAkC,CAChD,KAAkB,EAClB,UAAoB,EAAE;IAEtB,kEAAkE;IAClE,yFAAyF;IACzF,MAAM,SAAS,GAAG,KAAK;SACpB,GAAG,CAAC,CAAC,IAAI,EAAE,EAAE;QACZ,MAAM,IAAI,GAAG,oCAAoC,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;QAE9D,IAAI,CAAC,IAAI,CAAC,QAAQ,CAAC,MAAM,EAAE;YACzB,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,IAAI,CAAC,CAAC;SAC3B;QAED,MAAM,OAAO,GAAG,kCAAkC,CAAC,IAAI,CAAC,QAAQ,EAAE;YAChE,GAAG,OAAO;YACV,IAAI;SACL,CAAC,CAAC;QAEH,OAAO,CAAC,IAAI,CAAC,KAAK,EAAE,EAAE,IAAI,EAAE,OAAO,EAAE,CAAU,CAAC;IAClD,CAAC,CAAC;SACD,MAAM,CAAoB,CAAC,GAAG,EAAE,CAAC,KAAK,EAAE,OAAO,CAAC,EAAE,EAAE;QACnD,GAAG,CAAC,KAAK,CAAC,GAAG,OAAO,CAAC;QACrB,OAAO,GAAG,CAAC;IACb,CAAC,EAAE,EAAE,CAAC,CAAC;IAET,OAAO,SAAS,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,gBAAgB,CAAC,MAAmB;IAClD,OAAO;QACL,QAAQ,EAAE;YACR,2BAA2B;YAC3B,OAAO,CAAC,SAAS,CAAC,GAAG,CAAC;YAEtB,4FAA4F;YAC5F,0BAA0B;YAC1B,GAAG,kBAAkB,EAAE;SACxB;QACD,MAAM,EAAE;YACN,OAAO,EAAE,kCAAkC,CAAC,MAAM,CAAC;SACpD;QACD,gBAAgB;QAChB,gBAAgB;KACjB,CAAC;AACJ,CAAC","sourcesContent":["import { LinkingOptions, PathConfigMap } from \"@react-navigation/native\";\nimport * as Linking from \"expo-linking\";\n\nimport { getAllWebRedirects } from \"./aasa\";\nimport getPathFromState from \"./fork/getPathFromState\";\nimport getStateFromPath from \"./fork/getStateFromPath\";\nimport {\n matchDeepDynamicRouteName,\n matchDynamicName,\n matchFragmentName,\n} from \"./matchers\";\nimport { RouteNode } from \"./Route\";\n\n// `[page]` -> `:page`\n// `page` -> `page`\nfunction convertDynamicRouteToReactNavigation(name: string) {\n if (matchDeepDynamicRouteName(name)) {\n return \"*\";\n }\n const dynamicName = matchDynamicName(name);\n\n if (dynamicName) {\n return `:${dynamicName}`;\n }\n\n if (name === \"index\" || matchFragmentName(name)) {\n return \"\";\n }\n\n return name;\n}\n\nexport function treeToReactNavigationLinkingRoutes(\n nodes: RouteNode[],\n parents: string[] = []\n): PathConfigMap<{}> {\n // TODO: Intercept errors, strip invalid routes, and warn instead.\n // Our warnings can be more helpful than upstream since we know the associated file name.\n const firstPass = nodes\n .map((node) => {\n const path = convertDynamicRouteToReactNavigation(node.route);\n\n if (!node.children.length) {\n return [node.route, path];\n }\n\n const screens = treeToReactNavigationLinkingRoutes(node.children, [\n ...parents,\n path,\n ]);\n\n return [node.route, { path, screens }] as const;\n })\n .reduce<PathConfigMap<{}>>((acc, [route, current]) => {\n acc[route] = current;\n return acc;\n }, {});\n\n return firstPass;\n}\n\nexport function getLinkingConfig(routes: RouteNode[]): LinkingOptions<{}> {\n return {\n prefixes: [\n /* your linking prefixes */\n Linking.createURL(\"/\"),\n\n // This ensures that we can redirect correctly when the user comes from an associated domain\n // i.e. iOS Safari banner.\n ...getAllWebRedirects(),\n ],\n config: {\n screens: treeToReactNavigationLinkingRoutes(routes),\n },\n getStateFromPath,\n getPathFromState,\n };\n}\n"]}
@@ -1,9 +1,12 @@
1
1
  import { PickPartial, RouteNode } from "./Route";
2
2
  import { RequireContext } from "./types";
3
- export declare function createRouteNode(route: PickPartial<RouteNode, "screenName" | "dynamic" | "children">): RouteNode;
3
+ export declare function createRouteNode(route: PickPartial<RouteNode, "dynamic" | "children">): RouteNode;
4
+ export declare function generateDynamic(name: string): {
5
+ name: string;
6
+ deep: boolean;
7
+ } | null;
4
8
  /** Given a Metro context module, return an array of nested routes. */
5
9
  export declare function getRoutes(contextModule: RequireContext): RouteNode[];
6
- export declare function recurseAndAddMissingNavigators(routes: RouteNode[], parents: string[]): RouteNode[];
7
10
  /**
8
11
  * Exposed for testing.
9
12
  * @returns a top-level deep dynamic route if it exists, otherwise null.
@@ -1 +1 @@
1
- {"version":3,"file":"getRoutes.d.ts","sourceRoot":"","sources":["../src/getRoutes.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAOzC,wBAAgB,eAAe,CAC7B,KAAK,EAAE,WAAW,CAAC,SAAS,EAAE,YAAY,GAAG,SAAS,GAAG,UAAU,CAAC,GACnE,SAAS,CAOX;AA6CD,sEAAsE;AACtE,wBAAgB,SAAS,CAAC,aAAa,EAAE,cAAc,GAAG,SAAS,EAAE,CAwCpE;AAID,wBAAgB,8BAA8B,CAC5C,MAAM,EAAE,SAAS,EAAE,EACnB,OAAO,EAAE,MAAM,EAAE,GAChB,SAAS,EAAE,CAqBb;AA+CD;;;GAGG;AACH,wBAAgB,8BAA8B,CAC5C,MAAM,EAAE,SAAS,EAAE,GAClB,SAAS,GAAG,IAAI,CAgBlB"}
1
+ {"version":3,"file":"getRoutes.d.ts","sourceRoot":"","sources":["../src/getRoutes.ts"],"names":[],"mappings":"AAMA,OAAO,EAAE,WAAW,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACjD,OAAO,EAAE,cAAc,EAAE,MAAM,SAAS,CAAC;AAGzC,wBAAgB,eAAe,CAC7B,KAAK,EAAE,WAAW,CAAC,SAAS,EAAE,SAAS,GAAG,UAAU,CAAC,GACpD,SAAS,CAMX;AAqDD,wBAAgB,eAAe,CAAC,IAAI,EAAE,MAAM;;;SAK3C;AAoED,sEAAsE;AACtE,wBAAgB,SAAS,CAAC,aAAa,EAAE,cAAc,GAAG,SAAS,EAAE,CAapE;AA+CD;;;GAGG;AACH,wBAAgB,8BAA8B,CAC5C,MAAM,EAAE,SAAS,EAAE,GAClB,SAAS,GAAG,IAAI,CAgBlB"}
@@ -1,62 +1,91 @@
1
1
  import { getNameFromFilePath, matchDeepDynamicRouteName, matchDynamicName, matchFragmentName, } from "./matchers";
2
- import { Children } from "./views/Layout";
3
- function getReactNavigationScreenName(name) {
4
- return matchDeepDynamicRouteName(name) || matchDynamicName(name) || name;
5
- }
2
+ import { DefaultLayout } from "./views/Layout";
6
3
  export function createRouteNode(route) {
7
4
  return {
8
- screenName: getReactNavigationScreenName(route.route),
9
5
  children: [],
10
6
  dynamic: null,
11
7
  ...route,
12
8
  };
13
9
  }
14
- // Recursively convert flat map of file paths to tree
15
- function convert(files) {
16
- const tree = {};
10
+ /** Convert a flat map of file nodes into a nested tree of files. */
11
+ function getRecursiveTree(files) {
12
+ const tree = {
13
+ name: "",
14
+ children: [],
15
+ parents: [],
16
+ node: null,
17
+ };
17
18
  for (const file of files) {
19
+ // ['(tab)', 'settings', '[...another]']
18
20
  const parts = file.normalizedName.split("/");
19
- let current = tree;
21
+ let currentNode = tree;
20
22
  for (const part of parts) {
21
- current = current[part] = current[part] || {};
23
+ const existing = currentNode.children.find((item) => item.name === part);
24
+ if (existing) {
25
+ currentNode = existing;
26
+ }
27
+ else {
28
+ const newNode = {
29
+ name: part,
30
+ children: [],
31
+ parents: [...currentNode.parents, currentNode.name],
32
+ node: null,
33
+ };
34
+ currentNode.children.push(newNode);
35
+ currentNode = newNode;
36
+ }
22
37
  }
23
- // @ts-expect-error
24
- current.___child = file;
38
+ currentNode.node = file;
25
39
  }
26
- const toNodeArray = (tree) => {
27
- const out = [];
28
- // @ts-expect-error
29
- for (const [key, { ___child, ...obj }] of Object.entries(tree)) {
30
- const deepDynamicName = matchDeepDynamicRouteName(key);
31
- const dynamicName = deepDynamicName ?? matchDynamicName(key);
32
- out.push(createRouteNode({
33
- route: key,
34
- getExtras: ___child?.getExtras,
35
- getComponent: ___child?.getComponent,
36
- contextKey: ___child?.contextKey,
37
- children: toNodeArray(obj),
38
- dynamic: dynamicName
39
- ? { name: dynamicName, deep: !!deepDynamicName }
40
- : null,
41
- }));
42
- }
43
- return out;
44
- };
45
- return toNodeArray(tree);
40
+ return tree;
46
41
  }
47
- /** Given a Metro context module, return an array of nested routes. */
48
- export function getRoutes(contextModule) {
49
- const names = contextModule
50
- .keys()
51
- .map((key) => {
52
- if (process.env.NODE_ENV === "development") {
53
- // In development, check if the file exports a default component
54
- // this helps keep things snappy when creating files. In production we load all screens lazily.
55
- if (!contextModule(key)?.default) {
56
- return null;
57
- }
42
+ function getTreeNodesAsRouteNodes(nodes) {
43
+ return nodes.map(treeNodeToRouteNode).filter(Boolean);
44
+ }
45
+ export function generateDynamic(name) {
46
+ const deepDynamicName = matchDeepDynamicRouteName(name);
47
+ const dynamicName = deepDynamicName ?? matchDynamicName(name);
48
+ return dynamicName ? { name: dynamicName, deep: !!deepDynamicName } : null;
49
+ }
50
+ function treeNodeToRouteNode({ name, node, parents, children, }) {
51
+ const dynamic = generateDynamic(name);
52
+ if (node) {
53
+ return createRouteNode({
54
+ route: name,
55
+ getExtras: node.getExtras,
56
+ getComponent: node.getComponent,
57
+ contextKey: node.contextKey,
58
+ children: getTreeNodesAsRouteNodes(children),
59
+ dynamic,
60
+ });
61
+ }
62
+ // Empty folder, skip it.
63
+ if (!children.length) {
64
+ return null;
65
+ }
66
+ // When there's a directory, but no sibling file with the same name, the directory won't work.
67
+ // This ensures that we have a file for every directory (containing valid children).
68
+ return createRouteNode({
69
+ route: name,
70
+ generated: true,
71
+ getExtras: () => ({}),
72
+ getComponent: () => DefaultLayout,
73
+ // Generate a fake file name for the directory
74
+ contextKey: [".", ...parents, name + ".tsx"].filter(Boolean).join("/"),
75
+ children: getTreeNodesAsRouteNodes(children),
76
+ dynamic,
77
+ });
78
+ }
79
+ function contextModuleToFileNodes(contextModule) {
80
+ const nodes = contextModule.keys().map((key) => {
81
+ // if (process.env.NODE_ENV === "development") {
82
+ // In development, check if the file exports a default component
83
+ // this helps keep things snappy when creating files. In production we load all screens lazily.
84
+ if (!contextModule(key)?.default) {
85
+ return null;
58
86
  }
59
- return {
87
+ // }
88
+ const node = {
60
89
  normalizedName: getNameFromFilePath(key),
61
90
  getComponent() {
62
91
  return contextModule(key).default;
@@ -67,12 +96,15 @@ export function getRoutes(contextModule) {
67
96
  return extras;
68
97
  },
69
98
  };
70
- })
71
- .filter((node) => node);
72
- // @ts-expect-error
73
- const routes = convert(names);
74
- // Add all missing navigators
75
- recurseAndAddMissingNavigators(routes, []);
99
+ return node;
100
+ });
101
+ return nodes.filter(Boolean);
102
+ }
103
+ /** Given a Metro context module, return an array of nested routes. */
104
+ export function getRoutes(contextModule) {
105
+ const files = contextModuleToFileNodes(contextModule);
106
+ const treeNodes = getRecursiveTree(files).children;
107
+ const routes = getTreeNodesAsRouteNodes(treeNodes);
76
108
  if (process.env.NODE_ENV !== "production") {
77
109
  appendDirectoryRoute(routes);
78
110
  }
@@ -80,28 +112,6 @@ export function getRoutes(contextModule) {
80
112
  appendUnmatchedRoute(routes);
81
113
  return routes;
82
114
  }
83
- // When there's a directory, but no sibling file with the same name, the directory won't work.
84
- // This method ensures that we have a file for every directory (containing valid children).
85
- export function recurseAndAddMissingNavigators(routes, parents) {
86
- routes.forEach((route) => {
87
- // Route has children but no component and no contextKey (meaning no file path).
88
- if (route.children.length && route.contextKey == null) {
89
- route.getComponent = () => Children;
90
- route.generated = true;
91
- route.getExtras = () => ({});
92
- route.contextKey = [".", ...parents, route.route + ".tsx"]
93
- .filter(Boolean)
94
- .join("/");
95
- // TODO: Handle if the directory is dynamic.
96
- }
97
- route.children = recurseAndAddMissingNavigators(route.children, [
98
- ...parents,
99
- route.route,
100
- ]);
101
- return route;
102
- });
103
- return routes;
104
- }
105
115
  function appendDirectoryRoute(routes) {
106
116
  if (!routes.length) {
107
117
  return routes;
@@ -1 +1 @@
1
- {"version":3,"file":"getRoutes.js","sourceRoot":"","sources":["../src/getRoutes.ts"],"names":[],"mappings":"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","sourcesContent":["import {\n getNameFromFilePath,\n matchDeepDynamicRouteName,\n matchDynamicName,\n matchFragmentName,\n} from \"./matchers\";\nimport { PickPartial, RouteNode } from \"./Route\";\nimport { RequireContext } from \"./types\";\nimport { Children } from \"./views/Layout\";\n\nfunction getReactNavigationScreenName(name: string) {\n return matchDeepDynamicRouteName(name) || matchDynamicName(name) || name;\n}\n\nexport function createRouteNode(\n route: PickPartial<RouteNode, \"screenName\" | \"dynamic\" | \"children\">\n): RouteNode {\n return {\n screenName: getReactNavigationScreenName(route.route),\n children: [],\n dynamic: null,\n ...route,\n };\n}\n\n// Recursively convert flat map of file paths to tree\nfunction convert(\n files: (Pick<RouteNode, \"contextKey\" | \"getComponent\" | \"getExtras\"> & {\n normalizedName: string;\n })[]\n): RouteNode[] {\n const tree = {};\n for (const file of files) {\n const parts = file.normalizedName.split(\"/\");\n let current = tree;\n for (const part of parts) {\n current = current[part] = current[part] || {};\n }\n // @ts-expect-error\n current.___child = file;\n }\n\n const toNodeArray = (tree): RouteNode[] => {\n const out: RouteNode[] = [];\n // @ts-expect-error\n for (const [key, { ___child, ...obj }] of Object.entries(tree)) {\n const deepDynamicName = matchDeepDynamicRouteName(key);\n const dynamicName = deepDynamicName ?? matchDynamicName(key);\n\n out.push(\n createRouteNode({\n route: key,\n getExtras: ___child?.getExtras,\n getComponent: ___child?.getComponent,\n contextKey: ___child?.contextKey,\n children: toNodeArray(obj),\n dynamic: dynamicName\n ? { name: dynamicName, deep: !!deepDynamicName }\n : null,\n })\n );\n }\n return out;\n };\n\n return toNodeArray(tree);\n}\n\n/** Given a Metro context module, return an array of nested routes. */\nexport function getRoutes(contextModule: RequireContext): RouteNode[] {\n const names = contextModule\n .keys()\n .map((key) => {\n if (process.env.NODE_ENV === \"development\") {\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 if (!contextModule(key)?.default) {\n return null;\n }\n }\n\n return {\n normalizedName: getNameFromFilePath(key),\n getComponent() {\n return contextModule(key).default;\n },\n contextKey: key,\n getExtras() {\n const { default: mod, ...extras } = contextModule(key);\n return extras;\n },\n };\n })\n .filter((node) => node);\n\n // @ts-expect-error\n const routes = convert(names);\n\n // Add all missing navigators\n recurseAndAddMissingNavigators(routes, []);\n\n if (process.env.NODE_ENV !== \"production\") {\n appendDirectoryRoute(routes);\n }\n\n // Auto add not found route if it doesn't exist\n appendUnmatchedRoute(routes);\n\n return routes;\n}\n\n// When there's a directory, but no sibling file with the same name, the directory won't work.\n// This method ensures that we have a file for every directory (containing valid children).\nexport function recurseAndAddMissingNavigators(\n routes: RouteNode[],\n parents: string[]\n): RouteNode[] {\n routes.forEach((route) => {\n // Route has children but no component and no contextKey (meaning no file path).\n if (route.children.length && route.contextKey == null) {\n route.getComponent = () => Children;\n route.generated = true;\n route.getExtras = () => ({});\n route.contextKey = [\".\", ...parents, route.route + \".tsx\"]\n .filter(Boolean)\n .join(\"/\");\n // TODO: Handle if the directory is dynamic.\n }\n\n route.children = recurseAndAddMissingNavigators(route.children, [\n ...parents,\n route.route,\n ]);\n return route;\n });\n\n return routes;\n}\n\nfunction appendDirectoryRoute(routes: RouteNode[]) {\n if (!routes.length) {\n return routes;\n }\n const { Directory, getNavOptions } = require(\"./views/Directory\");\n routes.push(\n createRouteNode({\n getComponent() {\n return Directory;\n },\n getExtras() {\n return { getNavOptions };\n },\n route: \"__index\",\n contextKey: \"./__index.tsx\",\n generated: true,\n internal: true,\n })\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.push(\n createRouteNode({\n getComponent() {\n return require(\"./views/Unmatched\").Unmatched;\n },\n getExtras() {\n return {};\n },\n route: \"[...404]\",\n contextKey: \"./[...404].tsx\",\n dynamic: { name: \"404\", deep: true },\n generated: true,\n internal: true,\n })\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) {\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.children);\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 {\n getNameFromFilePath,\n matchDeepDynamicRouteName,\n matchDynamicName,\n matchFragmentName,\n} from \"./matchers\";\nimport { PickPartial, RouteNode } from \"./Route\";\nimport { RequireContext } from \"./types\";\nimport { DefaultLayout } from \"./views/Layout\";\n\nexport function createRouteNode(\n route: PickPartial<RouteNode, \"dynamic\" | \"children\">\n): RouteNode {\n return {\n children: [],\n dynamic: null,\n ...route,\n };\n}\n\ntype FileNode = Pick<RouteNode, \"contextKey\" | \"getComponent\" | \"getExtras\"> & {\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. */\nfunction 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 (const part of parts) {\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 return tree;\n}\n\nfunction getTreeNodesAsRouteNodes(nodes: TreeNode[]): RouteNode[] {\n return nodes.map(treeNodeToRouteNode).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 treeNodeToRouteNode({\n name,\n node,\n parents,\n children,\n}: TreeNode): RouteNode | null {\n const dynamic = generateDynamic(name);\n\n if (node) {\n return createRouteNode({\n route: name,\n getExtras: node.getExtras,\n getComponent: node.getComponent,\n contextKey: node.contextKey,\n children: getTreeNodesAsRouteNodes(children),\n dynamic,\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 sibling file with the same name, the directory won't work.\n // This ensures that we have a file for every directory (containing valid children).\n return createRouteNode({\n route: name,\n generated: true,\n getExtras: () => ({}),\n getComponent: () => DefaultLayout,\n // Generate a fake file name for the directory\n contextKey: [\".\", ...parents, name + \".tsx\"].filter(Boolean).join(\"/\"),\n children: getTreeNodesAsRouteNodes(children),\n dynamic,\n });\n}\n\nfunction contextModuleToFileNodes(contextModule: RequireContext): FileNode[] {\n const nodes = contextModule.keys().map((key) => {\n // if (process.env.NODE_ENV === \"development\") {\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 if (!contextModule(key)?.default) {\n return null;\n }\n // }\n\n const node: FileNode = {\n normalizedName: getNameFromFilePath(key),\n getComponent() {\n return contextModule(key).default;\n },\n contextKey: key,\n getExtras() {\n const { default: mod, ...extras } = contextModule(key);\n return extras;\n },\n };\n\n return node;\n });\n\n return nodes.filter(Boolean) as FileNode[];\n}\n\n/** Given a Metro context module, return an array of nested routes. */\nexport function getRoutes(contextModule: RequireContext): RouteNode[] {\n const files = contextModuleToFileNodes(contextModule);\n const treeNodes = getRecursiveTree(files).children;\n const routes = getTreeNodesAsRouteNodes(treeNodes);\n\n if (process.env.NODE_ENV !== \"production\") {\n appendDirectoryRoute(routes);\n }\n\n // Auto add not found route if it doesn't exist\n appendUnmatchedRoute(routes);\n\n return routes;\n}\n\nfunction appendDirectoryRoute(routes: RouteNode[]) {\n if (!routes.length) {\n return routes;\n }\n const { Directory, getNavOptions } = require(\"./views/Directory\");\n routes.push(\n createRouteNode({\n getComponent() {\n return Directory;\n },\n getExtras() {\n return { getNavOptions };\n },\n route: \"__index\",\n contextKey: \"./__index.tsx\",\n generated: true,\n internal: true,\n })\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.push(\n createRouteNode({\n getComponent() {\n return require(\"./views/Unmatched\").Unmatched;\n },\n getExtras() {\n return {};\n },\n route: \"[...404]\",\n contextKey: \"./[...404].tsx\",\n dynamic: { name: \"404\", deep: true },\n generated: true,\n internal: true,\n })\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) {\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.children);\n if (child) {\n return child;\n }\n }\n }\n return null;\n}\n"]}
package/build/index.d.ts CHANGED
@@ -1,10 +1,11 @@
1
1
  export { useRoutes } from "./Route";
2
- export { useScreens, useScreensRecord } from "./useScreens";
2
+ export { useScreens } from "./useScreens";
3
3
  export { ErrorBoundaryProps } from "./views/Try";
4
4
  export { Stack } from "./layouts/Stack";
5
5
  export { NativeStack } from "./layouts/NativeStack";
6
6
  export { Tabs } from "./layouts/Tabs";
7
7
  export { Drawer } from "./layouts/Drawer";
8
+ export { withLayoutContext } from "./layouts/withLayoutContext";
8
9
  export { ExpoRoot } from "./views/Root";
9
10
  export { Unmatched } from "./views/Unmatched";
10
11
  export { ErrorBoundary } from "./views/ErrorBoundary";
@@ -1 +1 @@
1
- {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAE5D,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEjD,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AACtC,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE1C,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAEtD,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,6BAA6B,EAAE,MAAM,8BAA8B,CAAC"}
1
+ {"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAE1C,OAAO,EAAE,kBAAkB,EAAE,MAAM,aAAa,CAAC;AAEjD,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AACtC,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAEhE,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAEtD,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,6BAA6B,EAAE,MAAM,8BAA8B,CAAC"}
package/build/index.js CHANGED
@@ -1,9 +1,10 @@
1
1
  export { useRoutes } from "./Route";
2
- export { useScreens, useScreensRecord } from "./useScreens";
2
+ export { useScreens } from "./useScreens";
3
3
  export { Stack } from "./layouts/Stack";
4
4
  export { NativeStack } from "./layouts/NativeStack";
5
5
  export { Tabs } from "./layouts/Tabs";
6
6
  export { Drawer } from "./layouts/Drawer";
7
+ export { withLayoutContext } from "./layouts/withLayoutContext";
7
8
  export { ExpoRoot } from "./views/Root";
8
9
  export { Unmatched } from "./views/Unmatched";
9
10
  export { ErrorBoundary } from "./views/ErrorBoundary";
@@ -1 +1 @@
1
- {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,gBAAgB,EAAE,MAAM,cAAc,CAAC;AAI5D,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AACtC,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAE1C,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAEtD,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,6BAA6B,EAAE,MAAM,8BAA8B,CAAC","sourcesContent":["export { useRoutes } from \"./Route\";\nexport { useScreens, useScreensRecord } from \"./useScreens\";\n\nexport { ErrorBoundaryProps } from \"./views/Try\";\n\nexport { Stack } from \"./layouts/Stack\";\nexport { NativeStack } from \"./layouts/NativeStack\";\nexport { Tabs } from \"./layouts/Tabs\";\nexport { Drawer } from \"./layouts/Drawer\";\n\nexport { ExpoRoot } from \"./views/Root\";\nexport { Unmatched } from \"./views/Unmatched\";\nexport { ErrorBoundary } from \"./views/ErrorBoundary\";\n\nexport { Layout, Children } from \"./views/Layout\";\nexport { Link } from \"./views/Link\";\nexport { RootContainer, useNavigationContainerContext } from \"./ContextNavigationContainer\";\n"]}
1
+ {"version":3,"file":"index.js","sourceRoot":"","sources":["../src/index.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,MAAM,SAAS,CAAC;AACpC,OAAO,EAAE,UAAU,EAAE,MAAM,cAAc,CAAC;AAI1C,OAAO,EAAE,KAAK,EAAE,MAAM,iBAAiB,CAAC;AACxC,OAAO,EAAE,WAAW,EAAE,MAAM,uBAAuB,CAAC;AACpD,OAAO,EAAE,IAAI,EAAE,MAAM,gBAAgB,CAAC;AACtC,OAAO,EAAE,MAAM,EAAE,MAAM,kBAAkB,CAAC;AAC1C,OAAO,EAAE,iBAAiB,EAAE,MAAM,6BAA6B,CAAC;AAEhE,OAAO,EAAE,QAAQ,EAAE,MAAM,cAAc,CAAC;AACxC,OAAO,EAAE,SAAS,EAAE,MAAM,mBAAmB,CAAC;AAC9C,OAAO,EAAE,aAAa,EAAE,MAAM,uBAAuB,CAAC;AAEtD,OAAO,EAAE,MAAM,EAAE,QAAQ,EAAE,MAAM,gBAAgB,CAAC;AAClD,OAAO,EAAE,IAAI,EAAE,MAAM,cAAc,CAAC;AACpC,OAAO,EAAE,aAAa,EAAE,6BAA6B,EAAE,MAAM,8BAA8B,CAAC","sourcesContent":["export { useRoutes } from \"./Route\";\nexport { useScreens } from \"./useScreens\";\n\nexport { ErrorBoundaryProps } from \"./views/Try\";\n\nexport { Stack } from \"./layouts/Stack\";\nexport { NativeStack } from \"./layouts/NativeStack\";\nexport { Tabs } from \"./layouts/Tabs\";\nexport { Drawer } from \"./layouts/Drawer\";\nexport { withLayoutContext } from \"./layouts/withLayoutContext\";\n\nexport { ExpoRoot } from \"./views/Root\";\nexport { Unmatched } from \"./views/Unmatched\";\nexport { ErrorBoundary } from \"./views/ErrorBoundary\";\n\nexport { Layout, Children } from \"./views/Layout\";\nexport { Link } from \"./views/Link\";\nexport { RootContainer, useNavigationContainerContext } from \"./ContextNavigationContainer\";\n"]}
@@ -1 +1 @@
1
- {"version":3,"file":"withLayoutContext.d.ts","sourceRoot":"","sources":["../../src/layouts/withLayoutContext.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAK1B,aAAK,WAAW,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,CAAC,IAAI,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,GAC/C,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AAExB,aAAK,WAAW,CAAC,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,IAAI;IAC3E,4DAA4D;IAC5D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;KAAE,CAAC;IACvC,OAAO,CAAC,EAAE,QAAQ,CAAC;CACtB,CAAA;AA+BD,2JAA2J;AAC3J,wBAAgB,iBAAiB,CAAC,QAAQ,SAAS,EAAE,EAAE,CAAC,SAAS,KAAK,CAAC,aAAa,CAAC,GAAG,CAAC,EACrF,GAAG,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,yBAAyB,CAAC,KAAK,CAAC,eAAe,CAAC,WAAW,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,GAAG,KAAK,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG;IACjJ,MAAM,EAAE,CAAC,KAAK,EAAE,WAAW,CAAC,QAAQ,CAAC,KAAK,IAAI,CAAA;CACjD,CAiDJ"}
1
+ {"version":3,"file":"withLayoutContext.d.ts","sourceRoot":"","sources":["../../src/layouts/withLayoutContext.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAK1B,aAAK,WAAW,CAAC,CAAC,EAAE,CAAC,SAAS,MAAM,CAAC,IAAI,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,GAC/C,OAAO,CAAC,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC,CAAC;AAExB,aAAK,WAAW,CAAC,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,IAAI;IAC3E,4DAA4D;IAC5D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;KAAE,CAAC;IACvC,OAAO,CAAC,EAAE,QAAQ,CAAC;CACtB,CAAA;AAED,2JAA2J;AAC3J,wBAAgB,iBAAiB,CAAC,QAAQ,SAAS,EAAE,EAAE,CAAC,SAAS,KAAK,CAAC,aAAa,CAAC,GAAG,CAAC,EACrF,GAAG,EAAE,CAAC,GAAG,CAAC,KAAK,CAAC,yBAAyB,CAAC,KAAK,CAAC,eAAe,CAAC,WAAW,CAAC,KAAK,CAAC,cAAc,CAAC,CAAC,CAAC,EAAE,UAAU,CAAC,CAAC,GAAG,KAAK,CAAC,aAAa,CAAC,OAAO,CAAC,CAAC,CAAC,GAAG;IACjJ,MAAM,EAAE,CAAC,KAAK,EAAE,WAAW,CAAC,QAAQ,CAAC,KAAK,IAAI,CAAA;CACjD,CA8CJ"}
@@ -1,32 +1,6 @@
1
1
  import React from 'react';
2
- import { useScreensRecord } from '../useScreens';
2
+ import { useSortedScreens } from '../useScreens';
3
3
  import { Screen } from '../views/Screen';
4
- function useSortedChildren(children, order) {
5
- return React.useMemo(() => {
6
- if (!order?.length) {
7
- return Object.values(children);
8
- }
9
- const entries = Object.entries(children);
10
- const ordered = order.map(({ name, initialParams, options }) => {
11
- const matchIndex = entries.findIndex((child) => child[0] === name);
12
- if (matchIndex === -1) {
13
- console.warn(`[Layout children]: No route named "${name}" exists in nested children:`, Object.keys(children));
14
- return null;
15
- }
16
- else {
17
- // Get match and remove from entries
18
- const [, match] = entries[matchIndex];
19
- entries.splice(matchIndex, 1);
20
- // @ts-expect-error
21
- return React.cloneElement(match, { initialParams, options });
22
- }
23
- }).filter(Boolean);
24
- // Add any remaining children
25
- // @ts-expect-error
26
- ordered.push(...entries.map(([, child]) => child));
27
- return ordered;
28
- }, [children, order]);
29
- }
30
4
  /** Return a navigator that automatically injects matched routes and renders nothing when there are no children. Return type with children prop optional */
31
5
  export function withLayoutContext(Nav) {
32
6
  const Navigator = React.forwardRef(({ children: userDefinedChildren, ...props }, ref) => {
@@ -56,8 +30,7 @@ export function withLayoutContext(Nav) {
56
30
  }
57
31
  return screens;
58
32
  }, [userDefinedChildren]);
59
- const children = useScreensRecord();
60
- const sorted = useSortedChildren(children, userDefinedOptions);
33
+ const sorted = useSortedScreens(userDefinedOptions ?? []);
61
34
  // Prevent throwing an error when there are no screens.
62
35
  if (!sorted.length) {
63
36
  return null;
@@ -1 +1 @@
1
- {"version":3,"file":"withLayoutContext.js","sourceRoot":"","sources":["../../src/layouts/withLayoutContext.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAYzC,SAAS,iBAAiB,CAAC,QAAyC,EAAE,KAAqB;IACvF,OAAO,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE;QACtB,IAAI,CAAC,KAAK,EAAE,MAAM,EAAE;YAChB,OAAO,MAAM,CAAC,MAAM,CAAC,QAAQ,CAAC,CAAC;SAClC;QACD,MAAM,OAAO,GAAG,MAAM,CAAC,OAAO,CAAC,QAAQ,CAAC,CAAC;QAEzC,MAAM,OAAO,GAAG,KAAK,CAAC,GAAG,CAAC,CAAC,EAAE,IAAI,EAAE,aAAa,EAAE,OAAO,EAAE,EAAE,EAAE;YAC3D,MAAM,UAAU,GAAG,OAAO,CAAC,SAAS,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC,KAAK,IAAI,CAAC,CAAA;YAClE,IAAI,UAAU,KAAK,CAAC,CAAC,EAAE;gBACnB,OAAO,CAAC,IAAI,CAAC,sCAAsC,IAAI,8BAA8B,EAAE,MAAM,CAAC,IAAI,CAAC,QAAQ,CAAC,CAAC,CAAC;gBAC9G,OAAO,IAAI,CAAC;aACf;iBAAM;gBACH,oCAAoC;gBACpC,MAAM,CAAC,EAAE,KAAK,CAAC,GAAG,OAAO,CAAC,UAAU,CAAC,CAAC;gBACtC,OAAO,CAAC,MAAM,CAAC,UAAU,EAAE,CAAC,CAAC,CAAC;gBAC9B,mBAAmB;gBACnB,OAAO,KAAK,CAAC,YAAY,CAAC,KAAK,EAAE,EAAE,aAAa,EAAE,OAAO,EAAE,CAAC,CAAC;aAChE;QACL,CAAC,CAAC,CAAC,MAAM,CAAC,OAAO,CAAC,CAAA;QAElB,6BAA6B;QAC7B,mBAAmB;QACnB,OAAO,CAAC,IAAI,CAAC,GAAG,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,KAAK,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,CAAC,CAAC;QAEnD,OAAO,OAAO,CAAC;IACnB,CAAC,EAAE,CAAC,QAAQ,EAAE,KAAK,CAAC,CAAC,CAAC;AAC1B,CAAC;AAED,2JAA2J;AAC3J,MAAM,UAAU,iBAAiB,CAC7B,GAAM;IAKN,MAAM,SAAS,GAAG,KAAK,CAAC,UAAU,CAAC,CAAC,EAAE,QAAQ,EAAE,mBAAmB,EAAE,GAAG,KAAK,EAAoD,EAAE,GAAG,EAAE,EAAE;QACtI,MAAM,kBAAkB,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE;YAC1C,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,mBAAmB,EAAE,CAAC,KAAK,EAAE,EAAE;gBAC9D,IAAI,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,EAAE;oBAC/D,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE;wBACnB,MAAM,IAAI,KAAK,CAAC,+DAA+D,CAAC,CAAC;qBACpF;oBACD,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,EAAE;wBACvC,IAAI,CAAC,UAAU,EAAE,WAAW,EAAE,cAAc,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,IAAI,KAAK,CAAC,KAAK,CAAC,EAAE;4BAC7E,MAAM,IAAI,KAAK,CAAC,mGAAmG,CAAC,CAAC;yBACxH;qBACJ;oBACD,OAAO,KAAK,CAAC,KAAK,CAAC;iBACtB;qBAAM;oBACH,OAAO,CAAC,IAAI,CAAC,6HAA6H,CAAC,CAAC;iBAC/I;YACL,CAAC,CAAC,CAAA;YAEF,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,EAAE;gBACvC,iCAAiC;gBACjC,MAAM,KAAK,GAAG,OAAO,EAAE,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;gBACpD,IAAI,KAAK,IAAI,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,KAAK,KAAK,CAAC,MAAM,EAAE;oBAC/C,MAAM,IAAI,KAAK,CAAC,+BAA+B,GAAG,KAAK,CAAC,CAAC;iBAC5D;aACJ;YAED,OAAO,OAAO,CAAC;QACnB,CAAC,EAAE,CAAC,mBAAmB,CAAC,CAAC,CAAC;QAE1B,MAAM,QAAQ,GAAG,gBAAgB,EAAE,CAAC;QAEpC,MAAM,MAAM,GAAG,iBAAiB,CAAC,QAAQ,EAAE,kBAAkB,CAAC,CAAC;QAE/D,uDAAuD;QACvD,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE;YAChB,OAAO,IAAI,CAAC;SACf;QAED,mBAAmB;QACnB,OAAO,oBAAC,GAAG,OAAK,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,GAAI,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,mBAAmB;IACnB,SAAS,CAAC,MAAM,GAAG,MAAM,CAAC;IAC1B,mBAAmB;IACnB,OAAO,SAAS,CAAC;AACrB,CAAC","sourcesContent":["import React from 'react';\n\nimport { useScreensRecord } from '../useScreens';\nimport { Screen } from '../views/Screen';\n\ntype PickPartial<T, K extends keyof T> = Omit<T, K> &\n Partial<Pick<T, K>>;\n\ntype ScreenProps<TOptions extends Record<string, any> = Record<string, any>> = {\n /** Name is required when used inside a Layout component. */\n name?: string,\n initialParams?: { [key: string]: any };\n options?: TOptions;\n}\n\nfunction useSortedChildren(children: Record<string, React.ReactNode>, order?: ScreenProps[]): React.ReactNode[] {\n return React.useMemo(() => {\n if (!order?.length) {\n return Object.values(children);\n }\n const entries = Object.entries(children);\n\n const ordered = order.map(({ name, initialParams, options }) => {\n const matchIndex = entries.findIndex((child) => child[0] === name)\n if (matchIndex === -1) {\n console.warn(`[Layout children]: No route named \"${name}\" exists in nested children:`, Object.keys(children));\n return null;\n } else {\n // Get match and remove from entries\n const [, match] = entries[matchIndex];\n entries.splice(matchIndex, 1);\n // @ts-expect-error\n return React.cloneElement(match, { initialParams, options });\n }\n }).filter(Boolean)\n\n // Add any remaining children\n // @ts-expect-error\n ordered.push(...entries.map(([, child]) => child));\n\n return ordered;\n }, [children, order]);\n}\n\n/** Return a navigator that automatically injects matched routes and renders nothing when there are no children. Return type with children prop optional */\nexport function withLayoutContext<TOptions extends {}, T extends React.ComponentType<any>>(\n Nav: T): (React.ForwardRefExoticComponent<React.PropsWithoutRef<PickPartial<React.ComponentProps<T>, \"children\">> & React.RefAttributes<unknown>>) & {\n Screen: (props: ScreenProps<TOptions>) => null\n } {\n\n\n const Navigator = React.forwardRef(({ children: userDefinedChildren, ...props }: PickPartial<React.ComponentProps<T>, 'children'>, ref) => {\n const userDefinedOptions = React.useMemo(() => {\n const screens = React.Children.map(userDefinedChildren, (child) => {\n if (React.isValidElement(child) && child && child.type === Screen) {\n if (!child.props.name) {\n throw new Error('Screen must have a name prop when used as a child of a Layout');\n }\n if (process.env.NODE_ENV !== 'production') {\n if (['children', 'component', 'getComponent'].some((key) => key in child.props)) {\n throw new Error('Screen must not have a children, component, or getComponent prop when used as a child of a Layout');\n }\n }\n return child.props;\n } else {\n console.warn('Layout children must be of type Screen, all other children are ignored. To use custom children, create a custom <Layout />.');\n }\n })\n\n if (process.env.NODE_ENV !== 'production') {\n // Assert if names are not unique\n const names = screens?.map((screen) => screen.name);\n if (names && new Set(names).size !== names.length) {\n throw new Error('Screen names must be unique: ' + names);\n }\n }\n\n return screens;\n }, [userDefinedChildren]);\n\n const children = useScreensRecord();\n\n const sorted = useSortedChildren(children, userDefinedOptions);\n\n // Prevent throwing an error when there are no screens.\n if (!sorted.length) {\n return null;\n }\n\n // @ts-expect-error\n return <Nav {...props} ref={ref} children={sorted} />;\n });\n\n // @ts-expect-error\n Navigator.Screen = Screen;\n // @ts-expect-error\n return Navigator;\n}\n"]}
1
+ {"version":3,"file":"withLayoutContext.js","sourceRoot":"","sources":["../../src/layouts/withLayoutContext.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,gBAAgB,EAAE,MAAM,eAAe,CAAC;AACjD,OAAO,EAAE,MAAM,EAAE,MAAM,iBAAiB,CAAC;AAYzC,2JAA2J;AAC3J,MAAM,UAAU,iBAAiB,CAC7B,GAAM;IAIN,MAAM,SAAS,GAAG,KAAK,CAAC,UAAU,CAAC,CAAC,EAAE,QAAQ,EAAE,mBAAmB,EAAE,GAAG,KAAK,EAAoD,EAAE,GAAG,EAAE,EAAE;QACtI,MAAM,kBAAkB,GAAG,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE;YAC1C,MAAM,OAAO,GAAG,KAAK,CAAC,QAAQ,CAAC,GAAG,CAAC,mBAAmB,EAAE,CAAC,KAAK,EAAE,EAAE;gBAC9D,IAAI,KAAK,CAAC,cAAc,CAAC,KAAK,CAAC,IAAI,KAAK,IAAI,KAAK,CAAC,IAAI,KAAK,MAAM,EAAE;oBAC/D,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,IAAI,EAAE;wBACnB,MAAM,IAAI,KAAK,CAAC,+DAA+D,CAAC,CAAC;qBACpF;oBACD,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,EAAE;wBACvC,IAAI,CAAC,UAAU,EAAE,WAAW,EAAE,cAAc,CAAC,CAAC,IAAI,CAAC,CAAC,GAAG,EAAE,EAAE,CAAC,GAAG,IAAI,KAAK,CAAC,KAAK,CAAC,EAAE;4BAC7E,MAAM,IAAI,KAAK,CAAC,mGAAmG,CAAC,CAAC;yBACxH;qBACJ;oBACD,OAAO,KAAK,CAAC,KAAK,CAAC;iBACtB;qBAAM;oBACH,OAAO,CAAC,IAAI,CAAC,6HAA6H,CAAC,CAAC;iBAC/I;YACL,CAAC,CAAC,CAAA;YAEF,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,EAAE;gBACvC,iCAAiC;gBACjC,MAAM,KAAK,GAAG,OAAO,EAAE,GAAG,CAAC,CAAC,MAAM,EAAE,EAAE,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC;gBACpD,IAAI,KAAK,IAAI,IAAI,GAAG,CAAC,KAAK,CAAC,CAAC,IAAI,KAAK,KAAK,CAAC,MAAM,EAAE;oBAC/C,MAAM,IAAI,KAAK,CAAC,+BAA+B,GAAG,KAAK,CAAC,CAAC;iBAC5D;aACJ;YAED,OAAO,OAAO,CAAC;QACnB,CAAC,EAAE,CAAC,mBAAmB,CAAC,CAAC,CAAC;QAE1B,MAAM,MAAM,GAAG,gBAAgB,CAAC,kBAAkB,IAAI,EAAE,CAAC,CAAC;QAE1D,uDAAuD;QACvD,IAAI,CAAC,MAAM,CAAC,MAAM,EAAE;YAChB,OAAO,IAAI,CAAC;SACf;QAED,mBAAmB;QACnB,OAAO,oBAAC,GAAG,OAAK,KAAK,EAAE,GAAG,EAAE,GAAG,EAAE,QAAQ,EAAE,MAAM,GAAI,CAAC;IAC1D,CAAC,CAAC,CAAC;IAEH,mBAAmB;IACnB,SAAS,CAAC,MAAM,GAAG,MAAM,CAAC;IAC1B,mBAAmB;IACnB,OAAO,SAAS,CAAC;AACrB,CAAC","sourcesContent":["import React from 'react';\n\nimport { useSortedScreens } from '../useScreens';\nimport { Screen } from '../views/Screen';\n\ntype PickPartial<T, K extends keyof T> = Omit<T, K> &\n Partial<Pick<T, K>>;\n\ntype ScreenProps<TOptions extends Record<string, any> = Record<string, any>> = {\n /** Name is required when used inside a Layout component. */\n name?: string,\n initialParams?: { [key: string]: any };\n options?: TOptions;\n}\n\n/** Return a navigator that automatically injects matched routes and renders nothing when there are no children. Return type with children prop optional */\nexport function withLayoutContext<TOptions extends {}, T extends React.ComponentType<any>>(\n Nav: T): (React.ForwardRefExoticComponent<React.PropsWithoutRef<PickPartial<React.ComponentProps<T>, \"children\">> & React.RefAttributes<unknown>>) & {\n Screen: (props: ScreenProps<TOptions>) => null\n } {\n\n const Navigator = React.forwardRef(({ children: userDefinedChildren, ...props }: PickPartial<React.ComponentProps<T>, 'children'>, ref) => {\n const userDefinedOptions = React.useMemo(() => {\n const screens = React.Children.map(userDefinedChildren, (child) => {\n if (React.isValidElement(child) && child && child.type === Screen) {\n if (!child.props.name) {\n throw new Error('Screen must have a name prop when used as a child of a Layout');\n }\n if (process.env.NODE_ENV !== 'production') {\n if (['children', 'component', 'getComponent'].some((key) => key in child.props)) {\n throw new Error('Screen must not have a children, component, or getComponent prop when used as a child of a Layout');\n }\n }\n return child.props;\n } else {\n console.warn('Layout children must be of type Screen, all other children are ignored. To use custom children, create a custom <Layout />.');\n }\n })\n\n if (process.env.NODE_ENV !== 'production') {\n // Assert if names are not unique\n const names = screens?.map((screen) => screen.name);\n if (names && new Set(names).size !== names.length) {\n throw new Error('Screen names must be unique: ' + names);\n }\n }\n\n return screens;\n }, [userDefinedChildren]);\n\n const sorted = useSortedScreens(userDefinedOptions ?? []);\n\n // Prevent throwing an error when there are no screens.\n if (!sorted.length) {\n return null;\n }\n\n // @ts-expect-error\n return <Nav {...props} ref={ref} children={sorted} />;\n });\n\n // @ts-expect-error\n Navigator.Screen = Screen;\n // @ts-expect-error\n return Navigator;\n}\n"]}
@@ -3,8 +3,16 @@ import React from 'react';
3
3
  * @returns React Navigation screens for the route.
4
4
  */
5
5
  export declare function useScreens(): React.ReactNode[];
6
+ export declare type ScreenProps<TOptions extends Record<string, any> = Record<string, any>> = {
7
+ /** Name is required when used inside a Layout component. */
8
+ name?: string;
9
+ initialParams?: {
10
+ [key: string]: any;
11
+ };
12
+ options?: TOptions;
13
+ };
6
14
  /**
7
15
  * @returns React Navigation screens sorted by the `route` property.
8
16
  */
9
- export declare function useScreensRecord(): Record<string, React.ReactNode>;
17
+ export declare function useSortedScreens(order: ScreenProps[]): React.ReactNode[];
10
18
  //# 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;AAM1B;;GAEG;AACH,wBAAgB,UAAU,IAAI,KAAK,CAAC,SAAS,EAAE,CAG9C;AAED;;GAEG;AACH,wBAAgB,gBAAgB,IAAI,MAAM,CAAC,MAAM,EAAE,KAAK,CAAC,SAAS,CAAC,CAKlE"}
1
+ {"version":3,"file":"useScreens.d.ts","sourceRoot":"","sources":["../src/useScreens.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAM1B;;GAEG;AACH,wBAAgB,UAAU,IAAI,KAAK,CAAC,SAAS,EAAE,CAG9C;AAED,oBAAY,WAAW,CAAC,QAAQ,SAAS,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,GAAG,MAAM,CAAC,MAAM,EAAE,GAAG,CAAC,IAAI;IAClF,4DAA4D;IAC5D,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,aAAa,CAAC,EAAE;QAAE,CAAC,GAAG,EAAE,MAAM,GAAG,GAAG,CAAA;KAAE,CAAC;IACvC,OAAO,CAAC,EAAE,QAAQ,CAAC;CACtB,CAAA;AAoCD;;GAEG;AACH,wBAAgB,gBAAgB,CAAC,KAAK,EAAE,WAAW,EAAE,GAAG,KAAK,CAAC,SAAS,EAAE,CAKxE"}
@@ -1,6 +1,6 @@
1
1
  import React from 'react';
2
2
  import { Screen } from './primitives';
3
- import { Route, useRoutes } from './Route';
3
+ import { Route, sortRoutes, useRoutes } from './Route';
4
4
  import { Try } from './views/Try';
5
5
  /**
6
6
  * @returns React Navigation screens for the route.
@@ -9,15 +9,48 @@ export function useScreens() {
9
9
  const children = useRoutes();
10
10
  return React.useMemo(() => children.map((value) => routeToScreen(value)), [children]);
11
11
  }
12
+ function getSortedChildren(children, order) {
13
+ if (!order?.length) {
14
+ return Object.values(children).sort(sortRoutes).map((route) => ({ route, props: {} }));
15
+ }
16
+ const entries = Object.entries(children);
17
+ const ordered = order.map(({ name, initialParams, options }) => {
18
+ if (entries.length === 0) {
19
+ console.warn(`[Layout children]: Too many screens defined. Route "${name}" is extraneous.`);
20
+ return null;
21
+ }
22
+ const matchIndex = entries.findIndex((child) => child[0] === name);
23
+ if (matchIndex === -1) {
24
+ console.warn(`[Layout children]: No route named "${name}" exists in nested children:`, Object.keys(children));
25
+ return null;
26
+ }
27
+ else {
28
+ // Get match and remove from entries
29
+ const [, match] = entries[matchIndex];
30
+ entries.splice(matchIndex, 1);
31
+ return { route: match, props: { initialParams, options } };
32
+ }
33
+ }).filter(Boolean);
34
+ // Add any remaining children
35
+ ordered.push(...entries.map(([, child]) => child).sort(sortRoutes).map((route) => ({ route, props: {} })));
36
+ return ordered;
37
+ }
12
38
  /**
13
39
  * @returns React Navigation screens sorted by the `route` property.
14
40
  */
15
- export function useScreensRecord() {
41
+ export function useSortedScreens(order) {
16
42
  const children = useRoutes();
17
- return React.useMemo(() => Object.fromEntries(children.map((value) => [value.route, routeToScreen(value)])), [children]);
43
+ const sorted = getSortedChildren(children, order);
44
+ return React.useMemo(() => sorted.map((value) => routeToScreen(value.route, value.props)), [sorted]);
18
45
  }
46
+ // TODO: Maybe there's a more React-y way to do this?
47
+ // Without this store, the process enters a recursive loop.
48
+ const qualifiedStore = new WeakMap();
19
49
  /** Wrap the component with various enhancements and add access to child routes. */
20
50
  function getQualifiedRouteComponent(value) {
51
+ if (qualifiedStore.has(value)) {
52
+ return qualifiedStore.get(value);
53
+ }
21
54
  const Component = value.getComponent();
22
55
  const { ErrorBoundary } = value.getExtras();
23
56
  const QualifiedRoute = React.forwardRef((props, ref) => {
@@ -30,9 +63,20 @@ function getQualifiedRouteComponent(value) {
30
63
  return (React.createElement(Route, { filename: value.contextKey }, errorBoundary));
31
64
  });
32
65
  QualifiedRoute.displayName = `Route(${Component.displayName || Component.name || value.route})`;
66
+ qualifiedStore.set(value, QualifiedRoute);
33
67
  return QualifiedRoute;
34
68
  }
35
- function routeToScreen(route) {
36
- return (React.createElement(Screen, { name: route.screenName, key: route.route, options: route.getExtras()?.getNavOptions, component: getQualifiedRouteComponent(route) }));
69
+ function routeToScreen(route, { options, ...props } = {}) {
70
+ const staticOptions = route.getExtras()?.getNavOptions;
71
+ return (
72
+ // @ts-expect-error: fixme
73
+ React.createElement(Screen, { ...props, name: route.route, key: route.route, options: options ? (args) => {
74
+ const staticResult = typeof staticOptions === 'function' ? staticOptions(args) : staticOptions;
75
+ const dynamicResult = typeof options === 'function' ? options?.(args) : options;
76
+ return {
77
+ ...staticResult,
78
+ ...dynamicResult,
79
+ };
80
+ } : staticOptions, component: getQualifiedRouteComponent(route) }));
37
81
  }
38
82
  //# sourceMappingURL=useScreens.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"useScreens.js","sourceRoot":"","sources":["../src/useScreens.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,OAAO,CAAC;AAE1B,OAAO,EAAE,MAAM,EAAE,MAAM,cAAc,CAAC;AACtC,OAAO,EAAE,KAAK,EAAa,SAAS,EAAE,MAAM,SAAS,CAAC;AACtD,OAAO,EAAE,GAAG,EAAE,MAAM,aAAa,CAAC;AAElC;;GAEG;AACH,MAAM,UAAU,UAAU;IACtB,MAAM,QAAQ,GAAG,SAAS,EAAE,CAAC;IAC7B,OAAO,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,QAAQ,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,aAAa,CAAC,KAAK,CAAC,CAAC,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;AAC1F,CAAC;AAED;;GAEG;AACH,MAAM,UAAU,gBAAgB;IAC5B,MAAM,QAAQ,GAAG,SAAS,EAAE,CAAC;IAC7B,OAAO,KAAK,CAAC,OAAO,CAAC,GAAG,EAAE,CAAC,MAAM,CAAC,WAAW,CACzC,QAAQ,CAAC,GAAG,CAAC,CAAC,KAAK,EAAE,EAAE,CAAC,CAAC,KAAK,CAAC,KAAK,EAAE,aAAa,CAAC,KAAK,CAAC,CAAC,CAAC,CAC/D,EAAE,CAAC,QAAQ,CAAC,CAAC,CAAC;AACnB,CAAC;AAED,mFAAmF;AACnF,SAAS,0BAA0B,CAAC,KAAgB;IAEhD,MAAM,SAAS,GAAG,KAAK,CAAC,YAAY,EAAE,CAAC;IAEvC,MAAM,EAAE,aAAa,EAAE,GAAG,KAAK,CAAC,SAAS,EAAE,CAAC;IAE5C,MAAM,cAAc,GAAG,KAAK,CAAC,UAAU,CACnC,CAAC,KAAsC,EAAE,GAAQ,EAAE,EAAE;QACjD,4CAA4C;QAC5C,MAAM,QAAQ,GAAG,KAAK,CAAC,aAAa,CAAC,SAAS,EAAE;YAC5C,GAAG,KAAK;YACR,GAAG;SACN,CAAC,CAAC;QAEH,MAAM,aAAa,GAAG,aAAa,CAAC,CAAC,CAAC,CAClC,oBAAC,GAAG,IAAC,KAAK,EAAE,aAAa,IAAG,QAAQ,CAAO,CAC9C,CAAC,CAAC,CAAC,CACA,QAAQ,CACX,CAAC;QAEF,OAAO,CACH,oBAAC,KAAK,IAAC,QAAQ,EAAE,KAAK,CAAC,UAAU,IAC5B,aAAa,CACV,CACX,CAAC;IACN,CAAC,CACJ,CAAC;IAEF,cAAc,CAAC,WAAW,GAAG,SAAS,SAAS,CAAC,WAAW,IAAI,SAAS,CAAC,IAAI,IAAI,KAAK,CAAC,KAAK,GAAG,CAAC;IAEhG,OAAO,cAAc,CAAC;AAC1B,CAAC;AAED,SAAS,aAAa,CAAC,KAAgB;IACnC,OAAO,CACH,oBAAC,MAAM,IACH,IAAI,EAAE,KAAK,CAAC,UAAU,EACtB,GAAG,EAAE,KAAK,CAAC,KAAK,EAChB,OAAO,EAAE,KAAK,CAAC,SAAS,EAAE,EAAE,aAAa,EACzC,SAAS,EAAE,0BAA0B,CAAC,KAAK,CAAC,GAC9C,CACL,CAAC;AACN,CAAC","sourcesContent":["import React from 'react';\n\nimport { Screen } from './primitives';\nimport { Route, RouteNode, useRoutes } from './Route';\nimport { Try } from './views/Try';\n\n/**\n * @returns React Navigation screens for the route.\n */\nexport function useScreens(): React.ReactNode[] {\n const children = useRoutes();\n return React.useMemo(() => children.map((value) => routeToScreen(value)), [children]);\n}\n\n/** \n * @returns React Navigation screens sorted by the `route` property.\n */\nexport function useScreensRecord(): Record<string, React.ReactNode> {\n const children = useRoutes();\n return React.useMemo(() => Object.fromEntries(\n children.map((value) => [value.route, routeToScreen(value)])\n ), [children]);\n}\n\n/** Wrap the component with various enhancements and add access to child routes. */\nfunction getQualifiedRouteComponent(value: RouteNode) {\n\n const Component = value.getComponent();\n\n const { ErrorBoundary } = value.getExtras();\n\n const QualifiedRoute = React.forwardRef(\n (props: { route: any; navigation: any }, ref: any) => {\n // Surface dynamic name as props to the view\n const children = React.createElement(Component, {\n ...props,\n ref,\n });\n\n const errorBoundary = ErrorBoundary ? (\n <Try catch={ErrorBoundary}>{children}</Try>\n ) : (\n children\n );\n\n return (\n <Route filename={value.contextKey}>\n {errorBoundary}\n </Route>\n );\n }\n );\n\n QualifiedRoute.displayName = `Route(${Component.displayName || Component.name || value.route})`;\n\n return QualifiedRoute;\n}\n\nfunction routeToScreen(route: RouteNode) {\n return (\n <Screen\n name={route.screenName}\n key={route.route}\n options={route.getExtras()?.getNavOptions}\n component={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 { Screen } from './primitives';\nimport { Route, RouteNode, sortRoutes, useRoutes } from './Route';\nimport { Try } from './views/Try';\n\n/**\n * @returns React Navigation screens for the route.\n */\nexport function useScreens(): React.ReactNode[] {\n const children = useRoutes();\n return React.useMemo(() => children.map((value) => routeToScreen(value)), [children]);\n}\n\nexport type ScreenProps<TOptions extends Record<string, any> = Record<string, any>> = {\n /** Name is required when used inside a Layout component. */\n name?: string,\n initialParams?: { [key: string]: any };\n options?: TOptions;\n}\n\nfunction getSortedChildren(children: RouteNode[], order?: ScreenProps[]): { route: RouteNode, props: any }[] {\n if (!order?.length) {\n return Object.values(children).sort(sortRoutes).map((route) => ({ route, props: {} }));\n }\n const entries = Object.entries(children);\n\n const ordered = order.map(({ name, initialParams, options }) => {\n if (entries.length === 0) {\n console.warn(`[Layout children]: Too many screens defined. Route \"${name}\" is extraneous.`);\n return null;\n }\n const matchIndex = entries.findIndex((child) => child[0] === name)\n if (matchIndex === -1) {\n console.warn(`[Layout children]: No route named \"${name}\" exists in nested children:`, Object.keys(children));\n return null;\n } else {\n // Get match and remove from entries\n const [, match] = entries[matchIndex];\n entries.splice(matchIndex, 1);\n\n return { route: match, props: { initialParams, options } }\n }\n }).filter(Boolean) as {\n route: RouteNode;\n props: Partial<ScreenProps>;\n }[]\n\n // Add any remaining children\n ordered.push(...entries.map(([, child]) => child).sort(sortRoutes).map((route) => ({ route, props: {} })));\n\n return ordered;\n}\n\n\n/** \n * @returns React Navigation screens sorted by the `route` property.\n */\nexport function useSortedScreens(order: ScreenProps[]): React.ReactNode[] {\n const children = useRoutes();\n const sorted = getSortedChildren(children, order);\n return React.useMemo(() =>\n sorted.map((value) => routeToScreen(value.route, value.props)), [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. */\nfunction getQualifiedRouteComponent(value: RouteNode) {\n if (qualifiedStore.has(value)) {\n return qualifiedStore.get(value);\n }\n\n const Component = value.getComponent();\n\n const { ErrorBoundary } = value.getExtras();\n\n const QualifiedRoute = React.forwardRef(\n (props: { route: any; navigation: any }, ref: any) => {\n // Surface dynamic name as props to the view\n const children = React.createElement(Component, {\n ...props,\n ref,\n });\n\n const errorBoundary = ErrorBoundary ? (\n <Try catch={ErrorBoundary}>{children}</Try>\n ) : (\n children\n );\n\n return (\n <Route filename={value.contextKey}>\n {errorBoundary}\n </Route>\n );\n }\n );\n\n QualifiedRoute.displayName = `Route(${Component.displayName || Component.name || value.route})`;\n qualifiedStore.set(value, QualifiedRoute);\n return QualifiedRoute;\n}\n\nfunction routeToScreen(route: RouteNode, { options, ...props }: Partial<ScreenProps> = {}) {\n const staticOptions = route.getExtras()?.getNavOptions;\n return (\n // @ts-expect-error: fixme\n <Screen\n {...props}\n name={route.route}\n key={route.route}\n options={options ? (args) => {\n const staticResult = typeof staticOptions === 'function' ? staticOptions(args) : staticOptions;\n const dynamicResult = typeof options === 'function' ? options?.(args) : options;\n return {\n ...staticResult,\n ...dynamicResult,\n };\n } : staticOptions}\n component={getQualifiedRouteComponent(route)}\n />\n );\n}\n"]}
@@ -1,6 +1,12 @@
1
- import { useNavigationBuilder } from '@react-navigation/native';
1
+ import { RouterFactory, useNavigationBuilder } from '@react-navigation/native';
2
2
  import * as React from 'react';
3
- export declare const LayoutContext: React.Context<any>;
3
+ export declare const LayoutContext: React.Context<{
4
+ contextKey: string;
5
+ state: any;
6
+ navigation: any;
7
+ descriptors: any;
8
+ router: RouterFactory<any, any, any>;
9
+ } | null>;
4
10
  export declare type LayoutProps = {
5
11
  initialRouteName?: Parameters<typeof useNavigationBuilder>[1]['initialRouteName'];
6
12
  screenOptions?: Parameters<typeof useNavigationBuilder>[1]['screenOptions'];
@@ -13,7 +19,16 @@ export declare namespace Layout {
13
19
  var Children: typeof import("./Layout").Children;
14
20
  var useContext: typeof useLayoutContext;
15
21
  }
16
- export declare function useLayoutContext(): any;
22
+ export declare function useLayoutContext(): {
23
+ contextKey: string;
24
+ state: any;
25
+ navigation: any;
26
+ descriptors: any;
27
+ router: RouterFactory<any, any, any>;
28
+ };
29
+ export declare function useChild(): any;
17
30
  /** Renders the currently selected content. */
18
31
  export declare function Children(props: Omit<LayoutProps, 'children'>): any;
32
+ export declare function TrustedChildren(): any;
33
+ export declare function DefaultLayout(): JSX.Element;
19
34
  //# sourceMappingURL=Layout.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"Layout.d.ts","sourceRoot":"","sources":["../../src/views/Layout.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAa,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAC3E,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAK/B,eAAO,MAAM,aAAa,oBAAiC,CAAC;AAM5D,oBAAY,WAAW,GAAG;IACtB,gBAAgB,CAAC,EAAE,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAC,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC;IAClF,aAAa,CAAC,EAAE,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC;IAC5E,QAAQ,CAAC,EAAE,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;IAClE,MAAM,CAAC,EAAE,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAC,CAAC,CAAC,CAAC;CACvD,CAAA;AAED,+DAA+D;AAC/D,wBAAgB,MAAM,CAAC,EACnB,gBAAgB,EAChB,aAAa,EACb,QAAQ,EACR,MAAkB,GACrB,EAAE,WAAW,eAeb;yBApBe,MAAM;;;;AAsBtB,wBAAgB,gBAAgB,QAQ/B;AAaD,8CAA8C;AAC9C,wBAAgB,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC,OAY5D"}
1
+ {"version":3,"file":"Layout.d.ts","sourceRoot":"","sources":["../../src/views/Layout.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,aAAa,EAAe,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAC5F,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAM/B,eAAO,MAAM,aAAa;gBAAqC,MAAM;WAAS,GAAG;gBAAc,GAAG;iBAAe,GAAG;YAAU,cAAc,GAAG,EAAE,GAAG,EAAE,GAAG,CAAC;SAAgB,CAAC;AAM3K,oBAAY,WAAW,GAAG;IACtB,gBAAgB,CAAC,EAAE,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAC,CAAC,CAAC,CAAC,kBAAkB,CAAC,CAAC;IAClF,aAAa,CAAC,EAAE,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAC,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC;IAC5E,QAAQ,CAAC,EAAE,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAC,CAAC,CAAC,CAAC,UAAU,CAAC,CAAC;IAClE,MAAM,CAAC,EAAE,UAAU,CAAC,OAAO,oBAAoB,CAAC,CAAC,CAAC,CAAC,CAAC;CACvD,CAAA;AAED,+DAA+D;AAC/D,wBAAgB,MAAM,CAAC,EACnB,gBAAgB,EAChB,aAAa,EACb,QAAQ,EACR,MAAoB,GACvB,EAAE,WAAW,eAgBb;yBArBe,MAAM;;;;AAuBtB,wBAAgB,gBAAgB;;;;;;EAQ/B;AAED,wBAAgB,QAAQ,QAcvB;AAED,8CAA8C;AAC9C,wBAAgB,QAAQ,CAAC,KAAK,EAAE,IAAI,CAAC,WAAW,EAAE,UAAU,CAAC,OAc5D;AAED,wBAAgB,eAAe,QAE9B;AAED,wBAAgB,aAAa,gBAE5B"}
@@ -1,5 +1,6 @@
1
- import { TabRouter, useNavigationBuilder } from '@react-navigation/native';
1
+ import { StackRouter, useNavigationBuilder } from '@react-navigation/native';
2
2
  import * as React from 'react';
3
+ import { useContextKey } from '../Route';
3
4
  import { useScreens } from '../useScreens';
4
5
  // TODO: This might already exist upstream, maybe something like `useCurrentRender` ?
5
6
  export const LayoutContext = React.createContext(null);
@@ -7,14 +8,15 @@ if (process.env.NODE_ENV !== "production") {
7
8
  LayoutContext.displayName = "LayoutContext";
8
9
  }
9
10
  /** An unstyled custom navigator. Good for basic web layouts */
10
- export function Layout({ initialRouteName, screenOptions, children, router = TabRouter, }) {
11
+ export function Layout({ initialRouteName, screenOptions, children, router = StackRouter, }) {
12
+ const contextKey = useContextKey();
11
13
  const screens = useScreens();
12
14
  const { state, navigation, descriptors, NavigationContent } = useNavigationBuilder(router, {
13
15
  children: screens,
14
16
  screenOptions,
15
17
  initialRouteName,
16
18
  });
17
- return (React.createElement(LayoutContext.Provider, { value: { state, navigation, descriptors, router } },
19
+ return (React.createElement(LayoutContext.Provider, { value: { contextKey, state, navigation, descriptors, router } },
18
20
  React.createElement(NavigationContent, null, children)));
19
21
  }
20
22
  export function useLayoutContext() {
@@ -24,10 +26,12 @@ export function useLayoutContext() {
24
26
  }
25
27
  return context;
26
28
  }
27
- function useChild() {
28
- const context = React.useContext(LayoutContext);
29
+ export function useChild() {
30
+ const context = useLayoutContext();
29
31
  const { state, descriptors } = context;
30
- const current = state.routes.find((route, i) => state.index === i);
32
+ const current = state.routes.find((route, i) => {
33
+ return state.index === i;
34
+ });
31
35
  if (!current) {
32
36
  return null;
33
37
  }
@@ -35,14 +39,23 @@ function useChild() {
35
39
  }
36
40
  /** Renders the currently selected content. */
37
41
  export function Children(props) {
42
+ const contextKey = useContextKey();
38
43
  const context = React.useContext(LayoutContext);
39
- if (!context) {
44
+ // Ensure the context is for the current contextKey
45
+ if (context?.contextKey !== contextKey) {
40
46
  // Qualify the content and re-export.
41
47
  return (React.createElement(Layout, { ...props },
42
- React.createElement(Children, null)));
48
+ React.createElement(TrustedChildren, null)));
43
49
  }
44
50
  return useChild();
45
51
  }
52
+ export function TrustedChildren() {
53
+ return useChild();
54
+ }
55
+ export function DefaultLayout() {
56
+ return React.createElement(Layout, null,
57
+ React.createElement(TrustedChildren, null));
58
+ }
46
59
  Layout.Children = Children;
47
60
  Layout.useContext = useLayoutContext;
48
61
  //# sourceMappingURL=Layout.js.map
@@ -1 +1 @@
1
- {"version":3,"file":"Layout.js","sourceRoot":"","sources":["../../src/views/Layout.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAC3E,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAE3C,qFAAqF;AACrF,MAAM,CAAC,MAAM,aAAa,GAAG,KAAK,CAAC,aAAa,CAAM,IAAI,CAAC,CAAC;AAE5D,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,EAAE;IACvC,aAAa,CAAC,WAAW,GAAG,eAAe,CAAC;CAC/C;AASD,+DAA+D;AAC/D,MAAM,UAAU,MAAM,CAAC,EACnB,gBAAgB,EAChB,aAAa,EACb,QAAQ,EACR,MAAM,GAAG,SAAS,GACR;IACV,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAE7B,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,iBAAiB,EAAE,GACvD,oBAAoB,CAAC,MAAM,EAAE;QACzB,QAAQ,EAAE,OAAO;QACjB,aAAa;QACb,gBAAgB;KACnB,CAAC,CAAC;IAEP,OAAO,CACH,oBAAC,aAAa,CAAC,QAAQ,IAAC,KAAK,EAAE,EAAE,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,EAAE;QACrE,oBAAC,iBAAiB,QAAE,QAAQ,CAAqB,CAC5B,CAC5B,CAAC;AACN,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC5B,MAAM,OAAO,GAAG,KAAK,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;IAChD,IAAI,CAAC,OAAO,EAAE;QACV,MAAM,IAAI,KAAK,CACX,mDAAmD,CACtD,CAAC;KACL;IACD,OAAO,OAAO,CAAC;AACnB,CAAC;AAED,SAAS,QAAQ;IACb,MAAM,OAAO,GAAG,KAAK,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;IAEhD,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC;IACvC,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE,CAAC,KAAK,CAAC,KAAK,KAAK,CAAC,CAAC,CAAC;IACnE,IAAI,CAAC,OAAO,EAAE;QACV,OAAO,IAAI,CAAC;KACf;IACD,OAAO,WAAW,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,IAAI,IAAI,CAAC;AACtD,CAAC;AAED,8CAA8C;AAC9C,MAAM,UAAU,QAAQ,CAAC,KAAoC;IACzD,MAAM,OAAO,GAAG,KAAK,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;IAChD,IAAI,CAAC,OAAO,EAAE;QACV,qCAAqC;QACrC,OAAO,CACH,oBAAC,MAAM,OAAK,KAAK;YACb,oBAAC,QAAQ,OAAG,CACP,CACZ,CAAC;KACL;IAED,OAAO,QAAQ,EAAE,CAAC;AACtB,CAAC;AAED,MAAM,CAAC,QAAQ,GAAG,QAAQ,CAAC;AAC3B,MAAM,CAAC,UAAU,GAAG,gBAAgB,CAAC","sourcesContent":["import { TabRouter, useNavigationBuilder } from '@react-navigation/native';\nimport * as React from 'react';\n\nimport { useScreens } from '../useScreens';\n\n// TODO: This might already exist upstream, maybe something like `useCurrentRender` ?\nexport const LayoutContext = React.createContext<any>(null);\n\nif (process.env.NODE_ENV !== \"production\") {\n LayoutContext.displayName = \"LayoutContext\";\n}\n\nexport type LayoutProps = {\n initialRouteName?: Parameters<typeof useNavigationBuilder>[1]['initialRouteName'];\n screenOptions?: Parameters<typeof useNavigationBuilder>[1]['screenOptions'];\n children?: Parameters<typeof useNavigationBuilder>[1]['children'];\n router?: Parameters<typeof useNavigationBuilder>[0];\n}\n\n/** An unstyled custom navigator. Good for basic web layouts */\nexport function Layout({\n initialRouteName,\n screenOptions,\n children,\n router = TabRouter,\n}: LayoutProps) {\n const screens = useScreens();\n\n const { state, navigation, descriptors, NavigationContent } =\n useNavigationBuilder(router, {\n children: screens,\n screenOptions,\n initialRouteName,\n });\n\n return (\n <LayoutContext.Provider value={{ state, navigation, descriptors, router }}>\n <NavigationContent>{children}</NavigationContent>\n </LayoutContext.Provider>\n );\n}\n\nexport function useLayoutContext() {\n const context = React.useContext(LayoutContext);\n if (!context) {\n throw new Error(\n \"useLayoutContext must be used within a <Layout />\"\n );\n }\n return context;\n}\n\nfunction useChild() {\n const context = React.useContext(LayoutContext);\n\n const { state, descriptors } = context;\n const current = state.routes.find((route, i) => state.index === i);\n if (!current) {\n return null;\n }\n return descriptors[current.key]?.render() ?? null;\n}\n\n/** Renders the currently selected content. */\nexport function Children(props: Omit<LayoutProps, 'children'>) {\n const context = React.useContext(LayoutContext);\n if (!context) {\n // Qualify the content and re-export.\n return (\n <Layout {...props}>\n <Children />\n </Layout>\n );\n }\n\n return useChild();\n}\n\nLayout.Children = Children;\nLayout.useContext = useLayoutContext;\n"]}
1
+ {"version":3,"file":"Layout.js","sourceRoot":"","sources":["../../src/views/Layout.tsx"],"names":[],"mappings":"AAAA,OAAO,EAAiB,WAAW,EAAE,oBAAoB,EAAE,MAAM,0BAA0B,CAAC;AAC5F,OAAO,KAAK,KAAK,MAAM,OAAO,CAAC;AAE/B,OAAO,EAAE,aAAa,EAAE,MAAM,UAAU,CAAC;AACzC,OAAO,EAAE,UAAU,EAAE,MAAM,eAAe,CAAC;AAE3C,qFAAqF;AACrF,MAAM,CAAC,MAAM,aAAa,GAAG,KAAK,CAAC,aAAa,CAAqH,IAAI,CAAC,CAAC;AAE3K,IAAI,OAAO,CAAC,GAAG,CAAC,QAAQ,KAAK,YAAY,EAAE;IACvC,aAAa,CAAC,WAAW,GAAG,eAAe,CAAC;CAC/C;AASD,+DAA+D;AAC/D,MAAM,UAAU,MAAM,CAAC,EACnB,gBAAgB,EAChB,aAAa,EACb,QAAQ,EACR,MAAM,GAAG,WAAW,GACV;IACV,MAAM,UAAU,GAAG,aAAa,EAAE,CAAA;IAClC,MAAM,OAAO,GAAG,UAAU,EAAE,CAAC;IAE7B,MAAM,EAAE,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,iBAAiB,EAAE,GACvD,oBAAoB,CAAC,MAAM,EAAE;QACzB,QAAQ,EAAE,OAAO;QACjB,aAAa;QACb,gBAAgB;KACnB,CAAC,CAAC;IAEP,OAAO,CACH,oBAAC,aAAa,CAAC,QAAQ,IAAC,KAAK,EAAE,EAAE,UAAU,EAAE,KAAK,EAAE,UAAU,EAAE,WAAW,EAAE,MAAM,EAAE;QACjF,oBAAC,iBAAiB,QAAE,QAAQ,CAAqB,CAC5B,CAC5B,CAAC;AACN,CAAC;AAED,MAAM,UAAU,gBAAgB;IAC5B,MAAM,OAAO,GAAG,KAAK,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;IAChD,IAAI,CAAC,OAAO,EAAE;QACV,MAAM,IAAI,KAAK,CACX,mDAAmD,CACtD,CAAC;KACL;IACD,OAAO,OAAO,CAAC;AACnB,CAAC;AAED,MAAM,UAAU,QAAQ;IACpB,MAAM,OAAO,GAAG,gBAAgB,EAAE,CAAC;IAEnC,MAAM,EAAE,KAAK,EAAE,WAAW,EAAE,GAAG,OAAO,CAAC;IAEvC,MAAM,OAAO,GAAG,KAAK,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,KAAK,EAAE,CAAC,EAAE,EAAE;QAC3C,OAAO,KAAK,CAAC,KAAK,KAAK,CAAC,CAAA;IAC5B,CAAC,CAAC,CAAC;IAEH,IAAI,CAAC,OAAO,EAAE;QACV,OAAO,IAAI,CAAC;KACf;IAED,OAAO,WAAW,CAAC,OAAO,CAAC,GAAG,CAAC,EAAE,MAAM,EAAE,IAAI,IAAI,CAAC;AACtD,CAAC;AAED,8CAA8C;AAC9C,MAAM,UAAU,QAAQ,CAAC,KAAoC;IACzD,MAAM,UAAU,GAAG,aAAa,EAAE,CAAA;IAClC,MAAM,OAAO,GAAG,KAAK,CAAC,UAAU,CAAC,aAAa,CAAC,CAAC;IAChD,mDAAmD;IACnD,IAAI,OAAO,EAAE,UAAU,KAAK,UAAU,EAAE;QACpC,qCAAqC;QACrC,OAAO,CACH,oBAAC,MAAM,OAAK,KAAK;YACb,oBAAC,eAAe,OAAG,CACd,CACZ,CAAC;KACL;IAED,OAAO,QAAQ,EAAE,CAAC;AACtB,CAAC;AAED,MAAM,UAAU,eAAe;IAC3B,OAAO,QAAQ,EAAE,CAAC;AACtB,CAAC;AAED,MAAM,UAAU,aAAa;IACzB,OAAO,oBAAC,MAAM;QAAC,oBAAC,eAAe,OAAG,CAAS,CAAC;AAChD,CAAC;AAED,MAAM,CAAC,QAAQ,GAAG,QAAQ,CAAC;AAC3B,MAAM,CAAC,UAAU,GAAG,gBAAgB,CAAC","sourcesContent":["import { RouterFactory, StackRouter, useNavigationBuilder } from '@react-navigation/native';\nimport * as React from 'react';\n\nimport { useContextKey } from '../Route';\nimport { useScreens } from '../useScreens';\n\n// TODO: This might already exist upstream, maybe something like `useCurrentRender` ?\nexport const LayoutContext = React.createContext<{ contextKey: string; state: any; navigation: any; descriptors: any; router: RouterFactory<any, any, any> } | null>(null);\n\nif (process.env.NODE_ENV !== \"production\") {\n LayoutContext.displayName = \"LayoutContext\";\n}\n\nexport type LayoutProps = {\n initialRouteName?: Parameters<typeof useNavigationBuilder>[1]['initialRouteName'];\n screenOptions?: Parameters<typeof useNavigationBuilder>[1]['screenOptions'];\n children?: Parameters<typeof useNavigationBuilder>[1]['children'];\n router?: Parameters<typeof useNavigationBuilder>[0];\n}\n\n/** An unstyled custom navigator. Good for basic web layouts */\nexport function Layout({\n initialRouteName,\n screenOptions,\n children,\n router = StackRouter,\n}: LayoutProps) {\n const contextKey = useContextKey()\n const screens = useScreens();\n\n const { state, navigation, descriptors, NavigationContent } =\n useNavigationBuilder(router, {\n children: screens,\n screenOptions,\n initialRouteName,\n });\n\n return (\n <LayoutContext.Provider value={{ contextKey, state, navigation, descriptors, router }}>\n <NavigationContent>{children}</NavigationContent>\n </LayoutContext.Provider>\n );\n}\n\nexport function useLayoutContext() {\n const context = React.useContext(LayoutContext);\n if (!context) {\n throw new Error(\n \"useLayoutContext must be used within a <Layout />\"\n );\n }\n return context;\n}\n\nexport function useChild() {\n const context = useLayoutContext();\n\n const { state, descriptors } = context;\n\n const current = state.routes.find((route, i) => {\n return state.index === i\n });\n\n if (!current) {\n return null;\n }\n\n return descriptors[current.key]?.render() ?? null;\n}\n\n/** Renders the currently selected content. */\nexport function Children(props: Omit<LayoutProps, 'children'>) {\n const contextKey = useContextKey()\n const context = React.useContext(LayoutContext);\n // Ensure the context is for the current contextKey\n if (context?.contextKey !== contextKey) {\n // Qualify the content and re-export.\n return (\n <Layout {...props}>\n <TrustedChildren />\n </Layout>\n );\n }\n\n return useChild();\n}\n\nexport function TrustedChildren() {\n return useChild();\n}\n\nexport function DefaultLayout() {\n return <Layout><TrustedChildren /></Layout>;\n}\n\nLayout.Children = Children;\nLayout.useContext = useLayoutContext;\n"]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "expo-router",
3
- "version": "0.0.4",
3
+ "version": "0.0.5",
4
4
  "main": "build/index.js",
5
5
  "files": [
6
6
  "entry.js",