feat(smart-app): implement complete mobile app MVP

- App.tsx: full navigation (Auth stack + Main tabs with 5 screens)
- Auth: LoginScreen, RegisterScreen, ForgotPasswordScreen
- HomeScreen: dashboard with IoT metrics, weather widget, alerts, quick actions, sensors
- MapScreen: interactive map with layer toggles (6 layers)
- MarketplaceScreen: categories (6), products (5), search
- ChatScreen: AI chat with quick prompts (4), bot responses
- ProfileScreen: user info, stats, menu (9 items), logout
- AlertsScreen: alert list with severity, acknowledge
- SensorsScreen: sensor list with type filters (6 types), search
- ZonesScreen: zone cards with stats
- SettingsScreen: language picker (FR/EN/ES/DE), privacy, about
- Stores: iotStore (sensors, zones, alerts), notificationStore, uiStore + i18n
- Hooks: useSensors, useAlerts, useNotifications, useLocation
- Components: Card, Button, LoadingSpinner, ErrorBoundary, Header
- Services: iotService, notificationService (with axios API client)
- Utils: formatters (temp, AQI, noise, dates), validators (email, password, IBAN)
- Theme: colors.ts with full design system (Blue Ocean palette)
- Ditto: fixed MongoDB connection, new JWT secrets, official gateway image
This commit is contained in:
Eric FELIXINE
2026-06-01 18:00:35 -04:00
parent 08ca495bde
commit e30ae8ed09
35578 changed files with 3703534 additions and 43 deletions

View File

@@ -0,0 +1,21 @@
MIT License
Copyright (c) 2017 React Navigation Contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
SOFTWARE.

View File

@@ -0,0 +1,17 @@
# `@react-navigation/routers`
Routers to help build custom navigators.
You probably don't need to use this package directly if you're not building custom navigators.
## Installation
Open a Terminal in your project's folder and run,
```sh
yarn add @react-navigation/routers
```
## Usage
Documentation can be found on the [React Navigation website](https://reactnavigation.org/docs/custom-routers/).

View File

@@ -0,0 +1,62 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.default = void 0;
var _nonSecure = require("nanoid/non-secure");
/**
* Base router object that can be used when writing custom routers.
* This provides few helper methods to handle common actions such as `RESET`.
*/
const BaseRouter = {
getStateForAction(state, action) {
switch (action.type) {
case 'SET_PARAMS':
{
const index = action.source ? state.routes.findIndex(r => r.key === action.source) : state.index;
if (index === -1) {
return null;
}
return {
...state,
routes: state.routes.map((r, i) => i === index ? {
...r,
params: {
...r.params,
...action.payload.params
}
} : r)
};
}
case 'RESET':
{
const nextState = action.payload;
if (nextState.routes.length === 0 || nextState.routes.some(route => !state.routeNames.includes(route.name))) {
return null;
}
if (nextState.stale === false) {
if (state.routeNames.length !== nextState.routeNames.length || nextState.routeNames.some(name => !state.routeNames.includes(name))) {
return null;
}
return {
...nextState,
routes: nextState.routes.map(route => route.key ? route : {
...route,
key: `${route.name}-${(0, _nonSecure.nanoid)()}`
})
};
}
return nextState;
}
default:
return null;
}
},
shouldActionChangeFocus(action) {
return action.type === 'NAVIGATE';
}
};
var _default = BaseRouter;
exports.default = _default;
//# sourceMappingURL=BaseRouter.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["BaseRouter","getStateForAction","state","action","type","index","source","routes","findIndex","r","key","map","i","params","payload","nextState","length","some","route","routeNames","includes","name","stale","nanoid","shouldActionChangeFocus"],"sourceRoot":"../../src","sources":["BaseRouter.tsx"],"mappings":";;;;;;AAAA;AAQA;AACA;AACA;AACA;AACA,MAAMA,UAAU,GAAG;EACjBC,iBAAiB,CACfC,KAAY,EACZC,MAA8B,EACM;IACpC,QAAQA,MAAM,CAACC,IAAI;MACjB,KAAK,YAAY;QAAE;UACjB,MAAMC,KAAK,GAAGF,MAAM,CAACG,MAAM,GACvBJ,KAAK,CAACK,MAAM,CAACC,SAAS,CAAEC,CAAC,IAAKA,CAAC,CAACC,GAAG,KAAKP,MAAM,CAACG,MAAM,CAAC,GACtDJ,KAAK,CAACG,KAAK;UAEf,IAAIA,KAAK,KAAK,CAAC,CAAC,EAAE;YAChB,OAAO,IAAI;UACb;UAEA,OAAO;YACL,GAAGH,KAAK;YACRK,MAAM,EAAEL,KAAK,CAACK,MAAM,CAACI,GAAG,CAAC,CAACF,CAAC,EAAEG,CAAC,KAC5BA,CAAC,KAAKP,KAAK,GACP;cAAE,GAAGI,CAAC;cAAEI,MAAM,EAAE;gBAAE,GAAGJ,CAAC,CAACI,MAAM;gBAAE,GAAGV,MAAM,CAACW,OAAO,CAACD;cAAO;YAAE,CAAC,GAC3DJ,CAAC;UAET,CAAC;QACH;MAEA,KAAK,OAAO;QAAE;UACZ,MAAMM,SAAS,GAAGZ,MAAM,CAACW,OAAsC;UAE/D,IACEC,SAAS,CAACR,MAAM,CAACS,MAAM,KAAK,CAAC,IAC7BD,SAAS,CAACR,MAAM,CAACU,IAAI,CAClBC,KAAuB,IAAK,CAAChB,KAAK,CAACiB,UAAU,CAACC,QAAQ,CAACF,KAAK,CAACG,IAAI,CAAC,CACpE,EACD;YACA,OAAO,IAAI;UACb;UAEA,IAAIN,SAAS,CAACO,KAAK,KAAK,KAAK,EAAE;YAC7B,IACEpB,KAAK,CAACiB,UAAU,CAACH,MAAM,KAAKD,SAAS,CAACI,UAAU,CAACH,MAAM,IACvDD,SAAS,CAACI,UAAU,CAACF,IAAI,CACtBI,IAAI,IAAK,CAACnB,KAAK,CAACiB,UAAU,CAACC,QAAQ,CAACC,IAAI,CAAC,CAC3C,EACD;cACA,OAAO,IAAI;YACb;YAEA,OAAO;cACL,GAAGN,SAAS;cACZR,MAAM,EAAEQ,SAAS,CAACR,MAAM,CAACI,GAAG,CAAEO,KAAK,IACjCA,KAAK,CAACR,GAAG,GAAGQ,KAAK,GAAG;gBAAE,GAAGA,KAAK;gBAAER,GAAG,EAAG,GAAEQ,KAAK,CAACG,IAAK,IAAG,IAAAE,iBAAM,GAAG;cAAE,CAAC;YAEtE,CAAC;UACH;UAEA,OAAOR,SAAS;QAClB;MAEA;QACE,OAAO,IAAI;IAAC;EAElB,CAAC;EAEDS,uBAAuB,CAACrB,MAA8B,EAAE;IACtD,OAAOA,MAAM,CAACC,IAAI,KAAK,UAAU;EACnC;AACF,CAAC;AAAC,eAEaJ,UAAU;AAAA"}

View File

@@ -0,0 +1,50 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.goBack = goBack;
exports.navigate = navigate;
exports.reset = reset;
exports.setParams = setParams;
function goBack() {
return {
type: 'GO_BACK'
};
}
// eslint-disable-next-line no-redeclare
function navigate() {
if (typeof (arguments.length <= 0 ? undefined : arguments[0]) === 'string') {
return {
type: 'NAVIGATE',
payload: {
name: arguments.length <= 0 ? undefined : arguments[0],
params: arguments.length <= 1 ? undefined : arguments[1]
}
};
} else {
const payload = (arguments.length <= 0 ? undefined : arguments[0]) || {};
if (!payload.hasOwnProperty('key') && !payload.hasOwnProperty('name')) {
throw new Error('You need to specify name or key when calling navigate with an object as the argument. See https://reactnavigation.org/docs/navigation-actions#navigate for usage.');
}
return {
type: 'NAVIGATE',
payload
};
}
}
function reset(state) {
return {
type: 'RESET',
payload: state
};
}
function setParams(params) {
return {
type: 'SET_PARAMS',
payload: {
params
}
};
}
//# sourceMappingURL=CommonActions.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["goBack","type","navigate","payload","name","params","hasOwnProperty","Error","reset","state","setParams"],"sourceRoot":"../../src","sources":["CommonActions.tsx"],"mappings":";;;;;;;;;AAgDO,SAASA,MAAM,GAAW;EAC/B,OAAO;IAAEC,IAAI,EAAE;EAAU,CAAC;AAC5B;AAeA;AACO,SAASC,QAAQ,GAAuB;EAC7C,IAAI,yDAAc,KAAK,QAAQ,EAAE;IAC/B,OAAO;MAAED,IAAI,EAAE,UAAU;MAAEE,OAAO,EAAE;QAAEC,IAAI,kDAAS;QAAEC,MAAM;MAAU;IAAE,CAAC;EAC1E,CAAC,MAAM;IACL,MAAMF,OAAO,GAAG,sDAAW,CAAC,CAAC;IAE7B,IAAI,CAACA,OAAO,CAACG,cAAc,CAAC,KAAK,CAAC,IAAI,CAACH,OAAO,CAACG,cAAc,CAAC,MAAM,CAAC,EAAE;MACrE,MAAM,IAAIC,KAAK,CACb,mKAAmK,CACpK;IACH;IAEA,OAAO;MAAEN,IAAI,EAAE,UAAU;MAAEE;IAAQ,CAAC;EACtC;AACF;AAEO,SAASK,KAAK,CAACC,KAA6B,EAAU;EAC3D,OAAO;IAAER,IAAI,EAAE,OAAO;IAAEE,OAAO,EAAEM;EAAM,CAAC;AAC1C;AAEO,SAASC,SAAS,CAACL,MAAc,EAAU;EAChD,OAAO;IAAEJ,IAAI,EAAE,YAAY;IAAEE,OAAO,EAAE;MAAEE;IAAO;EAAE,CAAC;AACpD"}

View File

@@ -0,0 +1,158 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.DrawerActions = void 0;
exports.default = DrawerRouter;
var _nonSecure = require("nanoid/non-secure");
var _TabRouter = _interopRequireWildcard(require("./TabRouter"));
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
const DrawerActions = {
..._TabRouter.TabActions,
openDrawer() {
return {
type: 'OPEN_DRAWER'
};
},
closeDrawer() {
return {
type: 'CLOSE_DRAWER'
};
},
toggleDrawer() {
return {
type: 'TOGGLE_DRAWER'
};
}
};
exports.DrawerActions = DrawerActions;
function DrawerRouter(_ref) {
let {
defaultStatus = 'closed',
...rest
} = _ref;
const router = (0, _TabRouter.default)(rest);
const isDrawerInHistory = state => {
var _state$history;
return Boolean((_state$history = state.history) === null || _state$history === void 0 ? void 0 : _state$history.some(it => it.type === 'drawer'));
};
const addDrawerToHistory = state => {
if (isDrawerInHistory(state)) {
return state;
}
return {
...state,
history: [...state.history, {
type: 'drawer',
status: defaultStatus === 'open' ? 'closed' : 'open'
}]
};
};
const removeDrawerFromHistory = state => {
if (!isDrawerInHistory(state)) {
return state;
}
return {
...state,
history: state.history.filter(it => it.type !== 'drawer')
};
};
const openDrawer = state => {
if (defaultStatus === 'open') {
return removeDrawerFromHistory(state);
}
return addDrawerToHistory(state);
};
const closeDrawer = state => {
if (defaultStatus === 'open') {
return addDrawerToHistory(state);
}
return removeDrawerFromHistory(state);
};
return {
...router,
type: 'drawer',
getInitialState(_ref2) {
let {
routeNames,
routeParamList,
routeGetIdList
} = _ref2;
const state = router.getInitialState({
routeNames,
routeParamList,
routeGetIdList
});
return {
...state,
default: defaultStatus,
stale: false,
type: 'drawer',
key: `drawer-${(0, _nonSecure.nanoid)()}`
};
},
getRehydratedState(partialState, _ref3) {
let {
routeNames,
routeParamList,
routeGetIdList
} = _ref3;
if (partialState.stale === false) {
return partialState;
}
let state = router.getRehydratedState(partialState, {
routeNames,
routeParamList,
routeGetIdList
});
if (isDrawerInHistory(partialState)) {
// Re-sync the drawer entry in history to correct it if it was wrong
state = removeDrawerFromHistory(state);
state = addDrawerToHistory(state);
}
return {
...state,
default: defaultStatus,
type: 'drawer',
key: `drawer-${(0, _nonSecure.nanoid)()}`
};
},
getStateForRouteFocus(state, key) {
const result = router.getStateForRouteFocus(state, key);
return closeDrawer(result);
},
getStateForAction(state, action, options) {
switch (action.type) {
case 'OPEN_DRAWER':
return openDrawer(state);
case 'CLOSE_DRAWER':
return closeDrawer(state);
case 'TOGGLE_DRAWER':
if (isDrawerInHistory(state)) {
return removeDrawerFromHistory(state);
}
return addDrawerToHistory(state);
case 'JUMP_TO':
case 'NAVIGATE':
{
const result = router.getStateForAction(state, action, options);
if (result != null && result.index !== state.index) {
return closeDrawer(result);
}
return result;
}
case 'GO_BACK':
if (isDrawerInHistory(state)) {
return removeDrawerFromHistory(state);
}
return router.getStateForAction(state, action, options);
default:
return router.getStateForAction(state, action, options);
}
},
actionCreators: DrawerActions
};
}
//# sourceMappingURL=DrawerRouter.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["DrawerActions","TabActions","openDrawer","type","closeDrawer","toggleDrawer","DrawerRouter","defaultStatus","rest","router","TabRouter","isDrawerInHistory","state","Boolean","history","some","it","addDrawerToHistory","status","removeDrawerFromHistory","filter","getInitialState","routeNames","routeParamList","routeGetIdList","default","stale","key","nanoid","getRehydratedState","partialState","getStateForRouteFocus","result","getStateForAction","action","options","index","actionCreators"],"sourceRoot":"../../src","sources":["DrawerRouter.tsx"],"mappings":"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"}

View File

@@ -0,0 +1,315 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.StackActions = void 0;
exports.default = StackRouter;
var _nonSecure = require("nanoid/non-secure");
var _BaseRouter = _interopRequireDefault(require("./BaseRouter"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const StackActions = {
replace(name, params) {
return {
type: 'REPLACE',
payload: {
name,
params
}
};
},
push(name, params) {
return {
type: 'PUSH',
payload: {
name,
params
}
};
},
pop() {
let count = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1;
return {
type: 'POP',
payload: {
count
}
};
},
popToTop() {
return {
type: 'POP_TO_TOP'
};
}
};
exports.StackActions = StackActions;
function StackRouter(options) {
const router = {
..._BaseRouter.default,
type: 'stack',
getInitialState(_ref) {
let {
routeNames,
routeParamList
} = _ref;
const initialRouteName = options.initialRouteName !== undefined && routeNames.includes(options.initialRouteName) ? options.initialRouteName : routeNames[0];
return {
stale: false,
type: 'stack',
key: `stack-${(0, _nonSecure.nanoid)()}`,
index: 0,
routeNames,
routes: [{
key: `${initialRouteName}-${(0, _nonSecure.nanoid)()}`,
name: initialRouteName,
params: routeParamList[initialRouteName]
}]
};
},
getRehydratedState(partialState, _ref2) {
let {
routeNames,
routeParamList
} = _ref2;
let state = partialState;
if (state.stale === false) {
return state;
}
const routes = state.routes.filter(route => routeNames.includes(route.name)).map(route => ({
...route,
key: route.key || `${route.name}-${(0, _nonSecure.nanoid)()}`,
params: routeParamList[route.name] !== undefined ? {
...routeParamList[route.name],
...route.params
} : route.params
}));
if (routes.length === 0) {
const initialRouteName = options.initialRouteName !== undefined ? options.initialRouteName : routeNames[0];
routes.push({
key: `${initialRouteName}-${(0, _nonSecure.nanoid)()}`,
name: initialRouteName,
params: routeParamList[initialRouteName]
});
}
return {
stale: false,
type: 'stack',
key: `stack-${(0, _nonSecure.nanoid)()}`,
index: routes.length - 1,
routeNames,
routes
};
},
getStateForRouteNamesChange(state, _ref3) {
let {
routeNames,
routeParamList,
routeKeyChanges
} = _ref3;
const routes = state.routes.filter(route => routeNames.includes(route.name) && !routeKeyChanges.includes(route.name));
if (routes.length === 0) {
const initialRouteName = options.initialRouteName !== undefined && routeNames.includes(options.initialRouteName) ? options.initialRouteName : routeNames[0];
routes.push({
key: `${initialRouteName}-${(0, _nonSecure.nanoid)()}`,
name: initialRouteName,
params: routeParamList[initialRouteName]
});
}
return {
...state,
routeNames,
routes,
index: Math.min(state.index, routes.length - 1)
};
},
getStateForRouteFocus(state, key) {
const index = state.routes.findIndex(r => r.key === key);
if (index === -1 || index === state.index) {
return state;
}
return {
...state,
index,
routes: state.routes.slice(0, index + 1)
};
},
getStateForAction(state, action, options) {
const {
routeParamList
} = options;
switch (action.type) {
case 'REPLACE':
{
const index = action.target === state.key && action.source ? state.routes.findIndex(r => r.key === action.source) : state.index;
if (index === -1) {
return null;
}
const {
name,
key,
params
} = action.payload;
if (!state.routeNames.includes(name)) {
return null;
}
return {
...state,
routes: state.routes.map((route, i) => i === index ? {
key: key !== undefined ? key : `${name}-${(0, _nonSecure.nanoid)()}`,
name,
params: routeParamList[name] !== undefined ? {
...routeParamList[name],
...params
} : params
} : route)
};
}
case 'PUSH':
if (state.routeNames.includes(action.payload.name)) {
const getId = options.routeGetIdList[action.payload.name];
const id = getId === null || getId === void 0 ? void 0 : getId({
params: action.payload.params
});
const route = id ? state.routes.find(route => route.name === action.payload.name && id === (getId === null || getId === void 0 ? void 0 : getId({
params: route.params
}))) : undefined;
let routes;
if (route) {
routes = state.routes.filter(r => r.key !== route.key);
routes.push({
...route,
params: routeParamList[action.payload.name] !== undefined ? {
...routeParamList[action.payload.name],
...action.payload.params
} : action.payload.params
});
} else {
routes = [...state.routes, {
key: `${action.payload.name}-${(0, _nonSecure.nanoid)()}`,
name: action.payload.name,
params: routeParamList[action.payload.name] !== undefined ? {
...routeParamList[action.payload.name],
...action.payload.params
} : action.payload.params
}];
}
return {
...state,
index: routes.length - 1,
routes
};
}
return null;
case 'POP':
{
const index = action.target === state.key && action.source ? state.routes.findIndex(r => r.key === action.source) : state.index;
if (index > 0) {
const count = Math.max(index - action.payload.count + 1, 1);
const routes = state.routes.slice(0, count).concat(state.routes.slice(index + 1));
return {
...state,
index: routes.length - 1,
routes
};
}
return null;
}
case 'POP_TO_TOP':
return router.getStateForAction(state, {
type: 'POP',
payload: {
count: state.routes.length - 1
}
}, options);
case 'NAVIGATE':
if (action.payload.name !== undefined && !state.routeNames.includes(action.payload.name)) {
return null;
}
if (action.payload.key || action.payload.name) {
// If the route already exists, navigate to that
let index = -1;
const getId =
// `getId` and `key` can't be used together
action.payload.key === undefined && action.payload.name !== undefined ? options.routeGetIdList[action.payload.name] : undefined;
const id = getId === null || getId === void 0 ? void 0 : getId({
params: action.payload.params
});
if (id) {
index = state.routes.findIndex(route => route.name === action.payload.name && id === (getId === null || getId === void 0 ? void 0 : getId({
params: route.params
})));
} else if (state.routes[state.index].name === action.payload.name && action.payload.key === undefined || state.routes[state.index].key === action.payload.key) {
index = state.index;
} else {
for (let i = state.routes.length - 1; i >= 0; i--) {
if (state.routes[i].name === action.payload.name && action.payload.key === undefined || state.routes[i].key === action.payload.key) {
index = i;
break;
}
}
}
if (index === -1 && action.payload.key && action.payload.name === undefined) {
return null;
}
if (index === -1 && action.payload.name !== undefined) {
const routes = [...state.routes, {
key: action.payload.key ?? `${action.payload.name}-${(0, _nonSecure.nanoid)()}`,
name: action.payload.name,
path: action.payload.path,
params: routeParamList[action.payload.name] !== undefined ? {
...routeParamList[action.payload.name],
...action.payload.params
} : action.payload.params
}];
return {
...state,
routes,
index: routes.length - 1
};
}
const route = state.routes[index];
let params;
if (action.payload.merge) {
params = action.payload.params !== undefined || routeParamList[route.name] !== undefined ? {
...routeParamList[route.name],
...route.params,
...action.payload.params
} : route.params;
} else {
params = routeParamList[route.name] !== undefined ? {
...routeParamList[route.name],
...action.payload.params
} : action.payload.params;
}
return {
...state,
index,
routes: [...state.routes.slice(0, index), params !== route.params || action.payload.path && action.payload.path !== route.path ? {
...route,
path: action.payload.path ?? route.path,
params
} : state.routes[index]]
};
}
return null;
case 'GO_BACK':
if (state.index > 0) {
return router.getStateForAction(state, {
type: 'POP',
payload: {
count: 1
},
target: action.target,
source: action.source
}, options);
}
return null;
default:
return _BaseRouter.default.getStateForAction(state, action);
}
},
actionCreators: StackActions
};
return router;
}
//# sourceMappingURL=StackRouter.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,259 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
exports.TabActions = void 0;
exports.default = TabRouter;
var _nonSecure = require("nanoid/non-secure");
var _BaseRouter = _interopRequireDefault(require("./BaseRouter"));
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
const TYPE_ROUTE = 'route';
const TabActions = {
jumpTo(name, params) {
return {
type: 'JUMP_TO',
payload: {
name,
params
}
};
}
};
exports.TabActions = TabActions;
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
};
};
function TabRouter(_ref) {
let {
initialRouteName,
backBehavior = 'firstRoute'
} = _ref;
const router = {
..._BaseRouter.default,
type: 'tab',
getInitialState(_ref2) {
let {
routeNames,
routeParamList
} = _ref2;
const index = initialRouteName !== undefined && routeNames.includes(initialRouteName) ? routeNames.indexOf(initialRouteName) : 0;
const routes = routeNames.map(name => ({
name,
key: `${name}-${(0, _nonSecure.nanoid)()}`,
params: routeParamList[name]
}));
const history = getRouteHistory(routes, index, backBehavior, initialRouteName);
return {
stale: false,
type: 'tab',
key: `tab-${(0, _nonSecure.nanoid)()}`,
index,
routeNames,
history,
routes
};
},
getRehydratedState(partialState, _ref3) {
var _state$routes, _state$history;
let {
routeNames,
routeParamList
} = _ref3;
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 : `${name}-${(0, _nonSecure.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 === null || state === void 0 ? void 0 : state.index) ?? 0]) === null || _state$routes === void 0 ? void 0 : _state$routes.name), 0), routes.length - 1);
const history = ((_state$history = state.history) === null || _state$history === void 0 ? void 0 : _state$history.filter(it => routes.find(r => r.key === it.key))) ?? [];
return changeIndex({
stale: false,
type: 'tab',
key: `tab-${(0, _nonSecure.nanoid)()}`,
index,
routeNames,
history,
routes
}, index, backBehavior, initialRouteName);
},
getStateForRouteNamesChange(state, _ref4) {
let {
routeNames,
routeParamList,
routeKeyChanges
} = _ref4;
const routes = routeNames.map(name => state.routes.find(r => r.name === name && !routeKeyChanges.includes(r.name)) || {
name,
key: `${name}-${(0, _nonSecure.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, _ref5) {
let {
routeParamList,
routeGetIdList
} = _ref5;
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: state.routes.map((route, i) => {
if (i !== index) {
return route;
}
const getId = routeGetIdList[route.name];
const currentId = getId === null || getId === void 0 ? void 0 : getId({
params: route.params
});
const nextId = getId === null || getId === void 0 ? void 0 : getId({
params: action.payload.params
});
const key = currentId === nextId ? route.key : `${route.name}-${(0, _nonSecure.nanoid)()}`;
let params;
if (action.type === 'NAVIGATE' && action.payload.merge && currentId === nextId) {
params = action.payload.params !== undefined || routeParamList[route.name] !== undefined ? {
...routeParamList[route.name],
...route.params,
...action.payload.params
} : route.params;
} else {
params = routeParamList[route.name] !== undefined ? {
...routeParamList[route.name],
...action.payload.params
} : action.payload.params;
}
const path = action.type === 'NAVIGATE' && action.payload.path != null ? action.payload.path : route.path;
return params !== route.params || path !== route.path ? {
...route,
key,
path,
params
} : route;
})
}, 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.default.getStateForAction(state, action);
}
},
shouldActionChangeFocus(action) {
return action.type === 'NAVIGATE';
},
actionCreators: TabActions
};
return router;
}
//# sourceMappingURL=TabRouter.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,80 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
var _exportNames = {
CommonActions: true,
BaseRouter: true,
DrawerActions: true,
DrawerRouter: true,
StackActions: true,
StackRouter: true,
TabActions: true,
TabRouter: true
};
Object.defineProperty(exports, "BaseRouter", {
enumerable: true,
get: function () {
return _BaseRouter.default;
}
});
exports.CommonActions = void 0;
Object.defineProperty(exports, "DrawerActions", {
enumerable: true,
get: function () {
return _DrawerRouter.DrawerActions;
}
});
Object.defineProperty(exports, "DrawerRouter", {
enumerable: true,
get: function () {
return _DrawerRouter.default;
}
});
Object.defineProperty(exports, "StackActions", {
enumerable: true,
get: function () {
return _StackRouter.StackActions;
}
});
Object.defineProperty(exports, "StackRouter", {
enumerable: true,
get: function () {
return _StackRouter.default;
}
});
Object.defineProperty(exports, "TabActions", {
enumerable: true,
get: function () {
return _TabRouter.TabActions;
}
});
Object.defineProperty(exports, "TabRouter", {
enumerable: true,
get: function () {
return _TabRouter.default;
}
});
var CommonActions = _interopRequireWildcard(require("./CommonActions"));
exports.CommonActions = CommonActions;
var _BaseRouter = _interopRequireDefault(require("./BaseRouter"));
var _DrawerRouter = _interopRequireWildcard(require("./DrawerRouter"));
var _StackRouter = _interopRequireWildcard(require("./StackRouter"));
var _TabRouter = _interopRequireWildcard(require("./TabRouter"));
var _types = require("./types");
Object.keys(_types).forEach(function (key) {
if (key === "default" || key === "__esModule") return;
if (Object.prototype.hasOwnProperty.call(_exportNames, key)) return;
if (key in exports && exports[key] === _types[key]) return;
Object.defineProperty(exports, key, {
enumerable: true,
get: function () {
return _types[key];
}
});
});
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; }
function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function (nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
function _interopRequireWildcard(obj, nodeInterop) { if (!nodeInterop && obj && obj.__esModule) { return obj; } if (obj === null || typeof obj !== "object" && typeof obj !== "function") { return { default: obj }; } var cache = _getRequireWildcardCache(nodeInterop); if (cache && cache.has(obj)) { return cache.get(obj); } var newObj = {}; var hasPropertyDescriptor = Object.defineProperty && Object.getOwnPropertyDescriptor; for (var key in obj) { if (key !== "default" && Object.prototype.hasOwnProperty.call(obj, key)) { var desc = hasPropertyDescriptor ? Object.getOwnPropertyDescriptor(obj, key) : null; if (desc && (desc.get || desc.set)) { Object.defineProperty(newObj, key, desc); } else { newObj[key] = obj[key]; } } } newObj.default = obj; if (cache) { cache.set(obj, newObj); } return newObj; }
//# sourceMappingURL=index.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":[],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AAAA;AAAiD;AAIjD;AAQA;AAOA;AAOA;AACA;AAAA;EAAA;EAAA;EAAA;EAAA;IAAA;IAAA;MAAA;IAAA;EAAA;AAAA;AAAwB;AAAA;AAAA"}

View File

@@ -0,0 +1,6 @@
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
//# sourceMappingURL=types.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":[],"sourceRoot":"../../src","sources":["types.tsx"],"mappings":""}

View File

@@ -0,0 +1,55 @@
import { nanoid } from 'nanoid/non-secure';
/**
* Base router object that can be used when writing custom routers.
* This provides few helper methods to handle common actions such as `RESET`.
*/
const BaseRouter = {
getStateForAction(state, action) {
switch (action.type) {
case 'SET_PARAMS':
{
const index = action.source ? state.routes.findIndex(r => r.key === action.source) : state.index;
if (index === -1) {
return null;
}
return {
...state,
routes: state.routes.map((r, i) => i === index ? {
...r,
params: {
...r.params,
...action.payload.params
}
} : r)
};
}
case 'RESET':
{
const nextState = action.payload;
if (nextState.routes.length === 0 || nextState.routes.some(route => !state.routeNames.includes(route.name))) {
return null;
}
if (nextState.stale === false) {
if (state.routeNames.length !== nextState.routeNames.length || nextState.routeNames.some(name => !state.routeNames.includes(name))) {
return null;
}
return {
...nextState,
routes: nextState.routes.map(route => route.key ? route : {
...route,
key: `${route.name}-${nanoid()}`
})
};
}
return nextState;
}
default:
return null;
}
},
shouldActionChangeFocus(action) {
return action.type === 'NAVIGATE';
}
};
export default BaseRouter;
//# sourceMappingURL=BaseRouter.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["nanoid","BaseRouter","getStateForAction","state","action","type","index","source","routes","findIndex","r","key","map","i","params","payload","nextState","length","some","route","routeNames","includes","name","stale","shouldActionChangeFocus"],"sourceRoot":"../../src","sources":["BaseRouter.tsx"],"mappings":"AAAA,SAASA,MAAM,QAAQ,mBAAmB;AAQ1C;AACA;AACA;AACA;AACA,MAAMC,UAAU,GAAG;EACjBC,iBAAiB,CACfC,KAAY,EACZC,MAA8B,EACM;IACpC,QAAQA,MAAM,CAACC,IAAI;MACjB,KAAK,YAAY;QAAE;UACjB,MAAMC,KAAK,GAAGF,MAAM,CAACG,MAAM,GACvBJ,KAAK,CAACK,MAAM,CAACC,SAAS,CAAEC,CAAC,IAAKA,CAAC,CAACC,GAAG,KAAKP,MAAM,CAACG,MAAM,CAAC,GACtDJ,KAAK,CAACG,KAAK;UAEf,IAAIA,KAAK,KAAK,CAAC,CAAC,EAAE;YAChB,OAAO,IAAI;UACb;UAEA,OAAO;YACL,GAAGH,KAAK;YACRK,MAAM,EAAEL,KAAK,CAACK,MAAM,CAACI,GAAG,CAAC,CAACF,CAAC,EAAEG,CAAC,KAC5BA,CAAC,KAAKP,KAAK,GACP;cAAE,GAAGI,CAAC;cAAEI,MAAM,EAAE;gBAAE,GAAGJ,CAAC,CAACI,MAAM;gBAAE,GAAGV,MAAM,CAACW,OAAO,CAACD;cAAO;YAAE,CAAC,GAC3DJ,CAAC;UAET,CAAC;QACH;MAEA,KAAK,OAAO;QAAE;UACZ,MAAMM,SAAS,GAAGZ,MAAM,CAACW,OAAsC;UAE/D,IACEC,SAAS,CAACR,MAAM,CAACS,MAAM,KAAK,CAAC,IAC7BD,SAAS,CAACR,MAAM,CAACU,IAAI,CAClBC,KAAuB,IAAK,CAAChB,KAAK,CAACiB,UAAU,CAACC,QAAQ,CAACF,KAAK,CAACG,IAAI,CAAC,CACpE,EACD;YACA,OAAO,IAAI;UACb;UAEA,IAAIN,SAAS,CAACO,KAAK,KAAK,KAAK,EAAE;YAC7B,IACEpB,KAAK,CAACiB,UAAU,CAACH,MAAM,KAAKD,SAAS,CAACI,UAAU,CAACH,MAAM,IACvDD,SAAS,CAACI,UAAU,CAACF,IAAI,CACtBI,IAAI,IAAK,CAACnB,KAAK,CAACiB,UAAU,CAACC,QAAQ,CAACC,IAAI,CAAC,CAC3C,EACD;cACA,OAAO,IAAI;YACb;YAEA,OAAO;cACL,GAAGN,SAAS;cACZR,MAAM,EAAEQ,SAAS,CAACR,MAAM,CAACI,GAAG,CAAEO,KAAK,IACjCA,KAAK,CAACR,GAAG,GAAGQ,KAAK,GAAG;gBAAE,GAAGA,KAAK;gBAAER,GAAG,EAAG,GAAEQ,KAAK,CAACG,IAAK,IAAGtB,MAAM,EAAG;cAAE,CAAC;YAEtE,CAAC;UACH;UAEA,OAAOgB,SAAS;QAClB;MAEA;QACE,OAAO,IAAI;IAAC;EAElB,CAAC;EAEDQ,uBAAuB,CAACpB,MAA8B,EAAE;IACtD,OAAOA,MAAM,CAACC,IAAI,KAAK,UAAU;EACnC;AACF,CAAC;AAED,eAAeJ,UAAU"}

View File

@@ -0,0 +1,41 @@
export function goBack() {
return {
type: 'GO_BACK'
};
}
// eslint-disable-next-line no-redeclare
export function navigate() {
if (typeof (arguments.length <= 0 ? undefined : arguments[0]) === 'string') {
return {
type: 'NAVIGATE',
payload: {
name: arguments.length <= 0 ? undefined : arguments[0],
params: arguments.length <= 1 ? undefined : arguments[1]
}
};
} else {
const payload = (arguments.length <= 0 ? undefined : arguments[0]) || {};
if (!payload.hasOwnProperty('key') && !payload.hasOwnProperty('name')) {
throw new Error('You need to specify name or key when calling navigate with an object as the argument. See https://reactnavigation.org/docs/navigation-actions#navigate for usage.');
}
return {
type: 'NAVIGATE',
payload
};
}
}
export function reset(state) {
return {
type: 'RESET',
payload: state
};
}
export function setParams(params) {
return {
type: 'SET_PARAMS',
payload: {
params
}
};
}
//# sourceMappingURL=CommonActions.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["goBack","type","navigate","payload","name","params","hasOwnProperty","Error","reset","state","setParams"],"sourceRoot":"../../src","sources":["CommonActions.tsx"],"mappings":"AAgDA,OAAO,SAASA,MAAM,GAAW;EAC/B,OAAO;IAAEC,IAAI,EAAE;EAAU,CAAC;AAC5B;AAeA;AACA,OAAO,SAASC,QAAQ,GAAuB;EAC7C,IAAI,yDAAc,KAAK,QAAQ,EAAE;IAC/B,OAAO;MAAED,IAAI,EAAE,UAAU;MAAEE,OAAO,EAAE;QAAEC,IAAI,kDAAS;QAAEC,MAAM;MAAU;IAAE,CAAC;EAC1E,CAAC,MAAM;IACL,MAAMF,OAAO,GAAG,sDAAW,CAAC,CAAC;IAE7B,IAAI,CAACA,OAAO,CAACG,cAAc,CAAC,KAAK,CAAC,IAAI,CAACH,OAAO,CAACG,cAAc,CAAC,MAAM,CAAC,EAAE;MACrE,MAAM,IAAIC,KAAK,CACb,mKAAmK,CACpK;IACH;IAEA,OAAO;MAAEN,IAAI,EAAE,UAAU;MAAEE;IAAQ,CAAC;EACtC;AACF;AAEA,OAAO,SAASK,KAAK,CAACC,KAA6B,EAAU;EAC3D,OAAO;IAAER,IAAI,EAAE,OAAO;IAAEE,OAAO,EAAEM;EAAM,CAAC;AAC1C;AAEA,OAAO,SAASC,SAAS,CAACL,MAAc,EAAU;EAChD,OAAO;IAAEJ,IAAI,EAAE,YAAY;IAAEE,OAAO,EAAE;MAAEE;IAAO;EAAE,CAAC;AACpD"}

View File

@@ -0,0 +1,148 @@
import { nanoid } from 'nanoid/non-secure';
import TabRouter, { TabActions } from './TabRouter';
export const DrawerActions = {
...TabActions,
openDrawer() {
return {
type: 'OPEN_DRAWER'
};
},
closeDrawer() {
return {
type: 'CLOSE_DRAWER'
};
},
toggleDrawer() {
return {
type: 'TOGGLE_DRAWER'
};
}
};
export default function DrawerRouter(_ref) {
let {
defaultStatus = 'closed',
...rest
} = _ref;
const router = TabRouter(rest);
const isDrawerInHistory = state => {
var _state$history;
return Boolean((_state$history = state.history) === null || _state$history === void 0 ? void 0 : _state$history.some(it => it.type === 'drawer'));
};
const addDrawerToHistory = state => {
if (isDrawerInHistory(state)) {
return state;
}
return {
...state,
history: [...state.history, {
type: 'drawer',
status: defaultStatus === 'open' ? 'closed' : 'open'
}]
};
};
const removeDrawerFromHistory = state => {
if (!isDrawerInHistory(state)) {
return state;
}
return {
...state,
history: state.history.filter(it => it.type !== 'drawer')
};
};
const openDrawer = state => {
if (defaultStatus === 'open') {
return removeDrawerFromHistory(state);
}
return addDrawerToHistory(state);
};
const closeDrawer = state => {
if (defaultStatus === 'open') {
return addDrawerToHistory(state);
}
return removeDrawerFromHistory(state);
};
return {
...router,
type: 'drawer',
getInitialState(_ref2) {
let {
routeNames,
routeParamList,
routeGetIdList
} = _ref2;
const state = router.getInitialState({
routeNames,
routeParamList,
routeGetIdList
});
return {
...state,
default: defaultStatus,
stale: false,
type: 'drawer',
key: `drawer-${nanoid()}`
};
},
getRehydratedState(partialState, _ref3) {
let {
routeNames,
routeParamList,
routeGetIdList
} = _ref3;
if (partialState.stale === false) {
return partialState;
}
let state = router.getRehydratedState(partialState, {
routeNames,
routeParamList,
routeGetIdList
});
if (isDrawerInHistory(partialState)) {
// Re-sync the drawer entry in history to correct it if it was wrong
state = removeDrawerFromHistory(state);
state = addDrawerToHistory(state);
}
return {
...state,
default: defaultStatus,
type: 'drawer',
key: `drawer-${nanoid()}`
};
},
getStateForRouteFocus(state, key) {
const result = router.getStateForRouteFocus(state, key);
return closeDrawer(result);
},
getStateForAction(state, action, options) {
switch (action.type) {
case 'OPEN_DRAWER':
return openDrawer(state);
case 'CLOSE_DRAWER':
return closeDrawer(state);
case 'TOGGLE_DRAWER':
if (isDrawerInHistory(state)) {
return removeDrawerFromHistory(state);
}
return addDrawerToHistory(state);
case 'JUMP_TO':
case 'NAVIGATE':
{
const result = router.getStateForAction(state, action, options);
if (result != null && result.index !== state.index) {
return closeDrawer(result);
}
return result;
}
case 'GO_BACK':
if (isDrawerInHistory(state)) {
return removeDrawerFromHistory(state);
}
return router.getStateForAction(state, action, options);
default:
return router.getStateForAction(state, action, options);
}
},
actionCreators: DrawerActions
};
}
//# sourceMappingURL=DrawerRouter.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["nanoid","TabRouter","TabActions","DrawerActions","openDrawer","type","closeDrawer","toggleDrawer","DrawerRouter","defaultStatus","rest","router","isDrawerInHistory","state","Boolean","history","some","it","addDrawerToHistory","status","removeDrawerFromHistory","filter","getInitialState","routeNames","routeParamList","routeGetIdList","default","stale","key","getRehydratedState","partialState","getStateForRouteFocus","result","getStateForAction","action","options","index","actionCreators"],"sourceRoot":"../../src","sources":["DrawerRouter.tsx"],"mappings":"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"}

View File

@@ -0,0 +1,306 @@
import { nanoid } from 'nanoid/non-secure';
import BaseRouter from './BaseRouter';
export const StackActions = {
replace(name, params) {
return {
type: 'REPLACE',
payload: {
name,
params
}
};
},
push(name, params) {
return {
type: 'PUSH',
payload: {
name,
params
}
};
},
pop() {
let count = arguments.length > 0 && arguments[0] !== undefined ? arguments[0] : 1;
return {
type: 'POP',
payload: {
count
}
};
},
popToTop() {
return {
type: 'POP_TO_TOP'
};
}
};
export default function StackRouter(options) {
const router = {
...BaseRouter,
type: 'stack',
getInitialState(_ref) {
let {
routeNames,
routeParamList
} = _ref;
const initialRouteName = options.initialRouteName !== undefined && routeNames.includes(options.initialRouteName) ? options.initialRouteName : routeNames[0];
return {
stale: false,
type: 'stack',
key: `stack-${nanoid()}`,
index: 0,
routeNames,
routes: [{
key: `${initialRouteName}-${nanoid()}`,
name: initialRouteName,
params: routeParamList[initialRouteName]
}]
};
},
getRehydratedState(partialState, _ref2) {
let {
routeNames,
routeParamList
} = _ref2;
let state = partialState;
if (state.stale === false) {
return state;
}
const routes = state.routes.filter(route => routeNames.includes(route.name)).map(route => ({
...route,
key: route.key || `${route.name}-${nanoid()}`,
params: routeParamList[route.name] !== undefined ? {
...routeParamList[route.name],
...route.params
} : route.params
}));
if (routes.length === 0) {
const initialRouteName = options.initialRouteName !== undefined ? options.initialRouteName : routeNames[0];
routes.push({
key: `${initialRouteName}-${nanoid()}`,
name: initialRouteName,
params: routeParamList[initialRouteName]
});
}
return {
stale: false,
type: 'stack',
key: `stack-${nanoid()}`,
index: routes.length - 1,
routeNames,
routes
};
},
getStateForRouteNamesChange(state, _ref3) {
let {
routeNames,
routeParamList,
routeKeyChanges
} = _ref3;
const routes = state.routes.filter(route => routeNames.includes(route.name) && !routeKeyChanges.includes(route.name));
if (routes.length === 0) {
const initialRouteName = options.initialRouteName !== undefined && routeNames.includes(options.initialRouteName) ? options.initialRouteName : routeNames[0];
routes.push({
key: `${initialRouteName}-${nanoid()}`,
name: initialRouteName,
params: routeParamList[initialRouteName]
});
}
return {
...state,
routeNames,
routes,
index: Math.min(state.index, routes.length - 1)
};
},
getStateForRouteFocus(state, key) {
const index = state.routes.findIndex(r => r.key === key);
if (index === -1 || index === state.index) {
return state;
}
return {
...state,
index,
routes: state.routes.slice(0, index + 1)
};
},
getStateForAction(state, action, options) {
const {
routeParamList
} = options;
switch (action.type) {
case 'REPLACE':
{
const index = action.target === state.key && action.source ? state.routes.findIndex(r => r.key === action.source) : state.index;
if (index === -1) {
return null;
}
const {
name,
key,
params
} = action.payload;
if (!state.routeNames.includes(name)) {
return null;
}
return {
...state,
routes: state.routes.map((route, i) => i === index ? {
key: key !== undefined ? key : `${name}-${nanoid()}`,
name,
params: routeParamList[name] !== undefined ? {
...routeParamList[name],
...params
} : params
} : route)
};
}
case 'PUSH':
if (state.routeNames.includes(action.payload.name)) {
const getId = options.routeGetIdList[action.payload.name];
const id = getId === null || getId === void 0 ? void 0 : getId({
params: action.payload.params
});
const route = id ? state.routes.find(route => route.name === action.payload.name && id === (getId === null || getId === void 0 ? void 0 : getId({
params: route.params
}))) : undefined;
let routes;
if (route) {
routes = state.routes.filter(r => r.key !== route.key);
routes.push({
...route,
params: routeParamList[action.payload.name] !== undefined ? {
...routeParamList[action.payload.name],
...action.payload.params
} : action.payload.params
});
} else {
routes = [...state.routes, {
key: `${action.payload.name}-${nanoid()}`,
name: action.payload.name,
params: routeParamList[action.payload.name] !== undefined ? {
...routeParamList[action.payload.name],
...action.payload.params
} : action.payload.params
}];
}
return {
...state,
index: routes.length - 1,
routes
};
}
return null;
case 'POP':
{
const index = action.target === state.key && action.source ? state.routes.findIndex(r => r.key === action.source) : state.index;
if (index > 0) {
const count = Math.max(index - action.payload.count + 1, 1);
const routes = state.routes.slice(0, count).concat(state.routes.slice(index + 1));
return {
...state,
index: routes.length - 1,
routes
};
}
return null;
}
case 'POP_TO_TOP':
return router.getStateForAction(state, {
type: 'POP',
payload: {
count: state.routes.length - 1
}
}, options);
case 'NAVIGATE':
if (action.payload.name !== undefined && !state.routeNames.includes(action.payload.name)) {
return null;
}
if (action.payload.key || action.payload.name) {
// If the route already exists, navigate to that
let index = -1;
const getId =
// `getId` and `key` can't be used together
action.payload.key === undefined && action.payload.name !== undefined ? options.routeGetIdList[action.payload.name] : undefined;
const id = getId === null || getId === void 0 ? void 0 : getId({
params: action.payload.params
});
if (id) {
index = state.routes.findIndex(route => route.name === action.payload.name && id === (getId === null || getId === void 0 ? void 0 : getId({
params: route.params
})));
} else if (state.routes[state.index].name === action.payload.name && action.payload.key === undefined || state.routes[state.index].key === action.payload.key) {
index = state.index;
} else {
for (let i = state.routes.length - 1; i >= 0; i--) {
if (state.routes[i].name === action.payload.name && action.payload.key === undefined || state.routes[i].key === action.payload.key) {
index = i;
break;
}
}
}
if (index === -1 && action.payload.key && action.payload.name === undefined) {
return null;
}
if (index === -1 && action.payload.name !== undefined) {
const routes = [...state.routes, {
key: action.payload.key ?? `${action.payload.name}-${nanoid()}`,
name: action.payload.name,
path: action.payload.path,
params: routeParamList[action.payload.name] !== undefined ? {
...routeParamList[action.payload.name],
...action.payload.params
} : action.payload.params
}];
return {
...state,
routes,
index: routes.length - 1
};
}
const route = state.routes[index];
let params;
if (action.payload.merge) {
params = action.payload.params !== undefined || routeParamList[route.name] !== undefined ? {
...routeParamList[route.name],
...route.params,
...action.payload.params
} : route.params;
} else {
params = routeParamList[route.name] !== undefined ? {
...routeParamList[route.name],
...action.payload.params
} : action.payload.params;
}
return {
...state,
index,
routes: [...state.routes.slice(0, index), params !== route.params || action.payload.path && action.payload.path !== route.path ? {
...route,
path: action.payload.path ?? route.path,
params
} : state.routes[index]]
};
}
return null;
case 'GO_BACK':
if (state.index > 0) {
return router.getStateForAction(state, {
type: 'POP',
payload: {
count: 1
},
target: action.target,
source: action.source
}, options);
}
return null;
default:
return BaseRouter.getStateForAction(state, action);
}
},
actionCreators: StackActions
};
return router;
}
//# sourceMappingURL=StackRouter.js.map

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,250 @@
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(_ref) {
let {
initialRouteName,
backBehavior = 'firstRoute'
} = _ref;
const router = {
...BaseRouter,
type: 'tab',
getInitialState(_ref2) {
let {
routeNames,
routeParamList
} = _ref2;
const index = initialRouteName !== undefined && routeNames.includes(initialRouteName) ? routeNames.indexOf(initialRouteName) : 0;
const routes = routeNames.map(name => ({
name,
key: `${name}-${nanoid()}`,
params: routeParamList[name]
}));
const history = getRouteHistory(routes, index, backBehavior, initialRouteName);
return {
stale: false,
type: 'tab',
key: `tab-${nanoid()}`,
index,
routeNames,
history,
routes
};
},
getRehydratedState(partialState, _ref3) {
var _state$routes, _state$history;
let {
routeNames,
routeParamList
} = _ref3;
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 : `${name}-${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 === null || state === void 0 ? void 0 : state.index) ?? 0]) === null || _state$routes === void 0 ? void 0 : _state$routes.name), 0), routes.length - 1);
const history = ((_state$history = state.history) === null || _state$history === void 0 ? void 0 : _state$history.filter(it => routes.find(r => r.key === it.key))) ?? [];
return changeIndex({
stale: false,
type: 'tab',
key: `tab-${nanoid()}`,
index,
routeNames,
history,
routes
}, index, backBehavior, initialRouteName);
},
getStateForRouteNamesChange(state, _ref4) {
let {
routeNames,
routeParamList,
routeKeyChanges
} = _ref4;
const routes = routeNames.map(name => state.routes.find(r => r.name === name && !routeKeyChanges.includes(r.name)) || {
name,
key: `${name}-${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, _ref5) {
let {
routeParamList,
routeGetIdList
} = _ref5;
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: state.routes.map((route, i) => {
if (i !== index) {
return route;
}
const getId = routeGetIdList[route.name];
const currentId = getId === null || getId === void 0 ? void 0 : getId({
params: route.params
});
const nextId = getId === null || getId === void 0 ? void 0 : getId({
params: action.payload.params
});
const key = currentId === nextId ? route.key : `${route.name}-${nanoid()}`;
let params;
if (action.type === 'NAVIGATE' && action.payload.merge && currentId === nextId) {
params = action.payload.params !== undefined || routeParamList[route.name] !== undefined ? {
...routeParamList[route.name],
...route.params,
...action.payload.params
} : route.params;
} else {
params = routeParamList[route.name] !== undefined ? {
...routeParamList[route.name],
...action.payload.params
} : action.payload.params;
}
const path = action.type === 'NAVIGATE' && action.payload.path != null ? action.payload.path : route.path;
return params !== route.params || path !== route.path ? {
...route,
key,
path,
params
} : route;
})
}, 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

File diff suppressed because one or more lines are too long

View File

@@ -0,0 +1,8 @@
import * as CommonActions from './CommonActions';
export { CommonActions };
export { default as BaseRouter } from './BaseRouter';
export { DrawerActions, default as DrawerRouter } from './DrawerRouter';
export { StackActions, default as StackRouter } from './StackRouter';
export { TabActions, default as TabRouter } from './TabRouter';
export * from './types';
//# sourceMappingURL=index.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":["CommonActions","default","BaseRouter","DrawerActions","DrawerRouter","StackActions","StackRouter","TabActions","TabRouter"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":"AAAA,OAAO,KAAKA,aAAa,MAAM,iBAAiB;AAEhD,SAASA,aAAa;AAEtB,SAASC,OAAO,IAAIC,UAAU,QAAQ,cAAc;AAQpD,SAASC,aAAa,EAAEF,OAAO,IAAIG,YAAY,QAAQ,gBAAgB;AAOvE,SAASC,YAAY,EAAEJ,OAAO,IAAIK,WAAW,QAAQ,eAAe;AAOpE,SAASC,UAAU,EAAEN,OAAO,IAAIO,SAAS,QAAQ,aAAa;AAC9D,cAAc,SAAS"}

View File

@@ -0,0 +1,2 @@
export {};
//# sourceMappingURL=types.js.map

View File

@@ -0,0 +1 @@
{"version":3,"names":[],"sourceRoot":"../../src","sources":["types.tsx"],"mappings":""}

View File

@@ -0,0 +1,27 @@
import type { CommonNavigationAction, PartialState } from './types';
/**
* Base router object that can be used when writing custom routers.
* This provides few helper methods to handle common actions such as `RESET`.
*/
declare const BaseRouter: {
getStateForAction<State extends Readonly<{
key: string;
index: number;
routeNames: string[];
history?: unknown[] | undefined;
routes: (Readonly<{
key: string;
name: string;
path?: string | undefined;
}> & Readonly<{
params?: Readonly<object | undefined>;
}> & {
state?: Readonly<any> | PartialState<Readonly<any>> | undefined;
})[];
type: string;
stale: false;
}>>(state: State, action: CommonNavigationAction): State | PartialState<State> | null;
shouldActionChangeFocus(action: CommonNavigationAction): boolean;
};
export default BaseRouter;
//# sourceMappingURL=BaseRouter.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"BaseRouter.d.ts","sourceRoot":"","sources":["../../../src/BaseRouter.tsx"],"names":[],"mappings":"AAEA,OAAO,KAAK,EACV,sBAAsB,EAEtB,YAAY,EACb,MAAM,SAAS,CAAC;AAEjB;;;GAGG;AACH,QAAA,MAAM,UAAU;;;;;;;;;;;;;;;;;8BAGJ,sBAAsB;oCA4DA,sBAAsB;CAGvD,CAAC;AAEF,eAAe,UAAU,CAAC"}

View File

@@ -0,0 +1,56 @@
import type { NavigationState, PartialState, Route } from './types';
type ResetState = PartialState<NavigationState> | NavigationState | (Omit<NavigationState, 'routes'> & {
routes: Omit<Route<string>, 'key'>[];
});
export type Action = {
type: 'GO_BACK';
source?: string;
target?: string;
} | {
type: 'NAVIGATE';
payload: {
key: string;
name?: undefined;
params?: object;
path?: string;
merge?: boolean;
} | {
name: string;
key?: string;
params?: object;
path?: string;
merge?: boolean;
};
source?: string;
target?: string;
} | {
type: 'RESET';
payload: ResetState | undefined;
source?: string;
target?: string;
} | {
type: 'SET_PARAMS';
payload: {
params?: object;
};
source?: string;
target?: string;
};
export declare function goBack(): Action;
export declare function navigate(options: {
key: string;
params?: object;
path?: string;
merge?: boolean;
} | {
name: string;
key?: string;
params?: object;
path?: string;
merge?: boolean;
}): Action;
export declare function navigate(name: string, params?: object): Action;
export declare function reset(state: ResetState | undefined): Action;
export declare function setParams(params: object): Action;
export {};
//# sourceMappingURL=CommonActions.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"CommonActions.d.ts","sourceRoot":"","sources":["../../../src/CommonActions.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,KAAK,EAAE,MAAM,SAAS,CAAC;AAEpE,KAAK,UAAU,GACX,YAAY,CAAC,eAAe,CAAC,GAC7B,eAAe,GACf,CAAC,IAAI,CAAC,eAAe,EAAE,QAAQ,CAAC,GAAG;IACjC,MAAM,EAAE,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,EAAE,KAAK,CAAC,EAAE,CAAC;CACtC,CAAC,CAAC;AAEP,MAAM,MAAM,MAAM,GACd;IACE,IAAI,EAAE,SAAS,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GACD;IACE,IAAI,EAAE,UAAU,CAAC;IACjB,OAAO,EACH;QACE,GAAG,EAAE,MAAM,CAAC;QACZ,IAAI,CAAC,EAAE,SAAS,CAAC;QACjB,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,KAAK,CAAC,EAAE,OAAO,CAAC;KACjB,GACD;QACE,IAAI,EAAE,MAAM,CAAC;QACb,GAAG,CAAC,EAAE,MAAM,CAAC;QACb,MAAM,CAAC,EAAE,MAAM,CAAC;QAChB,IAAI,CAAC,EAAE,MAAM,CAAC;QACd,KAAK,CAAC,EAAE,OAAO,CAAC;KACjB,CAAC;IACN,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GACD;IACE,IAAI,EAAE,OAAO,CAAC;IACd,OAAO,EAAE,UAAU,GAAG,SAAS,CAAC;IAChC,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GACD;IACE,IAAI,EAAE,YAAY,CAAC;IACnB,OAAO,EAAE;QAAE,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC7B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEN,wBAAgB,MAAM,IAAI,MAAM,CAE/B;AAED,wBAAgB,QAAQ,CACtB,OAAO,EACH;IAAE,GAAG,EAAE,MAAM,CAAC;IAAC,MAAM,CAAC,EAAE,MAAM,CAAC;IAAC,IAAI,CAAC,EAAE,MAAM,CAAC;IAAC,KAAK,CAAC,EAAE,OAAO,CAAA;CAAE,GAChE;IACE,IAAI,EAAE,MAAM,CAAC;IACb,GAAG,CAAC,EAAE,MAAM,CAAC;IACb,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,KAAK,CAAC,EAAE,OAAO,CAAC;CACjB,GACJ,MAAM,CAAC;AAEV,wBAAgB,QAAQ,CAAC,IAAI,EAAE,MAAM,EAAE,MAAM,CAAC,EAAE,MAAM,GAAG,MAAM,CAAC;AAkBhE,wBAAgB,KAAK,CAAC,KAAK,EAAE,UAAU,GAAG,SAAS,GAAG,MAAM,CAE3D;AAED,wBAAgB,SAAS,CAAC,MAAM,EAAE,MAAM,GAAG,MAAM,CAEhD"}

View File

@@ -0,0 +1,53 @@
import { TabActionHelpers, TabActionType, TabNavigationState, TabRouterOptions } from './TabRouter';
import type { CommonNavigationAction, ParamListBase, Router } from './types';
export type DrawerStatus = 'open' | 'closed';
export type DrawerActionType = TabActionType | {
type: 'OPEN_DRAWER' | 'CLOSE_DRAWER' | 'TOGGLE_DRAWER';
source?: string;
target?: string;
};
export type DrawerRouterOptions = TabRouterOptions & {
defaultStatus?: DrawerStatus;
};
export type DrawerNavigationState<ParamList extends ParamListBase> = Omit<TabNavigationState<ParamList>, 'type' | 'history'> & {
/**
* Type of the router, in this case, it's drawer.
*/
type: 'drawer';
/**
* Default status of the drawer.
*/
default: DrawerStatus;
/**
* List of previously visited route keys and drawer open status.
*/
history: ({
type: 'route';
key: string;
} | {
type: 'drawer';
status: DrawerStatus;
})[];
};
export type DrawerActionHelpers<ParamList extends ParamListBase> = TabActionHelpers<ParamList> & {
/**
* Open the drawer sidebar.
*/
openDrawer(): void;
/**
* Close the drawer sidebar.
*/
closeDrawer(): void;
/**
* Open the drawer sidebar if closed, or close if opened.
*/
toggleDrawer(): void;
};
export declare const DrawerActions: {
openDrawer(): DrawerActionType;
closeDrawer(): DrawerActionType;
toggleDrawer(): DrawerActionType;
jumpTo(name: string, params?: object | undefined): TabActionType;
};
export default function DrawerRouter({ defaultStatus, ...rest }: DrawerRouterOptions): Router<DrawerNavigationState<ParamListBase>, DrawerActionType | CommonNavigationAction>;
//# sourceMappingURL=DrawerRouter.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"DrawerRouter.d.ts","sourceRoot":"","sources":["../../../src/DrawerRouter.tsx"],"names":[],"mappings":"AAEA,OAAkB,EAChB,gBAAgB,EAEhB,aAAa,EACb,kBAAkB,EAClB,gBAAgB,EACjB,MAAM,aAAa,CAAC;AACrB,OAAO,KAAK,EACV,sBAAsB,EACtB,aAAa,EAEb,MAAM,EACP,MAAM,SAAS,CAAC;AACjB,MAAM,MAAM,YAAY,GAAG,MAAM,GAAG,QAAQ,CAAC;AAE7C,MAAM,MAAM,gBAAgB,GACxB,aAAa,GACb;IACE,IAAI,EAAE,aAAa,GAAG,cAAc,GAAG,eAAe,CAAC;IACvD,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEN,MAAM,MAAM,mBAAmB,GAAG,gBAAgB,GAAG;IACnD,aAAa,CAAC,EAAE,YAAY,CAAC;CAC9B,CAAC;AAEF,MAAM,MAAM,qBAAqB,CAAC,SAAS,SAAS,aAAa,IAAI,IAAI,CACvE,kBAAkB,CAAC,SAAS,CAAC,EAC7B,MAAM,GAAG,SAAS,CACnB,GAAG;IACF;;OAEG;IACH,IAAI,EAAE,QAAQ,CAAC;IACf;;OAEG;IACH,OAAO,EAAE,YAAY,CAAC;IACtB;;OAEG;IACH,OAAO,EAAE,CACL;QAAE,IAAI,EAAE,OAAO,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,GAC9B;QAAE,IAAI,EAAE,QAAQ,CAAC;QAAC,MAAM,EAAE,YAAY,CAAA;KAAE,CAC3C,EAAE,CAAC;CACL,CAAC;AAEF,MAAM,MAAM,mBAAmB,CAAC,SAAS,SAAS,aAAa,IAC7D,gBAAgB,CAAC,SAAS,CAAC,GAAG;IAC5B;;OAEG;IACH,UAAU,IAAI,IAAI,CAAC;IAEnB;;OAEG;IACH,WAAW,IAAI,IAAI,CAAC;IAEpB;;OAEG;IACH,YAAY,IAAI,IAAI,CAAC;CACtB,CAAC;AAEJ,eAAO,MAAM,aAAa;kBAEV,gBAAgB;mBAGf,gBAAgB;oBAGf,gBAAgB;;CAGjC,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,YAAY,CAAC,EACnC,aAAwB,EACxB,GAAG,IAAI,EACR,EAAE,mBAAmB,GAAG,MAAM,CAC7B,qBAAqB,CAAC,aAAa,CAAC,EACpC,gBAAgB,GAAG,sBAAsB,CAC1C,CA+JA"}

View File

@@ -0,0 +1,69 @@
import type { DefaultRouterOptions, NavigationState, ParamListBase, Router } from './types';
export type StackActionType = {
type: 'REPLACE';
payload: {
name: string;
key?: string | undefined;
params?: object;
};
source?: string;
target?: string;
} | {
type: 'PUSH';
payload: {
name: string;
params?: object;
};
source?: string;
target?: string;
} | {
type: 'POP';
payload: {
count: number;
};
source?: string;
target?: string;
} | {
type: 'POP_TO_TOP';
source?: string;
target?: string;
};
export type StackRouterOptions = DefaultRouterOptions;
export type StackNavigationState<ParamList extends ParamListBase> = NavigationState<ParamList> & {
/**
* Type of the router, in this case, it's stack.
*/
type: 'stack';
};
export type StackActionHelpers<ParamList extends ParamListBase> = {
/**
* Replace the current route with a new one.
*
* @param name Route name of the new route.
* @param [params] Params object for the new route.
*/
replace<RouteName extends keyof ParamList>(...args: undefined extends ParamList[RouteName] ? [screen: RouteName] | [screen: RouteName, params: ParamList[RouteName]] : [screen: RouteName, params: ParamList[RouteName]]): void;
/**
* Push a new screen onto the stack.
*
* @param name Name of the route for the tab.
* @param [params] Params object for the route.
*/
push<RouteName extends keyof ParamList>(...args: undefined extends ParamList[RouteName] ? [screen: RouteName] | [screen: RouteName, params: ParamList[RouteName]] : [screen: RouteName, params: ParamList[RouteName]]): void;
/**
* Pop a screen from the stack.
*/
pop(count?: number): void;
/**
* Pop to the first route in the stack, dismissing all other screens.
*/
popToTop(): void;
};
export declare const StackActions: {
replace(name: string, params?: object): StackActionType;
push(name: string, params?: object): StackActionType;
pop(count?: number): StackActionType;
popToTop(): StackActionType;
};
export default function StackRouter(options: StackRouterOptions): Router<StackNavigationState<ParamListBase>, import("./CommonActions").Action | StackActionType>;
//# sourceMappingURL=StackRouter.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"StackRouter.d.ts","sourceRoot":"","sources":["../../../src/StackRouter.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAEV,oBAAoB,EACpB,eAAe,EACf,aAAa,EAEb,MAAM,EACP,MAAM,SAAS,CAAC;AAEjB,MAAM,MAAM,eAAe,GACvB;IACE,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,GAAG,CAAC,EAAE,MAAM,GAAG,SAAS,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IACrE,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GACD;IACE,IAAI,EAAE,MAAM,CAAC;IACb,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GACD;IACE,IAAI,EAAE,KAAK,CAAC;IACZ,OAAO,EAAE;QAAE,KAAK,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3B,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,GACD;IACE,IAAI,EAAE,YAAY,CAAC;IACnB,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEN,MAAM,MAAM,kBAAkB,GAAG,oBAAoB,CAAC;AAEtD,MAAM,MAAM,oBAAoB,CAAC,SAAS,SAAS,aAAa,IAC9D,eAAe,CAAC,SAAS,CAAC,GAAG;IAC3B;;OAEG;IACH,IAAI,EAAE,OAAO,CAAC;CACf,CAAC;AAEJ,MAAM,MAAM,kBAAkB,CAAC,SAAS,SAAS,aAAa,IAAI;IAChE;;;;;OAKG;IACH,OAAO,CAAC,SAAS,SAAS,MAAM,SAAS,EACvC,GAAG,IAAI,EAAE,SAAS,SAAS,SAAS,CAAC,SAAS,CAAC,GAC3C,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC,GACvE,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC,GACpD,IAAI,CAAC;IAER;;;;;OAKG;IACH,IAAI,CAAC,SAAS,SAAS,MAAM,SAAS,EACpC,GAAG,IAAI,EAAE,SAAS,SAAS,SAAS,CAAC,SAAS,CAAC,GAC3C,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC,GACvE,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC,GACpD,IAAI,CAAC;IAER;;OAEG;IACH,GAAG,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,IAAI,CAAC;IAE1B;;OAEG;IACH,QAAQ,IAAI,IAAI,CAAC;CAClB,CAAC;AAEF,eAAO,MAAM,YAAY;kBACT,MAAM,WAAW,MAAM,GAAG,eAAe;eAG5C,MAAM,WAAW,MAAM,GAAG,eAAe;gBAGzC,MAAM,GAAO,eAAe;gBAG3B,eAAe;CAG5B,CAAC;AAEF,MAAM,CAAC,OAAO,UAAU,WAAW,CAAC,OAAO,EAAE,kBAAkB,mGA4Y9D"}

View File

@@ -0,0 +1,41 @@
import type { DefaultRouterOptions, NavigationState, ParamListBase, Router } from './types';
export type TabActionType = {
type: 'JUMP_TO';
payload: {
name: string;
params?: object;
};
source?: string;
target?: string;
};
export type BackBehavior = 'initialRoute' | 'firstRoute' | 'history' | 'order' | 'none';
export type TabRouterOptions = DefaultRouterOptions & {
backBehavior?: BackBehavior;
};
export type TabNavigationState<ParamList extends ParamListBase> = Omit<NavigationState<ParamList>, 'history'> & {
/**
* Type of the router, in this case, it's tab.
*/
type: 'tab';
/**
* List of previously visited route keys.
*/
history: {
type: 'route';
key: string;
}[];
};
export type TabActionHelpers<ParamList extends ParamListBase> = {
/**
* Jump to an existing tab.
*
* @param name Name of the route for the tab.
* @param [params] Params object for the route.
*/
jumpTo<RouteName extends Extract<keyof ParamList, string>>(...args: undefined extends ParamList[RouteName] ? [screen: RouteName] | [screen: RouteName, params: ParamList[RouteName]] : [screen: RouteName, params: ParamList[RouteName]]): void;
};
export declare const TabActions: {
jumpTo(name: string, params?: object): TabActionType;
};
export default function TabRouter({ initialRouteName, backBehavior, }: TabRouterOptions): Router<TabNavigationState<ParamListBase>, import("./CommonActions").Action | TabActionType>;
//# sourceMappingURL=TabRouter.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"TabRouter.d.ts","sourceRoot":"","sources":["../../../src/TabRouter.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EAEV,oBAAoB,EACpB,eAAe,EACf,aAAa,EAGb,MAAM,EACP,MAAM,SAAS,CAAC;AAEjB,MAAM,MAAM,aAAa,GAAG;IAC1B,IAAI,EAAE,SAAS,CAAC;IAChB,OAAO,EAAE;QAAE,IAAI,EAAE,MAAM,CAAC;QAAC,MAAM,CAAC,EAAE,MAAM,CAAA;KAAE,CAAC;IAC3C,MAAM,CAAC,EAAE,MAAM,CAAC;IAChB,MAAM,CAAC,EAAE,MAAM,CAAC;CACjB,CAAC;AAEF,MAAM,MAAM,YAAY,GACpB,cAAc,GACd,YAAY,GACZ,SAAS,GACT,OAAO,GACP,MAAM,CAAC;AAEX,MAAM,MAAM,gBAAgB,GAAG,oBAAoB,GAAG;IACpD,YAAY,CAAC,EAAE,YAAY,CAAC;CAC7B,CAAC;AAEF,MAAM,MAAM,kBAAkB,CAAC,SAAS,SAAS,aAAa,IAAI,IAAI,CACpE,eAAe,CAAC,SAAS,CAAC,EAC1B,SAAS,CACV,GAAG;IACF;;OAEG;IACH,IAAI,EAAE,KAAK,CAAC;IACZ;;OAEG;IACH,OAAO,EAAE;QAAE,IAAI,EAAE,OAAO,CAAC;QAAC,GAAG,EAAE,MAAM,CAAA;KAAE,EAAE,CAAC;CAC3C,CAAC;AAEF,MAAM,MAAM,gBAAgB,CAAC,SAAS,SAAS,aAAa,IAAI;IAC9D;;;;;OAKG;IACH,MAAM,CAAC,SAAS,SAAS,OAAO,CAAC,MAAM,SAAS,EAAE,MAAM,CAAC,EACvD,GAAG,IAAI,EAAE,SAAS,SAAS,SAAS,CAAC,SAAS,CAAC,GAC3C,CAAC,MAAM,EAAE,SAAS,CAAC,GAAG,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC,GACvE,CAAC,MAAM,EAAE,SAAS,EAAE,MAAM,EAAE,SAAS,CAAC,SAAS,CAAC,CAAC,GACpD,IAAI,CAAC;CACT,CAAC;AAIF,eAAO,MAAM,UAAU;iBACR,MAAM,WAAW,MAAM,GAAG,aAAa;CAGrD,CAAC;AA4EF,MAAM,CAAC,OAAO,UAAU,SAAS,CAAC,EAChC,gBAAgB,EAChB,YAA2B,GAC5B,EAAE,gBAAgB,+FAsQlB"}

View File

@@ -0,0 +1,11 @@
import * as CommonActions from './CommonActions';
export { CommonActions };
export { default as BaseRouter } from './BaseRouter';
export type { DrawerActionHelpers, DrawerActionType, DrawerNavigationState, DrawerRouterOptions, DrawerStatus, } from './DrawerRouter';
export { DrawerActions, default as DrawerRouter } from './DrawerRouter';
export type { StackActionHelpers, StackActionType, StackNavigationState, StackRouterOptions, } from './StackRouter';
export { StackActions, default as StackRouter } from './StackRouter';
export type { TabActionHelpers, TabActionType, TabNavigationState, TabRouterOptions, } from './TabRouter';
export { TabActions, default as TabRouter } from './TabRouter';
export * from './types';
//# sourceMappingURL=index.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,aAAa,MAAM,iBAAiB,CAAC;AAEjD,OAAO,EAAE,aAAa,EAAE,CAAC;AAEzB,OAAO,EAAE,OAAO,IAAI,UAAU,EAAE,MAAM,cAAc,CAAC;AACrD,YAAY,EACV,mBAAmB,EACnB,gBAAgB,EAChB,qBAAqB,EACrB,mBAAmB,EACnB,YAAY,GACb,MAAM,gBAAgB,CAAC;AACxB,OAAO,EAAE,aAAa,EAAE,OAAO,IAAI,YAAY,EAAE,MAAM,gBAAgB,CAAC;AACxE,YAAY,EACV,kBAAkB,EAClB,eAAe,EACf,oBAAoB,EACpB,kBAAkB,GACnB,MAAM,eAAe,CAAC;AACvB,OAAO,EAAE,YAAY,EAAE,OAAO,IAAI,WAAW,EAAE,MAAM,eAAe,CAAC;AACrE,YAAY,EACV,gBAAgB,EAChB,aAAa,EACb,kBAAkB,EAClB,gBAAgB,GACjB,MAAM,aAAa,CAAC;AACrB,OAAO,EAAE,UAAU,EAAE,OAAO,IAAI,SAAS,EAAE,MAAM,aAAa,CAAC;AAC/D,cAAc,SAAS,CAAC"}

View File

@@ -0,0 +1,177 @@
import type * as CommonActions from './CommonActions';
export type CommonNavigationAction = CommonActions.Action;
type NavigationRoute<ParamList extends ParamListBase, RouteName extends keyof ParamList> = Route<Extract<RouteName, string>, ParamList[RouteName]> & {
state?: NavigationState | PartialState<NavigationState>;
};
export type NavigationState<ParamList extends ParamListBase = ParamListBase> = Readonly<{
/**
* Unique key for the navigation state.
*/
key: string;
/**
* Index of the currently focused route.
*/
index: number;
/**
* List of valid route names as defined in the screen components.
*/
routeNames: Extract<keyof ParamList, string>[];
/**
* Alternative entries for history.
*/
history?: unknown[];
/**
* List of rendered routes.
*/
routes: NavigationRoute<ParamList, keyof ParamList>[];
/**
* Custom type for the state, whether it's for tab, stack, drawer etc.
* During rehydration, the state will be discarded if type doesn't match with router type.
* It can also be used to detect the type of the navigator we're dealing with.
*/
type: string;
/**
* Whether the navigation state has been rehydrated.
*/
stale: false;
}>;
export type InitialState = Readonly<Partial<Omit<NavigationState, 'stale' | 'routes'>> & {
routes: (Omit<Route<string>, 'key'> & {
state?: InitialState;
})[];
}>;
export type PartialRoute<R extends Route<string>> = Omit<R, 'key'> & {
key?: string;
state?: PartialState<NavigationState>;
};
export type PartialState<State extends NavigationState> = Partial<Omit<State, 'stale' | 'routes'>> & Readonly<{
stale?: true;
routes: PartialRoute<Route<State['routeNames'][number]>>[];
}>;
export type Route<RouteName extends string, Params extends object | undefined = object | undefined> = Readonly<{
/**
* Unique key for the route.
*/
key: string;
/**
* User-provided name for the route.
*/
name: RouteName;
/**
* Path associated with the route.
* Usually present when the screen was opened from a deep link.
*/
path?: string;
}> & (undefined extends Params ? Readonly<{
/**
* Params for this route
*/
params?: Readonly<Params>;
}> : Readonly<{
/**
* Params for this route
*/
params: Readonly<Params>;
}>);
export type ParamListBase = Record<string, object | undefined>;
export type NavigationAction = Readonly<{
/**
* Type of the action (e.g. `NAVIGATE`)
*/
type: string;
/**
* Additional data for the action
*/
payload?: object;
/**
* Key of the route which dispatched this action.
*/
source?: string;
/**
* Key of the navigator which should handle this action.
*/
target?: string;
}>;
export type ActionCreators<Action extends NavigationAction> = {
[key: string]: (...args: any) => Action;
};
export type DefaultRouterOptions<RouteName extends string = string> = {
/**
* Name of the route to focus by on initial render.
* If not specified, usually the first route is used.
*/
initialRouteName?: RouteName;
};
export type RouterFactory<State extends NavigationState, Action extends NavigationAction, RouterOptions extends DefaultRouterOptions> = (options: RouterOptions) => Router<State, Action>;
export type RouterConfigOptions = {
routeNames: string[];
routeParamList: ParamListBase;
routeGetIdList: Record<string, ((options: {
params?: Record<string, any>;
}) => string | undefined) | undefined>;
};
export type Router<State extends NavigationState, Action extends NavigationAction> = {
/**
* Type of the router. Should match the `type` property in state.
* If the type doesn't match, the state will be discarded during rehydration.
*/
type: State['type'];
/**
* Initialize the navigation state.
*
* @param options.routeNames List of valid route names as defined in the screen components.
* @param options.routeParamsList Object containing params for each route.
*/
getInitialState(options: RouterConfigOptions): State;
/**
* Rehydrate the full navigation state from a given partial state.
*
* @param partialState Navigation state to rehydrate from.
* @param options.routeNames List of valid route names as defined in the screen components.
* @param options.routeParamsList Object containing params for each route.
*/
getRehydratedState(partialState: PartialState<State> | State, options: RouterConfigOptions): State;
/**
* Take the current state and updated list of route names, and return a new state.
*
* @param state State object to update.
* @param options.routeNames New list of route names.
* @param options.routeParamsList Object containing params for each route.
*/
getStateForRouteNamesChange(state: State, options: RouterConfigOptions & {
/**
* List of routes whose key has changed even if they still have the same name.
* This allows to remove screens declaratively.
*/
routeKeyChanges: string[];
}): State;
/**
* Take the current state and key of a route, and return a new state with the route focused
*
* @param state State object to apply the action on.
* @param key Key of the route to focus.
*/
getStateForRouteFocus(state: State, key: string): State;
/**
* Take the current state and action, and return a new state.
* If the action cannot be handled, return `null`.
*
* @param state State object to apply the action on.
* @param action Action object to apply.
* @param options.routeNames List of valid route names as defined in the screen components.
* @param options.routeParamsList Object containing params for each route.
*/
getStateForAction(state: State, action: Action, options: RouterConfigOptions): State | PartialState<State> | null;
/**
* Whether the action should also change focus in parent navigator
*
* @param action Action object to check.
*/
shouldActionChangeFocus(action: NavigationAction): boolean;
/**
* Action creators for the router.
*/
actionCreators?: ActionCreators<Action>;
};
export {};
//# sourceMappingURL=types.d.ts.map

View File

@@ -0,0 +1 @@
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/types.tsx"],"names":[],"mappings":"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"}

View File

@@ -0,0 +1,61 @@
{
"name": "@react-navigation/routers",
"description": "Routers to help build custom navigators",
"version": "6.1.9",
"keywords": [
"react",
"react-native",
"react-navigation"
],
"license": "MIT",
"repository": {
"type": "git",
"url": "https://github.com/react-navigation/react-navigation.git",
"directory": "packages/routers"
},
"bugs": {
"url": "https://github.com/react-navigation/react-navigation/issues"
},
"homepage": "https://reactnavigation.org/docs/custom-routers/",
"main": "lib/commonjs/index.js",
"react-native": "src/index.tsx",
"source": "src/index.tsx",
"module": "lib/module/index.js",
"types": "lib/typescript/src/index.d.ts",
"files": [
"src",
"lib",
"!**/__tests__"
],
"sideEffects": false,
"publishConfig": {
"access": "public"
},
"scripts": {
"prepack": "bob build",
"clean": "del lib"
},
"dependencies": {
"nanoid": "^3.1.23"
},
"devDependencies": {
"del-cli": "^5.0.0",
"react-native-builder-bob": "^0.20.4",
"typescript": "^4.9.4"
},
"react-native-builder-bob": {
"source": "src",
"output": "lib",
"targets": [
"commonjs",
"module",
[
"typescript",
{
"project": "tsconfig.build.json"
}
]
]
},
"gitHead": "cf836cb84932638369f7bf59534d5a3ccea9b4f6"
}

View File

@@ -0,0 +1,81 @@
import { nanoid } from 'nanoid/non-secure';
import type {
CommonNavigationAction,
NavigationState,
PartialState,
} from './types';
/**
* Base router object that can be used when writing custom routers.
* This provides few helper methods to handle common actions such as `RESET`.
*/
const BaseRouter = {
getStateForAction<State extends NavigationState>(
state: State,
action: CommonNavigationAction
): State | PartialState<State> | null {
switch (action.type) {
case 'SET_PARAMS': {
const index = action.source
? state.routes.findIndex((r) => r.key === action.source)
: state.index;
if (index === -1) {
return null;
}
return {
...state,
routes: state.routes.map((r, i) =>
i === index
? { ...r, params: { ...r.params, ...action.payload.params } }
: r
),
};
}
case 'RESET': {
const nextState = action.payload as State | PartialState<State>;
if (
nextState.routes.length === 0 ||
nextState.routes.some(
(route: { name: string }) => !state.routeNames.includes(route.name)
)
) {
return null;
}
if (nextState.stale === false) {
if (
state.routeNames.length !== nextState.routeNames.length ||
nextState.routeNames.some(
(name) => !state.routeNames.includes(name)
)
) {
return null;
}
return {
...nextState,
routes: nextState.routes.map((route) =>
route.key ? route : { ...route, key: `${route.name}-${nanoid()}` }
),
};
}
return nextState;
}
default:
return null;
}
},
shouldActionChangeFocus(action: CommonNavigationAction) {
return action.type === 'NAVIGATE';
},
};
export default BaseRouter;

View File

@@ -0,0 +1,89 @@
import type { NavigationState, PartialState, Route } from './types';
type ResetState =
| PartialState<NavigationState>
| NavigationState
| (Omit<NavigationState, 'routes'> & {
routes: Omit<Route<string>, 'key'>[];
});
export type Action =
| {
type: 'GO_BACK';
source?: string;
target?: string;
}
| {
type: 'NAVIGATE';
payload:
| {
key: string;
name?: undefined;
params?: object;
path?: string;
merge?: boolean;
}
| {
name: string;
key?: string;
params?: object;
path?: string;
merge?: boolean;
};
source?: string;
target?: string;
}
| {
type: 'RESET';
payload: ResetState | undefined;
source?: string;
target?: string;
}
| {
type: 'SET_PARAMS';
payload: { params?: object };
source?: string;
target?: string;
};
export function goBack(): Action {
return { type: 'GO_BACK' };
}
export function navigate(
options:
| { key: string; params?: object; path?: string; merge?: boolean }
| {
name: string;
key?: string;
params?: object;
path?: string;
merge?: boolean;
}
): Action;
// eslint-disable-next-line no-redeclare
export function navigate(name: string, params?: object): Action;
// eslint-disable-next-line no-redeclare
export function navigate(...args: any): Action {
if (typeof args[0] === 'string') {
return { type: 'NAVIGATE', payload: { name: args[0], params: args[1] } };
} else {
const payload = args[0] || {};
if (!payload.hasOwnProperty('key') && !payload.hasOwnProperty('name')) {
throw new Error(
'You need to specify name or key when calling navigate with an object as the argument. See https://reactnavigation.org/docs/navigation-actions#navigate for usage.'
);
}
return { type: 'NAVIGATE', payload };
}
}
export function reset(state: ResetState | undefined): Action {
return { type: 'RESET', payload: state };
}
export function setParams(params: object): Action {
return { type: 'SET_PARAMS', payload: { params } };
}

View File

@@ -0,0 +1,247 @@
import { nanoid } from 'nanoid/non-secure';
import TabRouter, {
TabActionHelpers,
TabActions,
TabActionType,
TabNavigationState,
TabRouterOptions,
} from './TabRouter';
import type {
CommonNavigationAction,
ParamListBase,
PartialState,
Router,
} from './types';
export type DrawerStatus = 'open' | 'closed';
export type DrawerActionType =
| TabActionType
| {
type: 'OPEN_DRAWER' | 'CLOSE_DRAWER' | 'TOGGLE_DRAWER';
source?: string;
target?: string;
};
export type DrawerRouterOptions = TabRouterOptions & {
defaultStatus?: DrawerStatus;
};
export type DrawerNavigationState<ParamList extends ParamListBase> = Omit<
TabNavigationState<ParamList>,
'type' | 'history'
> & {
/**
* Type of the router, in this case, it's drawer.
*/
type: 'drawer';
/**
* Default status of the drawer.
*/
default: DrawerStatus;
/**
* List of previously visited route keys and drawer open status.
*/
history: (
| { type: 'route'; key: string }
| { type: 'drawer'; status: DrawerStatus }
)[];
};
export type DrawerActionHelpers<ParamList extends ParamListBase> =
TabActionHelpers<ParamList> & {
/**
* Open the drawer sidebar.
*/
openDrawer(): void;
/**
* Close the drawer sidebar.
*/
closeDrawer(): void;
/**
* Open the drawer sidebar if closed, or close if opened.
*/
toggleDrawer(): void;
};
export const DrawerActions = {
...TabActions,
openDrawer(): DrawerActionType {
return { type: 'OPEN_DRAWER' };
},
closeDrawer(): DrawerActionType {
return { type: 'CLOSE_DRAWER' };
},
toggleDrawer(): DrawerActionType {
return { type: 'TOGGLE_DRAWER' };
},
};
export default function DrawerRouter({
defaultStatus = 'closed',
...rest
}: DrawerRouterOptions): Router<
DrawerNavigationState<ParamListBase>,
DrawerActionType | CommonNavigationAction
> {
const router = TabRouter(rest) as unknown as Router<
DrawerNavigationState<ParamListBase>,
TabActionType | CommonNavigationAction
>;
const isDrawerInHistory = (
state:
| DrawerNavigationState<ParamListBase>
| PartialState<DrawerNavigationState<ParamListBase>>
) => Boolean(state.history?.some((it) => it.type === 'drawer'));
const addDrawerToHistory = (
state: DrawerNavigationState<ParamListBase>
): DrawerNavigationState<ParamListBase> => {
if (isDrawerInHistory(state)) {
return state;
}
return {
...state,
history: [
...state.history,
{
type: 'drawer',
status: defaultStatus === 'open' ? 'closed' : 'open',
},
],
};
};
const removeDrawerFromHistory = (
state: DrawerNavigationState<ParamListBase>
): DrawerNavigationState<ParamListBase> => {
if (!isDrawerInHistory(state)) {
return state;
}
return {
...state,
history: state.history.filter((it) => it.type !== 'drawer'),
};
};
const openDrawer = (
state: DrawerNavigationState<ParamListBase>
): DrawerNavigationState<ParamListBase> => {
if (defaultStatus === 'open') {
return removeDrawerFromHistory(state);
}
return addDrawerToHistory(state);
};
const closeDrawer = (
state: DrawerNavigationState<ParamListBase>
): DrawerNavigationState<ParamListBase> => {
if (defaultStatus === 'open') {
return addDrawerToHistory(state);
}
return removeDrawerFromHistory(state);
};
return {
...router,
type: 'drawer',
getInitialState({ routeNames, routeParamList, routeGetIdList }) {
const state = router.getInitialState({
routeNames,
routeParamList,
routeGetIdList,
});
return {
...state,
default: defaultStatus,
stale: false,
type: 'drawer',
key: `drawer-${nanoid()}`,
};
},
getRehydratedState(
partialState,
{ routeNames, routeParamList, routeGetIdList }
) {
if (partialState.stale === false) {
return partialState;
}
let state = router.getRehydratedState(partialState, {
routeNames,
routeParamList,
routeGetIdList,
});
if (isDrawerInHistory(partialState)) {
// Re-sync the drawer entry in history to correct it if it was wrong
state = removeDrawerFromHistory(state);
state = addDrawerToHistory(state);
}
return {
...state,
default: defaultStatus,
type: 'drawer',
key: `drawer-${nanoid()}`,
};
},
getStateForRouteFocus(state, key) {
const result = router.getStateForRouteFocus(state, key);
return closeDrawer(result);
},
getStateForAction(state, action, options) {
switch (action.type) {
case 'OPEN_DRAWER':
return openDrawer(state);
case 'CLOSE_DRAWER':
return closeDrawer(state);
case 'TOGGLE_DRAWER':
if (isDrawerInHistory(state)) {
return removeDrawerFromHistory(state);
}
return addDrawerToHistory(state);
case 'JUMP_TO':
case 'NAVIGATE': {
const result = router.getStateForAction(state, action, options);
if (result != null && result.index !== state.index) {
return closeDrawer(result as DrawerNavigationState<ParamListBase>);
}
return result;
}
case 'GO_BACK':
if (isDrawerInHistory(state)) {
return removeDrawerFromHistory(state);
}
return router.getStateForAction(state, action, options);
default:
return router.getStateForAction(state, action, options);
}
},
actionCreators: DrawerActions,
};
}

View File

@@ -0,0 +1,495 @@
import { nanoid } from 'nanoid/non-secure';
import BaseRouter from './BaseRouter';
import type {
CommonNavigationAction,
DefaultRouterOptions,
NavigationState,
ParamListBase,
Route,
Router,
} from './types';
export type StackActionType =
| {
type: 'REPLACE';
payload: { name: string; key?: string | undefined; params?: object };
source?: string;
target?: string;
}
| {
type: 'PUSH';
payload: { name: string; params?: object };
source?: string;
target?: string;
}
| {
type: 'POP';
payload: { count: number };
source?: string;
target?: string;
}
| {
type: 'POP_TO_TOP';
source?: string;
target?: string;
};
export type StackRouterOptions = DefaultRouterOptions;
export type StackNavigationState<ParamList extends ParamListBase> =
NavigationState<ParamList> & {
/**
* Type of the router, in this case, it's stack.
*/
type: 'stack';
};
export type StackActionHelpers<ParamList extends ParamListBase> = {
/**
* Replace the current route with a new one.
*
* @param name Route name of the new route.
* @param [params] Params object for the new route.
*/
replace<RouteName extends keyof ParamList>(
...args: undefined extends ParamList[RouteName]
? [screen: RouteName] | [screen: RouteName, params: ParamList[RouteName]]
: [screen: RouteName, params: ParamList[RouteName]]
): void;
/**
* Push a new screen onto the stack.
*
* @param name Name of the route for the tab.
* @param [params] Params object for the route.
*/
push<RouteName extends keyof ParamList>(
...args: undefined extends ParamList[RouteName]
? [screen: RouteName] | [screen: RouteName, params: ParamList[RouteName]]
: [screen: RouteName, params: ParamList[RouteName]]
): void;
/**
* Pop a screen from the stack.
*/
pop(count?: number): void;
/**
* Pop to the first route in the stack, dismissing all other screens.
*/
popToTop(): void;
};
export const StackActions = {
replace(name: string, params?: object): StackActionType {
return { type: 'REPLACE', payload: { name, params } };
},
push(name: string, params?: object): StackActionType {
return { type: 'PUSH', payload: { name, params } };
},
pop(count: number = 1): StackActionType {
return { type: 'POP', payload: { count } };
},
popToTop(): StackActionType {
return { type: 'POP_TO_TOP' };
},
};
export default function StackRouter(options: StackRouterOptions) {
const router: Router<
StackNavigationState<ParamListBase>,
CommonNavigationAction | StackActionType
> = {
...BaseRouter,
type: 'stack',
getInitialState({ routeNames, routeParamList }) {
const initialRouteName =
options.initialRouteName !== undefined &&
routeNames.includes(options.initialRouteName)
? options.initialRouteName
: routeNames[0];
return {
stale: false,
type: 'stack',
key: `stack-${nanoid()}`,
index: 0,
routeNames,
routes: [
{
key: `${initialRouteName}-${nanoid()}`,
name: initialRouteName,
params: routeParamList[initialRouteName],
},
],
};
},
getRehydratedState(partialState, { routeNames, routeParamList }) {
let state = partialState;
if (state.stale === false) {
return state;
}
const routes = state.routes
.filter((route) => routeNames.includes(route.name))
.map(
(route) =>
({
...route,
key: route.key || `${route.name}-${nanoid()}`,
params:
routeParamList[route.name] !== undefined
? {
...routeParamList[route.name],
...route.params,
}
: route.params,
} as Route<string>)
);
if (routes.length === 0) {
const initialRouteName =
options.initialRouteName !== undefined
? options.initialRouteName
: routeNames[0];
routes.push({
key: `${initialRouteName}-${nanoid()}`,
name: initialRouteName,
params: routeParamList[initialRouteName],
});
}
return {
stale: false,
type: 'stack',
key: `stack-${nanoid()}`,
index: routes.length - 1,
routeNames,
routes,
};
},
getStateForRouteNamesChange(
state,
{ routeNames, routeParamList, routeKeyChanges }
) {
const routes = state.routes.filter(
(route) =>
routeNames.includes(route.name) &&
!routeKeyChanges.includes(route.name)
);
if (routes.length === 0) {
const initialRouteName =
options.initialRouteName !== undefined &&
routeNames.includes(options.initialRouteName)
? options.initialRouteName
: routeNames[0];
routes.push({
key: `${initialRouteName}-${nanoid()}`,
name: initialRouteName,
params: routeParamList[initialRouteName],
});
}
return {
...state,
routeNames,
routes,
index: Math.min(state.index, routes.length - 1),
};
},
getStateForRouteFocus(state, key) {
const index = state.routes.findIndex((r) => r.key === key);
if (index === -1 || index === state.index) {
return state;
}
return {
...state,
index,
routes: state.routes.slice(0, index + 1),
};
},
getStateForAction(state, action, options) {
const { routeParamList } = options;
switch (action.type) {
case 'REPLACE': {
const index =
action.target === state.key && action.source
? state.routes.findIndex((r) => r.key === action.source)
: state.index;
if (index === -1) {
return null;
}
const { name, key, params } = action.payload;
if (!state.routeNames.includes(name)) {
return null;
}
return {
...state,
routes: state.routes.map((route, i) =>
i === index
? {
key: key !== undefined ? key : `${name}-${nanoid()}`,
name,
params:
routeParamList[name] !== undefined
? {
...routeParamList[name],
...params,
}
: params,
}
: route
),
};
}
case 'PUSH':
if (state.routeNames.includes(action.payload.name)) {
const getId = options.routeGetIdList[action.payload.name];
const id = getId?.({ params: action.payload.params });
const route = id
? state.routes.find(
(route) =>
route.name === action.payload.name &&
id === getId?.({ params: route.params })
)
: undefined;
let routes: Route<string>[];
if (route) {
routes = state.routes.filter((r) => r.key !== route.key);
routes.push({
...route,
params:
routeParamList[action.payload.name] !== undefined
? {
...routeParamList[action.payload.name],
...action.payload.params,
}
: action.payload.params,
});
} else {
routes = [
...state.routes,
{
key: `${action.payload.name}-${nanoid()}`,
name: action.payload.name,
params:
routeParamList[action.payload.name] !== undefined
? {
...routeParamList[action.payload.name],
...action.payload.params,
}
: action.payload.params,
},
];
}
return {
...state,
index: routes.length - 1,
routes,
};
}
return null;
case 'POP': {
const index =
action.target === state.key && action.source
? state.routes.findIndex((r) => r.key === action.source)
: state.index;
if (index > 0) {
const count = Math.max(index - action.payload.count + 1, 1);
const routes = state.routes
.slice(0, count)
.concat(state.routes.slice(index + 1));
return {
...state,
index: routes.length - 1,
routes,
};
}
return null;
}
case 'POP_TO_TOP':
return router.getStateForAction(
state,
{
type: 'POP',
payload: { count: state.routes.length - 1 },
},
options
);
case 'NAVIGATE':
if (
action.payload.name !== undefined &&
!state.routeNames.includes(action.payload.name)
) {
return null;
}
if (action.payload.key || action.payload.name) {
// If the route already exists, navigate to that
let index = -1;
const getId =
// `getId` and `key` can't be used together
action.payload.key === undefined &&
action.payload.name !== undefined
? options.routeGetIdList[action.payload.name]
: undefined;
const id = getId?.({ params: action.payload.params });
if (id) {
index = state.routes.findIndex(
(route) =>
route.name === action.payload.name &&
id === getId?.({ params: route.params })
);
} else if (
(state.routes[state.index].name === action.payload.name &&
action.payload.key === undefined) ||
state.routes[state.index].key === action.payload.key
) {
index = state.index;
} else {
for (let i = state.routes.length - 1; i >= 0; i--) {
if (
(state.routes[i].name === action.payload.name &&
action.payload.key === undefined) ||
state.routes[i].key === action.payload.key
) {
index = i;
break;
}
}
}
if (
index === -1 &&
action.payload.key &&
action.payload.name === undefined
) {
return null;
}
if (index === -1 && action.payload.name !== undefined) {
const routes = [
...state.routes,
{
key:
action.payload.key ?? `${action.payload.name}-${nanoid()}`,
name: action.payload.name,
path: action.payload.path,
params:
routeParamList[action.payload.name] !== undefined
? {
...routeParamList[action.payload.name],
...action.payload.params,
}
: action.payload.params,
},
];
return {
...state,
routes,
index: routes.length - 1,
};
}
const route = state.routes[index];
let params;
if (action.payload.merge) {
params =
action.payload.params !== undefined ||
routeParamList[route.name] !== undefined
? {
...routeParamList[route.name],
...route.params,
...action.payload.params,
}
: route.params;
} else {
params =
routeParamList[route.name] !== undefined
? {
...routeParamList[route.name],
...action.payload.params,
}
: action.payload.params;
}
return {
...state,
index,
routes: [
...state.routes.slice(0, index),
params !== route.params ||
(action.payload.path && action.payload.path !== route.path)
? {
...route,
path: action.payload.path ?? route.path,
params,
}
: state.routes[index],
],
};
}
return null;
case 'GO_BACK':
if (state.index > 0) {
return router.getStateForAction(
state,
{
type: 'POP',
payload: { count: 1 },
target: action.target,
source: action.source,
},
options
);
}
return null;
default:
return BaseRouter.getStateForAction(state, action);
}
},
actionCreators: StackActions,
};
return router;
}

View File

@@ -0,0 +1,407 @@
import { nanoid } from 'nanoid/non-secure';
import BaseRouter from './BaseRouter';
import type {
CommonNavigationAction,
DefaultRouterOptions,
NavigationState,
ParamListBase,
PartialState,
Route,
Router,
} from './types';
export type TabActionType = {
type: 'JUMP_TO';
payload: { name: string; params?: object };
source?: string;
target?: string;
};
export type BackBehavior =
| 'initialRoute'
| 'firstRoute'
| 'history'
| 'order'
| 'none';
export type TabRouterOptions = DefaultRouterOptions & {
backBehavior?: BackBehavior;
};
export type TabNavigationState<ParamList extends ParamListBase> = Omit<
NavigationState<ParamList>,
'history'
> & {
/**
* Type of the router, in this case, it's tab.
*/
type: 'tab';
/**
* List of previously visited route keys.
*/
history: { type: 'route'; key: string }[];
};
export type TabActionHelpers<ParamList extends ParamListBase> = {
/**
* Jump to an existing tab.
*
* @param name Name of the route for the tab.
* @param [params] Params object for the route.
*/
jumpTo<RouteName extends Extract<keyof ParamList, string>>(
...args: undefined extends ParamList[RouteName]
? [screen: RouteName] | [screen: RouteName, params: ParamList[RouteName]]
: [screen: RouteName, params: ParamList[RouteName]]
): void;
};
const TYPE_ROUTE = 'route' as const;
export const TabActions = {
jumpTo(name: string, params?: object): TabActionType {
return { type: 'JUMP_TO', payload: { name, params } };
},
};
const getRouteHistory = (
routes: Route<string>[],
index: number,
backBehavior: BackBehavior,
initialRouteName: string | undefined
) => {
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: TabNavigationState<ParamListBase>,
index: number,
backBehavior: BackBehavior,
initialRouteName: string | undefined
) => {
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 = 'firstRoute',
}: TabRouterOptions) {
const router: Router<
TabNavigationState<ParamListBase>,
TabActionType | CommonNavigationAction
> = {
...BaseRouter,
type: 'tab',
getInitialState({ routeNames, routeParamList }) {
const index =
initialRouteName !== undefined && routeNames.includes(initialRouteName)
? routeNames.indexOf(initialRouteName)
: 0;
const routes = routeNames.map((name) => ({
name,
key: `${name}-${nanoid()}`,
params: routeParamList[name],
}));
const history = getRouteHistory(
routes,
index,
backBehavior,
initialRouteName
);
return {
stale: false,
type: 'tab',
key: `tab-${nanoid()}`,
index,
routeNames,
history,
routes,
};
},
getRehydratedState(partialState, { routeNames, routeParamList }) {
let state = partialState;
if (state.stale === false) {
return state;
}
const routes = routeNames.map((name) => {
const route = (
state as PartialState<TabNavigationState<ParamListBase>>
).routes.find((r) => r.name === name);
return {
...route,
name,
key:
route && route.name === name && route.key
? route.key
: `${name}-${nanoid()}`,
params:
routeParamList[name] !== undefined
? {
...routeParamList[name],
...(route ? route.params : undefined),
}
: route
? route.params
: undefined,
} as Route<string>;
});
const index = Math.min(
Math.max(routeNames.indexOf(state.routes[state?.index ?? 0]?.name), 0),
routes.length - 1
);
const history =
state.history?.filter((it) => routes.find((r) => r.key === it.key)) ??
[];
return changeIndex(
{
stale: false,
type: 'tab',
key: `tab-${nanoid()}`,
index,
routeNames,
history,
routes,
},
index,
backBehavior,
initialRouteName
);
},
getStateForRouteNamesChange(
state,
{ routeNames, routeParamList, routeKeyChanges }
) {
const routes = routeNames.map(
(name) =>
state.routes.find(
(r) => r.name === name && !routeKeyChanges.includes(r.name)
) || {
name,
key: `${name}-${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, routeGetIdList }) {
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: state.routes.map((route, i) => {
if (i !== index) {
return route;
}
const getId = routeGetIdList[route.name];
const currentId = getId?.({ params: route.params });
const nextId = getId?.({ params: action.payload.params });
const key =
currentId === nextId
? route.key
: `${route.name}-${nanoid()}`;
let params;
if (
action.type === 'NAVIGATE' &&
action.payload.merge &&
currentId === nextId
) {
params =
action.payload.params !== undefined ||
routeParamList[route.name] !== undefined
? {
...routeParamList[route.name],
...route.params,
...action.payload.params,
}
: route.params;
} else {
params =
routeParamList[route.name] !== undefined
? {
...routeParamList[route.name],
...action.payload.params,
}
: action.payload.params;
}
const path =
action.type === 'NAVIGATE' && action.payload.path != null
? action.payload.path
: route.path;
return params !== route.params || path !== route.path
? { ...route, key, path, params }
: route;
}),
},
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;
}

View File

@@ -0,0 +1,28 @@
import * as CommonActions from './CommonActions';
export { CommonActions };
export { default as BaseRouter } from './BaseRouter';
export type {
DrawerActionHelpers,
DrawerActionType,
DrawerNavigationState,
DrawerRouterOptions,
DrawerStatus,
} from './DrawerRouter';
export { DrawerActions, default as DrawerRouter } from './DrawerRouter';
export type {
StackActionHelpers,
StackActionType,
StackNavigationState,
StackRouterOptions,
} from './StackRouter';
export { StackActions, default as StackRouter } from './StackRouter';
export type {
TabActionHelpers,
TabActionType,
TabNavigationState,
TabRouterOptions,
} from './TabRouter';
export { TabActions, default as TabRouter } from './TabRouter';
export * from './types';

View File

@@ -0,0 +1,228 @@
import type * as CommonActions from './CommonActions';
export type CommonNavigationAction = CommonActions.Action;
type NavigationRoute<
ParamList extends ParamListBase,
RouteName extends keyof ParamList
> = Route<Extract<RouteName, string>, ParamList[RouteName]> & {
state?: NavigationState | PartialState<NavigationState>;
};
export type NavigationState<ParamList extends ParamListBase = ParamListBase> =
Readonly<{
/**
* Unique key for the navigation state.
*/
key: string;
/**
* Index of the currently focused route.
*/
index: number;
/**
* List of valid route names as defined in the screen components.
*/
routeNames: Extract<keyof ParamList, string>[];
/**
* Alternative entries for history.
*/
history?: unknown[];
/**
* List of rendered routes.
*/
routes: NavigationRoute<ParamList, keyof ParamList>[];
/**
* Custom type for the state, whether it's for tab, stack, drawer etc.
* During rehydration, the state will be discarded if type doesn't match with router type.
* It can also be used to detect the type of the navigator we're dealing with.
*/
type: string;
/**
* Whether the navigation state has been rehydrated.
*/
stale: false;
}>;
export type InitialState = Readonly<
Partial<Omit<NavigationState, 'stale' | 'routes'>> & {
routes: (Omit<Route<string>, 'key'> & { state?: InitialState })[];
}
>;
export type PartialRoute<R extends Route<string>> = Omit<R, 'key'> & {
key?: string;
state?: PartialState<NavigationState>;
};
export type PartialState<State extends NavigationState> = Partial<
Omit<State, 'stale' | 'routes'>
> &
Readonly<{
stale?: true;
routes: PartialRoute<Route<State['routeNames'][number]>>[];
}>;
export type Route<
RouteName extends string,
Params extends object | undefined = object | undefined
> = Readonly<{
/**
* Unique key for the route.
*/
key: string;
/**
* User-provided name for the route.
*/
name: RouteName;
/**
* Path associated with the route.
* Usually present when the screen was opened from a deep link.
*/
path?: string;
}> &
(undefined extends Params
? Readonly<{
/**
* Params for this route
*/
params?: Readonly<Params>;
}>
: Readonly<{
/**
* Params for this route
*/
params: Readonly<Params>;
}>);
export type ParamListBase = Record<string, object | undefined>;
export type NavigationAction = Readonly<{
/**
* Type of the action (e.g. `NAVIGATE`)
*/
type: string;
/**
* Additional data for the action
*/
payload?: object;
/**
* Key of the route which dispatched this action.
*/
source?: string;
/**
* Key of the navigator which should handle this action.
*/
target?: string;
}>;
export type ActionCreators<Action extends NavigationAction> = {
[key: string]: (...args: any) => Action;
};
export type DefaultRouterOptions<RouteName extends string = string> = {
/**
* Name of the route to focus by on initial render.
* If not specified, usually the first route is used.
*/
initialRouteName?: RouteName;
};
export type RouterFactory<
State extends NavigationState,
Action extends NavigationAction,
RouterOptions extends DefaultRouterOptions
> = (options: RouterOptions) => Router<State, Action>;
export type RouterConfigOptions = {
routeNames: string[];
routeParamList: ParamListBase;
routeGetIdList: Record<
string,
| ((options: { params?: Record<string, any> }) => string | undefined)
| undefined
>;
};
export type Router<
State extends NavigationState,
Action extends NavigationAction
> = {
/**
* Type of the router. Should match the `type` property in state.
* If the type doesn't match, the state will be discarded during rehydration.
*/
type: State['type'];
/**
* Initialize the navigation state.
*
* @param options.routeNames List of valid route names as defined in the screen components.
* @param options.routeParamsList Object containing params for each route.
*/
getInitialState(options: RouterConfigOptions): State;
/**
* Rehydrate the full navigation state from a given partial state.
*
* @param partialState Navigation state to rehydrate from.
* @param options.routeNames List of valid route names as defined in the screen components.
* @param options.routeParamsList Object containing params for each route.
*/
getRehydratedState(
partialState: PartialState<State> | State,
options: RouterConfigOptions
): State;
/**
* Take the current state and updated list of route names, and return a new state.
*
* @param state State object to update.
* @param options.routeNames New list of route names.
* @param options.routeParamsList Object containing params for each route.
*/
getStateForRouteNamesChange(
state: State,
options: RouterConfigOptions & {
/**
* List of routes whose key has changed even if they still have the same name.
* This allows to remove screens declaratively.
*/
routeKeyChanges: string[];
}
): State;
/**
* Take the current state and key of a route, and return a new state with the route focused
*
* @param state State object to apply the action on.
* @param key Key of the route to focus.
*/
getStateForRouteFocus(state: State, key: string): State;
/**
* Take the current state and action, and return a new state.
* If the action cannot be handled, return `null`.
*
* @param state State object to apply the action on.
* @param action Action object to apply.
* @param options.routeNames List of valid route names as defined in the screen components.
* @param options.routeParamsList Object containing params for each route.
*/
getStateForAction(
state: State,
action: Action,
options: RouterConfigOptions
): State | PartialState<State> | null;
/**
* Whether the action should also change focus in parent navigator
*
* @param action Action object to check.
*/
shouldActionChangeFocus(action: NavigationAction): boolean;
/**
* Action creators for the router.
*/
actionCreators?: ActionCreators<Action>;
};