expo-router 0.0.4 → 0.0.6

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.
Files changed (37) hide show
  1. package/build/ContextNavigationContainer.d.ts +1 -1
  2. package/build/ContextNavigationContainer.d.ts.map +1 -1
  3. package/build/ContextNavigationContainer.js +3 -3
  4. package/build/ContextNavigationContainer.js.map +1 -1
  5. package/build/ContextNavigator.d.ts.map +1 -1
  6. package/build/ContextNavigator.js +6 -5
  7. package/build/ContextNavigator.js.map +1 -1
  8. package/build/Route.d.ts +2 -2
  9. package/build/Route.d.ts.map +1 -1
  10. package/build/Route.js +41 -22
  11. package/build/Route.js.map +1 -1
  12. package/build/getLinkingConfig.d.ts.map +1 -1
  13. package/build/getLinkingConfig.js +78 -16
  14. package/build/getLinkingConfig.js.map +1 -1
  15. package/build/getRoutes.d.ts +5 -2
  16. package/build/getRoutes.d.ts.map +1 -1
  17. package/build/getRoutes.js +82 -72
  18. package/build/getRoutes.js.map +1 -1
  19. package/build/index.d.ts +2 -1
  20. package/build/index.d.ts.map +1 -1
  21. package/build/index.js +2 -1
  22. package/build/index.js.map +1 -1
  23. package/build/layouts/withLayoutContext.d.ts.map +1 -1
  24. package/build/layouts/withLayoutContext.js +2 -29
  25. package/build/layouts/withLayoutContext.js.map +1 -1
  26. package/build/useScreens.d.ts +9 -1
  27. package/build/useScreens.d.ts.map +1 -1
  28. package/build/useScreens.js +49 -5
  29. package/build/useScreens.js.map +1 -1
  30. package/build/views/Directory.d.ts.map +1 -1
  31. package/build/views/Directory.js +16 -3
  32. package/build/views/Directory.js.map +1 -1
  33. package/build/views/Layout.d.ts +18 -3
  34. package/build/views/Layout.d.ts.map +1 -1
  35. package/build/views/Layout.js +21 -8
  36. package/build/views/Layout.js.map +1 -1
  37. package/package.json +1 -1
@@ -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;AAYzE,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,CA0FxE"}
@@ -1,4 +1,5 @@
1
1
  import * as Linking from "expo-linking";
2
+ import Constants, { ExecutionEnvironment } from "expo-constants";
2
3
  import { getAllWebRedirects } from "./aasa";
3
4
  import getPathFromState from "./fork/getPathFromState";
4
5
  import getStateFromPath from "./fork/getStateFromPath";
@@ -23,31 +24,28 @@ export function treeToReactNavigationLinkingRoutes(nodes, parents = []) {
23
24
  // Our warnings can be more helpful than upstream since we know the associated file name.
24
25
  const firstPass = nodes
25
26
  .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
- ];
27
+ const path = convertDynamicRouteToReactNavigation(node.route);
28
+ if (!node.children.length) {
29
+ return [node.route, path];
30
+ }
31
+ const screens = treeToReactNavigationLinkingRoutes(node.children, [
32
+ ...parents,
33
+ path,
34
+ ]);
35
+ return [node.route, { path, screens }];
39
36
  })
40
- .reduce((acc, [screenName, current]) => {
41
- acc[screenName] = current;
37
+ .reduce((acc, [route, current]) => {
38
+ acc[route] = current;
42
39
  return acc;
43
40
  }, {});
44
41
  return firstPass;
45
42
  }
46
43
  export function getLinkingConfig(routes) {
44
+ const rootURL = Linking.createURL("/");
47
45
  return {
48
46
  prefixes: [
49
47
  /* your linking prefixes */
50
- Linking.createURL("/"),
48
+ rootURL,
51
49
  // This ensures that we can redirect correctly when the user comes from an associated domain
52
50
  // i.e. iOS Safari banner.
53
51
  ...getAllWebRedirects(),
@@ -55,6 +53,70 @@ export function getLinkingConfig(routes) {
55
53
  config: {
56
54
  screens: treeToReactNavigationLinkingRoutes(routes),
57
55
  },
56
+ // A custom getInitialURL is used on native to ensure the app always starts at
57
+ // the root path if it's launched from something other than a deep link.
58
+ // This helps keep the native functionality working like the web functionality.
59
+ // For example, if you had a root navigator where the first screen was `/settings` and the second was `/index`
60
+ // then `/index` would be used on web and `/settings` would be used on native.
61
+ async getInitialURL() {
62
+ const url = await Promise.race([
63
+ (async () => {
64
+ const url = await Linking.getInitialURL();
65
+ // NOTE(EvanBacon): This could probably be wrapped with the development boundary
66
+ // since Expo Go is mostly just used in development.
67
+ // Expo Go is weird and requires the root path to be `/--/`
68
+ if (url &&
69
+ Constants.executionEnvironment === ExecutionEnvironment.StoreClient) {
70
+ const parsed = Linking.parse(url);
71
+ // If the URL is defined (default in Expo Go dev apps) and the URL has no path:
72
+ // `exp://192.168.87.39:19000/` then use the default `exp://192.168.87.39:19000/--/`
73
+ if (parsed.path === null || ["", "/"].includes(parsed.path)) {
74
+ return rootURL;
75
+ }
76
+ }
77
+ // The path will be nullish in bare apps when the app is launched from the home screen.
78
+ // TODO(EvanBacon): define some policy around notifications.
79
+ return url ?? rootURL;
80
+ })(),
81
+ new Promise((resolve) =>
82
+ // Timeout in 150ms if `getInitialState` doesn't resolve
83
+ // Workaround for https://github.com/facebook/react-native/issues/25675
84
+ setTimeout(() => resolve(rootURL), 150)),
85
+ ]);
86
+ return url;
87
+ },
88
+ subscribe: (listener) => {
89
+ let callback = undefined;
90
+ if (Constants.executionEnvironment === ExecutionEnvironment.StoreClient) {
91
+ // This extra work is only done in the Expo Go app.
92
+ callback = ({ url }) => {
93
+ const parsed = Linking.parse(url);
94
+ // If the URL is defined (default in Expo Go dev apps) and the URL has no path:
95
+ // `exp://192.168.87.39:19000/` then use the default `exp://192.168.87.39:19000/--/`
96
+ if (parsed.path === null || ["", "/"].includes(parsed.path)) {
97
+ listener(rootURL);
98
+ }
99
+ else {
100
+ listener(url);
101
+ }
102
+ };
103
+ }
104
+ else {
105
+ callback = ({ url }) => listener(url);
106
+ }
107
+ const subscription = Linking.addEventListener("url", callback);
108
+ // Storing this in a local variable stops Jest from complaining about import after teardown
109
+ const removeEventListener = Linking.removeEventListener?.bind(Linking);
110
+ return () => {
111
+ // https://github.com/facebook/react-native/commit/6d1aca806cee86ad76de771ed3a1cc62982ebcd7
112
+ if (subscription?.remove) {
113
+ subscription.remove();
114
+ }
115
+ else {
116
+ removeEventListener?.("url", callback);
117
+ }
118
+ };
119
+ },
58
120
  getStateFromPath,
59
121
  getPathFromState,
60
122
  };
@@ -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":"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","sourcesContent":["import { LinkingOptions, PathConfigMap } from \"@react-navigation/native\";\nimport * as Linking from \"expo-linking\";\n\nimport Constants, { ExecutionEnvironment } from \"expo-constants\";\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 const rootURL = Linking.createURL(\"/\");\n\n return {\n prefixes: [\n /* your linking prefixes */\n rootURL,\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 // A custom getInitialURL is used on native to ensure the app always starts at\n // the root path if it's launched from something other than a deep link.\n // This helps keep the native functionality working like the web functionality.\n // For example, if you had a root navigator where the first screen was `/settings` and the second was `/index`\n // then `/index` would be used on web and `/settings` would be used on native.\n async getInitialURL(): Promise<string> {\n const url = await Promise.race<string>([\n (async () => {\n const url = await Linking.getInitialURL();\n\n // NOTE(EvanBacon): This could probably be wrapped with the development boundary\n // since Expo Go is mostly just used in development.\n\n // Expo Go is weird and requires the root path to be `/--/`\n if (\n url &&\n Constants.executionEnvironment === ExecutionEnvironment.StoreClient\n ) {\n const parsed = Linking.parse(url);\n // If the URL is defined (default in Expo Go dev apps) and the URL has no path:\n // `exp://192.168.87.39:19000/` then use the default `exp://192.168.87.39:19000/--/`\n if (parsed.path === null || [\"\", \"/\"].includes(parsed.path)) {\n return rootURL;\n }\n }\n // The path will be nullish in bare apps when the app is launched from the home screen.\n // TODO(EvanBacon): define some policy around notifications.\n return url ?? rootURL;\n })(),\n new Promise<string>((resolve) =>\n // Timeout in 150ms if `getInitialState` doesn't resolve\n // Workaround for https://github.com/facebook/react-native/issues/25675\n setTimeout(() => resolve(rootURL), 150)\n ),\n ]);\n return url;\n },\n subscribe: (listener) => {\n let callback: (({ url }: { url: string }) => void) | undefined =\n undefined;\n\n if (Constants.executionEnvironment === ExecutionEnvironment.StoreClient) {\n // This extra work is only done in the Expo Go app.\n callback = ({ url }: { url: string }) => {\n const parsed = Linking.parse(url);\n // If the URL is defined (default in Expo Go dev apps) and the URL has no path:\n // `exp://192.168.87.39:19000/` then use the default `exp://192.168.87.39:19000/--/`\n if (parsed.path === null || [\"\", \"/\"].includes(parsed.path)) {\n listener(rootURL);\n } else {\n listener(url);\n }\n };\n } else {\n callback = ({ url }: { url: string }) => listener(url);\n }\n const subscription = Linking.addEventListener(\"url\", callback) as\n | { remove(): void }\n | undefined;\n\n // Storing this in a local variable stops Jest from complaining about import after teardown\n const removeEventListener = Linking.removeEventListener?.bind(Linking);\n\n return () => {\n // https://github.com/facebook/react-native/commit/6d1aca806cee86ad76de771ed3a1cc62982ebcd7\n if (subscription?.remove) {\n subscription.remove();\n } else {\n removeEventListener?.(\"url\", callback);\n }\n };\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"}