260 lines
7.3 KiB
JavaScript
260 lines
7.3 KiB
JavaScript
|
import { nanoid } from 'nanoid/non-secure';
|
||
|
import BaseRouter from './BaseRouter';
|
||
|
const TYPE_ROUTE = 'route';
|
||
|
export const TabActions = {
|
||
|
jumpTo(name, params) {
|
||
|
return {
|
||
|
type: 'JUMP_TO',
|
||
|
payload: {
|
||
|
name,
|
||
|
params
|
||
|
}
|
||
|
};
|
||
|
}
|
||
|
|
||
|
};
|
||
|
|
||
|
const getRouteHistory = (routes, index, backBehavior, initialRouteName) => {
|
||
|
const history = [{
|
||
|
type: TYPE_ROUTE,
|
||
|
key: routes[index].key
|
||
|
}];
|
||
|
let initialRouteIndex;
|
||
|
|
||
|
switch (backBehavior) {
|
||
|
case 'order':
|
||
|
for (let i = index; i > 0; i--) {
|
||
|
history.unshift({
|
||
|
type: TYPE_ROUTE,
|
||
|
key: routes[i - 1].key
|
||
|
});
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
|
||
|
case 'firstRoute':
|
||
|
if (index !== 0) {
|
||
|
history.unshift({
|
||
|
type: TYPE_ROUTE,
|
||
|
key: routes[0].key
|
||
|
});
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
|
||
|
case 'initialRoute':
|
||
|
initialRouteIndex = routes.findIndex(route => route.name === initialRouteName);
|
||
|
initialRouteIndex = initialRouteIndex === -1 ? 0 : initialRouteIndex;
|
||
|
|
||
|
if (index !== initialRouteIndex) {
|
||
|
history.unshift({
|
||
|
type: TYPE_ROUTE,
|
||
|
key: routes[initialRouteIndex].key
|
||
|
});
|
||
|
}
|
||
|
|
||
|
break;
|
||
|
|
||
|
case 'history':
|
||
|
// The history will fill up on navigation
|
||
|
break;
|
||
|
}
|
||
|
|
||
|
return history;
|
||
|
};
|
||
|
|
||
|
const changeIndex = (state, index, backBehavior, initialRouteName) => {
|
||
|
let history;
|
||
|
|
||
|
if (backBehavior === 'history') {
|
||
|
const currentKey = state.routes[index].key;
|
||
|
history = state.history.filter(it => it.type === 'route' ? it.key !== currentKey : false).concat({
|
||
|
type: TYPE_ROUTE,
|
||
|
key: currentKey
|
||
|
});
|
||
|
} else {
|
||
|
history = getRouteHistory(state.routes, index, backBehavior, initialRouteName);
|
||
|
}
|
||
|
|
||
|
return { ...state,
|
||
|
index,
|
||
|
history
|
||
|
};
|
||
|
};
|
||
|
|
||
|
export default function TabRouter({
|
||
|
initialRouteName,
|
||
|
backBehavior = 'history'
|
||
|
}) {
|
||
|
const router = { ...BaseRouter,
|
||
|
type: 'tab',
|
||
|
|
||
|
getInitialState({
|
||
|
routeNames,
|
||
|
routeParamList
|
||
|
}) {
|
||
|
const index = initialRouteName !== undefined && routeNames.includes(initialRouteName) ? routeNames.indexOf(initialRouteName) : 0;
|
||
|
const routes = routeNames.map(name => ({
|
||
|
name,
|
||
|
key: "".concat(name, "-").concat(nanoid()),
|
||
|
params: routeParamList[name]
|
||
|
}));
|
||
|
const history = getRouteHistory(routes, index, backBehavior, initialRouteName);
|
||
|
return {
|
||
|
stale: false,
|
||
|
type: 'tab',
|
||
|
key: "tab-".concat(nanoid()),
|
||
|
index,
|
||
|
routeNames,
|
||
|
history,
|
||
|
routes
|
||
|
};
|
||
|
},
|
||
|
|
||
|
getRehydratedState(partialState, {
|
||
|
routeNames,
|
||
|
routeParamList
|
||
|
}) {
|
||
|
var _state$routes, _state$index, _state$history$filter, _state$history;
|
||
|
|
||
|
let state = partialState;
|
||
|
|
||
|
if (state.stale === false) {
|
||
|
return state;
|
||
|
}
|
||
|
|
||
|
const routes = routeNames.map(name => {
|
||
|
const route = state.routes.find(r => r.name === name);
|
||
|
return { ...route,
|
||
|
name,
|
||
|
key: route && route.name === name && route.key ? route.key : "".concat(name, "-").concat(nanoid()),
|
||
|
params: routeParamList[name] !== undefined ? { ...routeParamList[name],
|
||
|
...(route ? route.params : undefined)
|
||
|
} : route ? route.params : undefined
|
||
|
};
|
||
|
});
|
||
|
const index = Math.min(Math.max(routeNames.indexOf((_state$routes = state.routes[(_state$index = state === null || state === void 0 ? void 0 : state.index) !== null && _state$index !== void 0 ? _state$index : 0]) === null || _state$routes === void 0 ? void 0 : _state$routes.name), 0), routes.length - 1);
|
||
|
const history = (_state$history$filter = (_state$history = state.history) === null || _state$history === void 0 ? void 0 : _state$history.filter(it => routes.find(r => r.key === it.key))) !== null && _state$history$filter !== void 0 ? _state$history$filter : [];
|
||
|
return changeIndex({
|
||
|
stale: false,
|
||
|
type: 'tab',
|
||
|
key: "tab-".concat(nanoid()),
|
||
|
index,
|
||
|
routeNames,
|
||
|
history,
|
||
|
routes
|
||
|
}, index, backBehavior, initialRouteName);
|
||
|
},
|
||
|
|
||
|
getStateForRouteNamesChange(state, {
|
||
|
routeNames,
|
||
|
routeParamList
|
||
|
}) {
|
||
|
const routes = routeNames.map(name => state.routes.find(r => r.name === name) || {
|
||
|
name,
|
||
|
key: "".concat(name, "-").concat(nanoid()),
|
||
|
params: routeParamList[name]
|
||
|
});
|
||
|
const index = Math.max(0, routeNames.indexOf(state.routes[state.index].name));
|
||
|
let history = state.history.filter( // Type will always be 'route' for tabs, but could be different in a router extending this (e.g. drawer)
|
||
|
it => it.type !== 'route' || routes.find(r => r.key === it.key));
|
||
|
|
||
|
if (!history.length) {
|
||
|
history = getRouteHistory(routes, index, backBehavior, initialRouteName);
|
||
|
}
|
||
|
|
||
|
return { ...state,
|
||
|
history,
|
||
|
routeNames,
|
||
|
routes,
|
||
|
index
|
||
|
};
|
||
|
},
|
||
|
|
||
|
getStateForRouteFocus(state, key) {
|
||
|
const index = state.routes.findIndex(r => r.key === key);
|
||
|
|
||
|
if (index === -1 || index === state.index) {
|
||
|
return state;
|
||
|
}
|
||
|
|
||
|
return changeIndex(state, index, backBehavior, initialRouteName);
|
||
|
},
|
||
|
|
||
|
getStateForAction(state, action, {
|
||
|
routeParamList
|
||
|
}) {
|
||
|
switch (action.type) {
|
||
|
case 'JUMP_TO':
|
||
|
case 'NAVIGATE':
|
||
|
{
|
||
|
let index = -1;
|
||
|
|
||
|
if (action.type === 'NAVIGATE' && action.payload.key) {
|
||
|
index = state.routes.findIndex(route => route.key === action.payload.key);
|
||
|
} else {
|
||
|
index = state.routes.findIndex(route => route.name === action.payload.name);
|
||
|
}
|
||
|
|
||
|
if (index === -1) {
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
return changeIndex({ ...state,
|
||
|
routes: action.payload.params !== undefined ? state.routes.map((route, i) => {
|
||
|
if (i !== index) {
|
||
|
return route;
|
||
|
}
|
||
|
|
||
|
let params;
|
||
|
|
||
|
if (action.type === 'NAVIGATE' && action.payload.merge === false) {
|
||
|
params = routeParamList[route.name] !== undefined ? { ...routeParamList[route.name],
|
||
|
...action.payload.params
|
||
|
} : action.payload.params;
|
||
|
} else {
|
||
|
params = action.payload.params ? { ...route.params,
|
||
|
...action.payload.params
|
||
|
} : route.params;
|
||
|
}
|
||
|
|
||
|
return params !== route.params ? { ...route,
|
||
|
params
|
||
|
} : route;
|
||
|
}) : state.routes
|
||
|
}, index, backBehavior, initialRouteName);
|
||
|
}
|
||
|
|
||
|
case 'GO_BACK':
|
||
|
{
|
||
|
if (state.history.length === 1) {
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
const previousKey = state.history[state.history.length - 2].key;
|
||
|
const index = state.routes.findIndex(route => route.key === previousKey);
|
||
|
|
||
|
if (index === -1) {
|
||
|
return null;
|
||
|
}
|
||
|
|
||
|
return { ...state,
|
||
|
history: state.history.slice(0, -1),
|
||
|
index
|
||
|
};
|
||
|
}
|
||
|
|
||
|
default:
|
||
|
return BaseRouter.getStateForAction(state, action);
|
||
|
}
|
||
|
},
|
||
|
|
||
|
shouldActionChangeFocus(action) {
|
||
|
return action.type === 'NAVIGATE';
|
||
|
},
|
||
|
|
||
|
actionCreators: TabActions
|
||
|
};
|
||
|
return router;
|
||
|
}
|
||
|
//# sourceMappingURL=TabRouter.js.map
|