/* eslint-disable react-native/no-inline-styles */ import * as React from 'react'; import shortid from 'shortid'; import { useNavigationBuilder, NavigationProp, CommonAction, ParamListBase, Router, createNavigator, TargetRoute, BaseRouter, } from '../src/index'; type Props = { initialRouteName?: string; children: React.ReactNode; }; type Action = { type: 'JUMP_TO'; payload: { name?: string; key?: string; params?: object }; }; export type TabNavigationOptions = { /** * Title text for the screen. */ title?: string; }; export type TabNavigationProp = NavigationProp< ParamList, TabNavigationOptions > & { /** * Jump to an existing tab. * * @param name Name of the route for the tab. * @param [params] Params object for the route. */ jumpTo>( ...args: ParamList[RouteName] extends void ? [TargetRoute] : [TargetRoute, ParamList[RouteName]] ): void; }; const TabRouter: Router = { ...BaseRouter, getInitialState({ routeNames, initialRouteName = routeNames[0], initialParamsList, }) { const index = routeNames.indexOf(initialRouteName); return { key: `tab-${shortid()}`, index, routeNames, routes: routeNames.map(name => ({ name, key: `${name}-${shortid()}`, params: initialParamsList[name], })), }; }, getRehydratedState({ routeNames, partialState }) { let state = partialState; if (state.stale) { state = { ...state, stale: false, routeNames, key: `tab-${shortid()}`, }; } return state; }, getStateForRouteNamesChange(state, { routeNames, initialParamsList }) { return { ...state, routeNames, routes: routeNames.map( name => state.routes.find(r => r.name === name) || { name, key: `${name}-${shortid()}`, params: initialParamsList[name], } ), }; }, getStateForRouteFocus(state, key) { const index = state.routes.findIndex(r => r.key === key); if (index === -1 || index === state.index) { return state; } return { ...state, index }; }, getStateForAction(state, action) { switch (action.type) { case 'JUMP_TO': case 'NAVIGATE': { let index = -1; if (action.payload.key) { index = state.routes.findIndex( route => route.key === action.payload.key ); } if (action.payload.name) { index = state.routes.findIndex( route => route.name === action.payload.name ); } if (index === -1) { return null; } return { ...state, routes: action.payload.params !== undefined ? state.routes.map((route, i) => i === index ? { ...route, params: { ...route.params, ...action.payload.params, }, } : route ) : state.routes, index, }; } default: return BaseRouter.getStateForAction(state, action); } }, shouldActionPropagateToChildren(action) { return action.type === 'NAVIGATE'; }, shouldActionChangeFocus(action) { return action.type === 'NAVIGATE'; }, actionCreators: { jumpTo(target: TargetRoute, params?: object) { if (typeof target === 'string') { return { type: 'JUMP_TO', payload: { name: target, params } }; } else { if ( (target.hasOwnProperty('key') && target.hasOwnProperty('name')) || (!target.hasOwnProperty('key') && !target.hasOwnProperty('name')) ) { throw new Error( 'While calling jumpTo you need to specify either name or key' ); } return { type: 'JUMP_TO', payload: { ...target, params } }; } }, }, }; export function TabNavigator(props: Props) { const { state, descriptors } = useNavigationBuilder(TabRouter, props); return (
{state.routes.map((route, i, self) => (
{descriptors[route.key].render()}
))}
); } export default createNavigator( TabNavigator );