|
/** |
|
* Surprisingly, there is very little code here as all we really need to do |
|
* is provide a short hand for the default render function of the provided screens. |
|
* |
|
* If a custom `render` is provided, we execute it by passing the whole configuration |
|
* as props. |
|
* |
|
* Otherwise use the default behaviour defined in `renderScreens`. |
|
*/ |
|
export function makeNavigator< |
|
TNavigatorType extends NavigatorType, |
|
TScreens extends ScreenMap |
|
>( |
|
config: PartialNavigatorConfiguration<TNavigatorType, TScreens>, |
|
): NavigatorConfiguration<TNavigatorType, TScreens> { |
|
if (config.render) { |
|
const Component = config.render; |
|
return { |
|
...config, |
|
render: () => <Component {...config} />, |
|
}; |
|
} |
|
|
|
const Parent = navigators[config.type](); |
|
|
|
return { |
|
...config, |
|
render: () => ( |
|
<Parent.Navigator> |
|
{renderScreens(Parent, config.screens)} |
|
</Parent.Navigator> |
|
); |
|
}; |
|
} |
|
|
|
/** |
|
* This function loops through the `screens` object and |
|
* returns an array of rendered screens with common options. |
|
*/ |
|
export function renderScreens<TScreens extends ScreenMap>( |
|
Navigator: TypedNavigator<any, any, any, any, any>, |
|
screens: TScreens, |
|
mapper?: ( |
|
entry: TScreens[keyof TScreens], |
|
) => Omit<ComponentProps<typeof Navigator['Screen']>, 'children'>, |
|
) { |
|
return Object.entries(screens).map(([name, entry]) => ( |
|
// @ts-ignore due to an odd union type bug... |
|
<Navigator.Screen |
|
key={name} |
|
name={name} |
|
options={entry.options} |
|
component={entry.screen} |
|
initialParams={entry.initialParams} |
|
{...mapper?.((entry as unknown) as TScreens[keyof TScreens])} |
|
/> |
|
)); |
|
} |
|
|
|
/** |
|
* This is a small utility to deep merge navigation options. |
|
*/ |
|
export function mergeOptions<TOptions extends NavigatorProps<keyof typeof navigators>>( |
|
...xs: Array<Partial<TOptions>> |
|
): TOptions { |
|
return xs.reduce<TOptions>((output, x) => { |
|
return { |
|
...output, |
|
...x, |
|
screenOptions: { |
|
...output.screenOptions, |
|
...x.screenOptions, |
|
}, |
|
}; |
|
}, {} as TOptions); |
|
} |