navigation-stack 0.3.1 → 0.4.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +603 -163
- package/data-storage/package.json +6 -0
- package/karma.conf.cjs +21 -4
- package/lib/cjs/NavigationStack.js +73 -0
- package/lib/cjs/data-storage/DataStorage.js +71 -0
- package/lib/cjs/data-storage/LocationDataStorage.js +29 -0
- package/lib/cjs/data-storage/index.js +9 -0
- package/lib/cjs/environment/InMemoryEnvironment.js +15 -0
- package/lib/cjs/environment/WebBrowserEnvironment.js +15 -0
- package/lib/cjs/environment/data-storage/InMemoryDataStorage.js +27 -0
- package/lib/cjs/environment/data-storage/WebBrowserDataStorage.js +21 -0
- package/lib/cjs/environment/scroll-position/InMemoryScrollPosition.js +44 -0
- package/lib/cjs/environment/scroll-position/WebBrowserScrollPosition.js +60 -0
- package/lib/cjs/getLocationFromInternalLocation.js +14 -0
- package/lib/cjs/index.js +20 -16
- package/lib/cjs/navigationBlockers.js +25 -23
- package/lib/cjs/{normalizeInputLocation.js → parseInputLocation.js} +25 -9
- package/lib/cjs/{ActionTypes.js → redux/ActionTypes.js} +1 -1
- package/lib/cjs/redux/ActionTypesInternal.js +8 -0
- package/lib/cjs/{Actions.js → redux/Actions.js} +5 -4
- package/lib/cjs/redux/createMiddlewares.js +60 -0
- package/lib/cjs/redux/index.js +13 -0
- package/lib/cjs/redux/internalLocationReducer.js +14 -0
- package/lib/cjs/redux/middleware/createAddInputLocationBasePathMiddleware.js +32 -0
- package/lib/cjs/redux/middleware/createNonProgrammaticNavigationBlockerMiddleware.js +113 -0
- package/lib/cjs/redux/middleware/createProgrammaticNavigationBlockerMiddleware.js +94 -0
- package/lib/cjs/redux/middleware/createRemoveOutputLocationBasePathMiddleware.js +30 -0
- package/lib/cjs/redux/middleware/createUpdateInternalLocationMiddleware.js +73 -0
- package/lib/cjs/{middleware/navigationActionMiddleware.js → redux/middleware/navigationOperationMiddleware.js} +11 -8
- package/lib/cjs/{middleware/normalizeInputLocationMiddleware.js → redux/middleware/parseInputLocationMiddleware.js} +6 -4
- package/lib/cjs/redux/middleware/updateLocationMiddleware.js +34 -0
- package/lib/cjs/scroll-position/PageScrollPositionSetter.js +97 -0
- package/lib/cjs/scroll-position/ScrollPositionAutoSaver.js +130 -0
- package/lib/cjs/scroll-position/ScrollPositionRestoration.js +383 -0
- package/lib/cjs/scroll-position/ScrollPositionSaver.js +81 -0
- package/lib/cjs/scroll-position/ScrollPositionSetter.js +16 -0
- package/lib/cjs/scroll-position/constants.js +5 -0
- package/lib/cjs/scroll-position/index.js +7 -0
- package/lib/cjs/scroll-position/scheduleNextTick.js +11 -0
- package/lib/cjs/session/InMemorySession.js +22 -0
- package/lib/cjs/session/ServerSideRenderSession.js +17 -0
- package/lib/cjs/session/Session.js +196 -0
- package/lib/cjs/session/WebBrowserSession.js +20 -0
- package/lib/cjs/session/key/createSessionKey.js +23 -0
- package/lib/cjs/session/lifecycle/InMemorySessionLifecycle.js +19 -0
- package/lib/cjs/session/lifecycle/WebBrowserSessionLifecycle.js +128 -0
- package/lib/cjs/session/lifecycle/page-lifecycle/PageLifecycle.js +269 -0
- package/lib/cjs/session/lifecycle/page-lifecycle/PageLifecycleInstance.js +8 -0
- package/lib/cjs/session/lifecycle/page-lifecycle/supportsConstructableEventTarget.js +33 -0
- package/lib/cjs/session/navigation/InMemoryNavigation.js +104 -0
- package/lib/cjs/session/navigation/ServerSideNavigation.js +61 -0
- package/lib/cjs/session/navigation/WebBrowserNavigation.js +221 -0
- package/lib/cjs/session/navigation/error/NavigationOutOfBoundsError.js +12 -0
- package/lib/cjs/session/navigation/error/ServerSideNavigationError.js +21 -0
- package/lib/cjs/session/navigation/operation/operations.js +11 -0
- package/lib/cjs/session/subscription/Subscription.js +81 -0
- package/lib/data-storage/index.d.ts +35 -0
- package/lib/esm/NavigationStack.js +66 -0
- package/lib/esm/data-storage/DataStorage.js +65 -0
- package/lib/esm/data-storage/LocationDataStorage.js +22 -0
- package/lib/esm/data-storage/index.js +2 -0
- package/lib/esm/environment/InMemoryEnvironment.js +8 -0
- package/lib/esm/environment/WebBrowserEnvironment.js +8 -0
- package/lib/esm/environment/data-storage/InMemoryDataStorage.js +21 -0
- package/lib/esm/environment/data-storage/WebBrowserDataStorage.js +15 -0
- package/lib/esm/environment/scroll-position/InMemoryScrollPosition.js +38 -0
- package/lib/esm/environment/scroll-position/WebBrowserScrollPosition.js +54 -0
- package/lib/esm/getLocationFromInternalLocation.js +9 -0
- package/lib/esm/index.js +10 -8
- package/lib/esm/navigationBlockers.js +25 -23
- package/lib/esm/{normalizeInputLocation.js → parseInputLocation.js} +24 -8
- package/lib/esm/{ActionTypes.js → redux/ActionTypes.js} +1 -1
- package/lib/esm/redux/ActionTypesInternal.js +3 -0
- package/lib/esm/{Actions.js → redux/Actions.js} +5 -4
- package/lib/esm/redux/createMiddlewares.js +54 -0
- package/lib/esm/redux/index.js +4 -0
- package/lib/esm/redux/internalLocationReducer.js +8 -0
- package/lib/esm/redux/middleware/createAddInputLocationBasePathMiddleware.js +27 -0
- package/lib/esm/redux/middleware/createNonProgrammaticNavigationBlockerMiddleware.js +108 -0
- package/lib/esm/redux/middleware/createProgrammaticNavigationBlockerMiddleware.js +88 -0
- package/lib/esm/redux/middleware/createRemoveOutputLocationBasePathMiddleware.js +25 -0
- package/lib/esm/redux/middleware/createUpdateInternalLocationMiddleware.js +68 -0
- package/lib/esm/{middleware/navigationActionMiddleware.js → redux/middleware/navigationOperationMiddleware.js} +10 -7
- package/lib/esm/{middleware/normalizeInputLocationMiddleware.js → redux/middleware/parseInputLocationMiddleware.js} +5 -3
- package/lib/esm/redux/middleware/updateLocationMiddleware.js +28 -0
- package/lib/esm/scroll-position/PageScrollPositionSetter.js +91 -0
- package/lib/esm/scroll-position/ScrollPositionAutoSaver.js +123 -0
- package/lib/esm/scroll-position/ScrollPositionRestoration.js +376 -0
- package/lib/esm/scroll-position/ScrollPositionSaver.js +74 -0
- package/lib/esm/scroll-position/ScrollPositionSetter.js +10 -0
- package/lib/esm/scroll-position/constants.js +1 -0
- package/lib/esm/scroll-position/index.js +1 -0
- package/lib/esm/scroll-position/scheduleNextTick.js +6 -0
- package/lib/esm/session/InMemorySession.js +15 -0
- package/lib/esm/session/ServerSideRenderSession.js +11 -0
- package/lib/esm/session/Session.js +189 -0
- package/lib/esm/session/WebBrowserSession.js +13 -0
- package/lib/esm/session/key/createSessionKey.js +18 -0
- package/lib/esm/session/lifecycle/InMemorySessionLifecycle.js +13 -0
- package/lib/esm/session/lifecycle/WebBrowserSessionLifecycle.js +120 -0
- package/lib/esm/session/lifecycle/page-lifecycle/PageLifecycle.js +263 -0
- package/lib/esm/session/lifecycle/page-lifecycle/PageLifecycleInstance.js +2 -0
- package/lib/esm/session/lifecycle/page-lifecycle/supportsConstructableEventTarget.js +30 -0
- package/lib/esm/session/navigation/InMemoryNavigation.js +97 -0
- package/lib/esm/session/navigation/ServerSideNavigation.js +54 -0
- package/lib/esm/session/navigation/WebBrowserNavigation.js +213 -0
- package/lib/esm/session/navigation/error/NavigationOutOfBoundsError.js +6 -0
- package/lib/esm/session/navigation/error/ServerSideNavigationError.js +14 -0
- package/lib/esm/session/navigation/operation/operations.js +6 -0
- package/lib/esm/session/subscription/Subscription.js +75 -0
- package/lib/index.d.ts +178 -157
- package/lib/redux/index.d.ts +90 -0
- package/lib/scroll-position/index.d.ts +107 -0
- package/package.json +9 -5
- package/redux/package.json +6 -0
- package/scroll-position/package.json +6 -0
- package/src/NavigationStack.js +84 -0
- package/src/data-storage/DataStorage.js +69 -0
- package/src/data-storage/LocationDataStorage.js +23 -0
- package/src/data-storage/index.js +2 -0
- package/src/environment/InMemoryEnvironment.js +9 -0
- package/src/environment/WebBrowserEnvironment.js +9 -0
- package/src/environment/data-storage/InMemoryDataStorage.js +23 -0
- package/src/environment/data-storage/WebBrowserDataStorage.js +17 -0
- package/src/environment/scroll-position/InMemoryScrollPosition.js +45 -0
- package/src/environment/scroll-position/WebBrowserScrollPosition.js +72 -0
- package/src/getLocationFromInternalLocation.js +7 -0
- package/src/index.js +10 -8
- package/src/navigationBlockers.js +28 -27
- package/src/{normalizeInputLocation.js → parseInputLocation.js} +23 -8
- package/src/{ActionTypes.js → redux/ActionTypes.js} +1 -1
- package/src/redux/ActionTypesInternal.js +3 -0
- package/src/{Actions.js → redux/Actions.js} +4 -3
- package/src/redux/createMiddlewares.js +65 -0
- package/src/redux/index.js +4 -0
- package/src/redux/internalLocationReducer.js +9 -0
- package/src/redux/middleware/createAddInputLocationBasePathMiddleware.js +27 -0
- package/src/redux/middleware/createNonProgrammaticNavigationBlockerMiddleware.js +119 -0
- package/src/redux/middleware/createProgrammaticNavigationBlockerMiddleware.js +94 -0
- package/src/redux/middleware/createRemoveOutputLocationBasePathMiddleware.js +26 -0
- package/src/redux/middleware/createUpdateInternalLocationMiddleware.js +72 -0
- package/src/{middleware/navigationActionMiddleware.js → redux/middleware/navigationOperationMiddleware.js} +10 -3
- package/src/{middleware/normalizeInputLocationMiddleware.js → redux/middleware/parseInputLocationMiddleware.js} +5 -3
- package/src/redux/middleware/updateLocationMiddleware.js +28 -0
- package/src/scroll-position/PageScrollPositionSetter.js +110 -0
- package/src/scroll-position/ScrollPositionAutoSaver.js +151 -0
- package/src/scroll-position/ScrollPositionRestoration.js +506 -0
- package/src/scroll-position/ScrollPositionSaver.js +100 -0
- package/src/scroll-position/ScrollPositionSetter.js +16 -0
- package/src/scroll-position/constants.js +1 -0
- package/src/scroll-position/index.js +1 -0
- package/src/scroll-position/scheduleNextTick.js +6 -0
- package/src/session/InMemorySession.js +13 -0
- package/src/session/ServerSideRenderSession.js +9 -0
- package/src/session/Session.js +216 -0
- package/src/session/WebBrowserSession.js +13 -0
- package/src/session/key/createSessionKey.js +18 -0
- package/src/session/lifecycle/InMemorySessionLifecycle.js +13 -0
- package/src/session/lifecycle/WebBrowserSessionLifecycle.js +126 -0
- package/src/session/lifecycle/page-lifecycle/PageLifecycle.js +291 -0
- package/src/session/lifecycle/page-lifecycle/PageLifecycleInstance.js +3 -0
- package/src/session/lifecycle/page-lifecycle/supportsConstructableEventTarget.js +32 -0
- package/src/session/navigation/InMemoryNavigation.js +78 -0
- package/src/session/navigation/ServerSideNavigation.js +43 -0
- package/src/session/navigation/WebBrowserNavigation.js +224 -0
- package/src/session/navigation/error/NavigationOutOfBoundsError.js +7 -0
- package/src/session/navigation/error/ServerSideNavigationError.js +18 -0
- package/src/session/navigation/operation/operations.js +6 -0
- package/src/session/subscription/Subscription.js +76 -0
- package/test/NavigationStack.test.js +296 -0
- package/test/{LocationDataStorage.test.js → data-storage/LocationDataStorage.test.js} +3 -3
- package/test/data-storage/index.test.js +8 -0
- package/test/index.js +12 -0
- package/test/index.test.js +8 -7
- package/test/{helpers.js → middlewareTestUtil.js} +9 -12
- package/test/{normalizeInputLocation.test.js → parseInputLocationMiddleware.test.js} +9 -9
- package/test/{Action.test.js → redux/Action.test.js} +7 -6
- package/test/{ActionTypes.test.js → redux/ActionTypes.test.js} +2 -2
- package/test/redux/createMiddlewares.test.js +96 -0
- package/test/redux/index.test.js +10 -0
- package/test/{locationReducer.test.js → redux/locationReducer.test.js} +4 -7
- package/test/redux/middleware/createAddInputLocationBasePathMiddleware.test.js +40 -0
- package/test/redux/middleware/createNonProgrammaticNavigationBlockerMiddleware.test.js +264 -0
- package/test/redux/middleware/createProgrammaticNavigationBlockerMiddleware.test.js +312 -0
- package/test/redux/middleware/createRemoveOutputLocationBasePathMiddleware.test.js +51 -0
- package/test/{middleware/navigationActionMiddleware.test.js → redux/middleware/navigationOperationMiddleware.test.js} +16 -12
- package/test/{middleware/normalizeInputLocationMiddleware.test.js → redux/middleware/parseInputLocationMiddleware.test.js} +4 -4
- package/test/scroll-position/ScrollPositionRestoration.test.js +418 -0
- package/test/scroll-position/addScrollableContainer.js +36 -0
- package/test/scroll-position/addScrollableContainerWithHyperlink.js +50 -0
- package/test/scroll-position/createApp.js +112 -0
- package/test/scroll-position/delay.js +9 -0
- package/test/scroll-position/mockPageLifecycle.js +17 -0
- package/test/scroll-position/runApp.js +24 -0
- package/test/scroll-position/withScrollableContainerAtIndexPage.js +62 -0
- package/test/session/InMemorySession.test.js +348 -0
- package/test/session/ServerSession.test.js +17 -9
- package/test/session/WebBrowserSession.test.js +265 -0
- package/test/testUtil.js +3 -0
- package/types/data-storage/index.d.ts +35 -0
- package/types/index.d.ts +178 -157
- package/types/redux/index.d.ts +90 -0
- package/types/scroll-position/index.d.ts +107 -0
- package/types/tsconfig.json +1 -1
- package/lib/cjs/LocationDataStorage.js +0 -61
- package/lib/cjs/addBeforeLocationChangeListener.js +0 -7
- package/lib/cjs/beforeLocationChangeListeners.js +0 -51
- package/lib/cjs/createMiddlewares.js +0 -47
- package/lib/cjs/middleware/createBasePathMiddleware.js +0 -24
- package/lib/cjs/middleware/createBeforeLocationChangeListenerMiddleware.js +0 -39
- package/lib/cjs/middleware/createLocationMiddleware.js +0 -56
- package/lib/cjs/middleware/createNavigationBlockerMiddleware.js +0 -161
- package/lib/cjs/middleware/createTransformLocationMiddleware.js +0 -38
- package/lib/cjs/onlyAllowedOnClientSide.js +0 -10
- package/lib/cjs/session/BrowserSession.js +0 -235
- package/lib/cjs/session/MemorySession.js +0 -223
- package/lib/cjs/session/ServerSession.js +0 -65
- package/lib/esm/LocationDataStorage.js +0 -54
- package/lib/esm/addBeforeLocationChangeListener.js +0 -2
- package/lib/esm/beforeLocationChangeListeners.js +0 -44
- package/lib/esm/createMiddlewares.js +0 -41
- package/lib/esm/middleware/createBasePathMiddleware.js +0 -19
- package/lib/esm/middleware/createBeforeLocationChangeListenerMiddleware.js +0 -34
- package/lib/esm/middleware/createLocationMiddleware.js +0 -50
- package/lib/esm/middleware/createNavigationBlockerMiddleware.js +0 -156
- package/lib/esm/middleware/createTransformLocationMiddleware.js +0 -33
- package/lib/esm/onlyAllowedOnClientSide.js +0 -5
- package/lib/esm/session/BrowserSession.js +0 -229
- package/lib/esm/session/MemorySession.js +0 -217
- package/lib/esm/session/ServerSession.js +0 -58
- package/src/LocationDataStorage.js +0 -60
- package/src/addBeforeLocationChangeListener.js +0 -2
- package/src/beforeLocationChangeListeners.js +0 -54
- package/src/createMiddlewares.js +0 -45
- package/src/middleware/createBasePathMiddleware.js +0 -20
- package/src/middleware/createBeforeLocationChangeListenerMiddleware.js +0 -40
- package/src/middleware/createLocationMiddleware.js +0 -55
- package/src/middleware/createNavigationBlockerMiddleware.js +0 -168
- package/src/middleware/createTransformLocationMiddleware.js +0 -29
- package/src/onlyAllowedOnClientSide.js +0 -5
- package/src/session/BrowserSession.js +0 -235
- package/src/session/MemorySession.js +0 -219
- package/src/session/ServerSession.js +0 -67
- package/test/createMiddlewares.test.js +0 -62
- package/test/middleware/createBasePathMiddleware.test.js +0 -67
- package/test/middleware/createBeforeLocationChangeListenerMiddleware.test.js +0 -141
- package/test/middleware/createNavigationBlockerMiddleware.test.js +0 -471
- package/test/middleware/createTransformLocationMiddleware.test.js +0 -44
- package/test/session/BrowserSession.test.js +0 -182
- package/test/session/MemorySession.test.js +0 -244
- /package/lib/cjs/{locationReducer.js → redux/locationReducer.js} +0 -0
- /package/lib/esm/{locationReducer.js → redux/locationReducer.js} +0 -0
- /package/src/{locationReducer.js → redux/locationReducer.js} +0 -0
package/karma.conf.cjs
CHANGED
|
@@ -14,7 +14,7 @@ module.exports = (config) => {
|
|
|
14
14
|
const { env } = process;
|
|
15
15
|
|
|
16
16
|
config.set({
|
|
17
|
-
frameworks: ['
|
|
17
|
+
frameworks: ['webpack', 'mocha', 'sinon-chai'],
|
|
18
18
|
|
|
19
19
|
files: ['test/index.js', { pattern: 'test/**/*.test.js', watched: false }],
|
|
20
20
|
|
|
@@ -26,16 +26,32 @@ module.exports = (config) => {
|
|
|
26
26
|
mode: 'development',
|
|
27
27
|
module: {
|
|
28
28
|
rules: [
|
|
29
|
-
{
|
|
29
|
+
{
|
|
30
|
+
test: /\.js$/,
|
|
31
|
+
exclude: /node_modules/,
|
|
32
|
+
use: {
|
|
33
|
+
loader: 'babel-loader',
|
|
34
|
+
},
|
|
35
|
+
},
|
|
30
36
|
],
|
|
31
37
|
},
|
|
32
38
|
plugins: [
|
|
33
39
|
new webpack.DefinePlugin({
|
|
34
40
|
__DEV__: true,
|
|
35
41
|
}),
|
|
42
|
+
new webpack.ProvidePlugin({
|
|
43
|
+
process: 'process/browser',
|
|
44
|
+
}),
|
|
36
45
|
],
|
|
37
46
|
},
|
|
38
47
|
|
|
48
|
+
resolve: {
|
|
49
|
+
fallback: {
|
|
50
|
+
process: require.resolve('process/browser'),
|
|
51
|
+
util: require.resolve('util/'),
|
|
52
|
+
},
|
|
53
|
+
},
|
|
54
|
+
|
|
39
55
|
webpackMiddleware: {
|
|
40
56
|
noInfo: true,
|
|
41
57
|
},
|
|
@@ -53,11 +69,12 @@ module.exports = (config) => {
|
|
|
53
69
|
|
|
54
70
|
customLaunchers: {
|
|
55
71
|
ChromeCi: {
|
|
56
|
-
base: 'ChromeHeadless',
|
|
72
|
+
// base: 'ChromeHeadless',
|
|
73
|
+
base: 'Chrome',
|
|
57
74
|
flags: ['--no-sandbox'],
|
|
58
75
|
},
|
|
59
76
|
},
|
|
60
77
|
|
|
61
|
-
browsers: env.BROWSER ? env.BROWSER.split(',') : ['Chrome'],
|
|
78
|
+
browsers: env.BROWSER ? env.BROWSER.split(',') : ['Chrome', 'Firefox'],
|
|
62
79
|
});
|
|
63
80
|
};
|
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
exports.__esModule = true;
|
|
4
|
+
exports.default = void 0;
|
|
5
|
+
var _redux = require("redux");
|
|
6
|
+
var _Actions = _interopRequireDefault(require("./redux/Actions"));
|
|
7
|
+
var _createMiddlewares = _interopRequireDefault(require("./redux/createMiddlewares"));
|
|
8
|
+
var _locationReducer = _interopRequireDefault(require("./redux/locationReducer"));
|
|
9
|
+
var _ScrollPositionRestoration = _interopRequireDefault(require("./scroll-position/ScrollPositionRestoration"));
|
|
10
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
11
|
+
class NavigationStack {
|
|
12
|
+
constructor(session, options) {
|
|
13
|
+
this._session = session;
|
|
14
|
+
|
|
15
|
+
// Create a Redux store.
|
|
16
|
+
this._store = (0, _redux.createStore)(_locationReducer.default, (0, _redux.applyMiddleware)(...(0, _createMiddlewares.default)(session, options)));
|
|
17
|
+
|
|
18
|
+
// Create `ScrollPositionRestoration`.
|
|
19
|
+
if (options && options.maintainScrollPosition) {
|
|
20
|
+
this._scrollPositionRestoration = new _ScrollPositionRestoration.default(session);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
addScrollableContainer(scrollableContainerKey, scrollableContainer) {
|
|
24
|
+
if (!this._scrollPositionRestoration) {
|
|
25
|
+
throw new Error('`maintainScrollPosition: true` option not passed');
|
|
26
|
+
}
|
|
27
|
+
return this._scrollPositionRestoration.addScrollableContainer(scrollableContainerKey, scrollableContainer);
|
|
28
|
+
}
|
|
29
|
+
subscribe(listener) {
|
|
30
|
+
// Subscribe to any potential Redux state changes.
|
|
31
|
+
return this._store.subscribe(() => {
|
|
32
|
+
// Initially, calls the listener when setting the initial location.
|
|
33
|
+
// After that, calls it on any location change.
|
|
34
|
+
const location = this.current();
|
|
35
|
+
if (!this._latestLocation || location !== this._latestLocation) {
|
|
36
|
+
this._latestLocation = location;
|
|
37
|
+
listener(location);
|
|
38
|
+
}
|
|
39
|
+
});
|
|
40
|
+
}
|
|
41
|
+
init(initialLocation) {
|
|
42
|
+
if (this._latestLocation) {
|
|
43
|
+
throw new Error('Already initialized');
|
|
44
|
+
}
|
|
45
|
+
this._store.dispatch(_Actions.default.init(initialLocation));
|
|
46
|
+
this._latestLocation = this.current();
|
|
47
|
+
}
|
|
48
|
+
current() {
|
|
49
|
+
return this._store.getState();
|
|
50
|
+
}
|
|
51
|
+
push(location) {
|
|
52
|
+
this._store.dispatch(_Actions.default.push(location));
|
|
53
|
+
}
|
|
54
|
+
replace(location) {
|
|
55
|
+
this._store.dispatch(_Actions.default.replace(location));
|
|
56
|
+
}
|
|
57
|
+
shift(delta) {
|
|
58
|
+
this._store.dispatch(_Actions.default.shift(delta));
|
|
59
|
+
}
|
|
60
|
+
stop() {
|
|
61
|
+
if (this._scrollPositionRestoration) {
|
|
62
|
+
this._scrollPositionRestoration.stop();
|
|
63
|
+
}
|
|
64
|
+
this._store.dispatch(_Actions.default.stop());
|
|
65
|
+
}
|
|
66
|
+
locationRendered() {
|
|
67
|
+
if (this._scrollPositionRestoration) {
|
|
68
|
+
this._scrollPositionRestoration.locationRendered(this.current());
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
}
|
|
72
|
+
exports.default = NavigationStack;
|
|
73
|
+
module.exports = exports.default;
|
|
@@ -0,0 +1,71 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
exports.__esModule = true;
|
|
4
|
+
exports.default = void 0;
|
|
5
|
+
class DataStorage {
|
|
6
|
+
constructor(session, {
|
|
7
|
+
namespace
|
|
8
|
+
}) {
|
|
9
|
+
if (!session.key) {
|
|
10
|
+
throw new Error('`DataStorage` requires a `session.key`');
|
|
11
|
+
}
|
|
12
|
+
this._sessionKey = session.key;
|
|
13
|
+
this._dataStorage = session.environment.dataStorage;
|
|
14
|
+
this._namespace = namespace;
|
|
15
|
+
}
|
|
16
|
+
get(key) {
|
|
17
|
+
const storageKey = this._getStorageKey(key);
|
|
18
|
+
try {
|
|
19
|
+
const value = this._dataStorage.get(storageKey);
|
|
20
|
+
// === null is probably sufficient.
|
|
21
|
+
if (value === null) {
|
|
22
|
+
return undefined;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
// We want to catch JSON parse errors in case someone separately threw
|
|
26
|
+
// junk into sessionStorage under our namespace.
|
|
27
|
+
return JSON.parse(value);
|
|
28
|
+
} catch (error) {
|
|
29
|
+
// eslint-disable-next-line no-console
|
|
30
|
+
console.error('[navigation-stack] Could not read data from storage');
|
|
31
|
+
|
|
32
|
+
// Pretend that the entry doesn't exist.
|
|
33
|
+
return undefined;
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
set(key, value) {
|
|
37
|
+
const storageKey = this._getStorageKey(key);
|
|
38
|
+
if (value === undefined) {
|
|
39
|
+
try {
|
|
40
|
+
this._dataStorage.remove(storageKey);
|
|
41
|
+
} catch (error) {
|
|
42
|
+
// No need to handle errors here.
|
|
43
|
+
// eslint-disable-next-line no-console
|
|
44
|
+
console.error('[navigation-stack] Could not delete data from storage');
|
|
45
|
+
}
|
|
46
|
+
return;
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Unlike with read, we want to fail on invalid values here, since the
|
|
50
|
+
// value here is provided by the caller of this method.
|
|
51
|
+
const valueString = JSON.stringify(value);
|
|
52
|
+
try {
|
|
53
|
+
this._dataStorage.set(storageKey, valueString);
|
|
54
|
+
} catch (error) {
|
|
55
|
+
// No need to handle errors here either. If it didn't work, it didn't
|
|
56
|
+
// work. We make no guarantees about actually saving the value.
|
|
57
|
+
// eslint-disable-next-line no-console
|
|
58
|
+
console.error('[navigation-stack] Could not save data in storage');
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
// It could also implement a method that would clean up any data written so far,
|
|
63
|
+
// but so far it doesn't seem to be required by any real-world use case.
|
|
64
|
+
// cleanUp() {}
|
|
65
|
+
|
|
66
|
+
_getStorageKey(key) {
|
|
67
|
+
return `${this._sessionKey}|${this.namespace}|${key}`;
|
|
68
|
+
}
|
|
69
|
+
}
|
|
70
|
+
exports.default = DataStorage;
|
|
71
|
+
module.exports = exports.default;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
exports.__esModule = true;
|
|
4
|
+
exports.default = void 0;
|
|
5
|
+
var _DataStorage = _interopRequireDefault(require("./DataStorage"));
|
|
6
|
+
var _getLocationUrl = _interopRequireDefault(require("../getLocationUrl"));
|
|
7
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
8
|
+
class LocationDataStorage {
|
|
9
|
+
constructor(session, {
|
|
10
|
+
namespace
|
|
11
|
+
}) {
|
|
12
|
+
this._storage = new _DataStorage.default(session, {
|
|
13
|
+
namespace
|
|
14
|
+
});
|
|
15
|
+
this._getFallbackLocationKey = _getLocationUrl.default;
|
|
16
|
+
}
|
|
17
|
+
get(location, key) {
|
|
18
|
+
return this._storage.get(this._getKey(location, key));
|
|
19
|
+
}
|
|
20
|
+
set(location, key, value) {
|
|
21
|
+
this._storage.set(this._getKey(location, key), value);
|
|
22
|
+
}
|
|
23
|
+
_getKey(location, key) {
|
|
24
|
+
const locationKey = location.key || this._getFallbackLocationKey(location);
|
|
25
|
+
return `${locationKey}|${key}`;
|
|
26
|
+
}
|
|
27
|
+
}
|
|
28
|
+
exports.default = LocationDataStorage;
|
|
29
|
+
module.exports = exports.default;
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
exports.__esModule = true;
|
|
4
|
+
exports.LocationDataStorage = exports.DataStorage = void 0;
|
|
5
|
+
var _DataStorage = _interopRequireDefault(require("./DataStorage"));
|
|
6
|
+
exports.DataStorage = _DataStorage.default;
|
|
7
|
+
var _LocationDataStorage = _interopRequireDefault(require("./LocationDataStorage"));
|
|
8
|
+
exports.LocationDataStorage = _LocationDataStorage.default;
|
|
9
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
exports.__esModule = true;
|
|
4
|
+
exports.default = void 0;
|
|
5
|
+
var _InMemoryDataStorage = _interopRequireDefault(require("./data-storage/InMemoryDataStorage"));
|
|
6
|
+
var _InMemoryScrollPosition = _interopRequireDefault(require("./scroll-position/InMemoryScrollPosition"));
|
|
7
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
8
|
+
class InMemoryEnvironment {
|
|
9
|
+
constructor() {
|
|
10
|
+
this.dataStorage = new _InMemoryDataStorage.default();
|
|
11
|
+
this.scrollPosition = new _InMemoryScrollPosition.default();
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
exports.default = InMemoryEnvironment;
|
|
15
|
+
module.exports = exports.default;
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
exports.__esModule = true;
|
|
4
|
+
exports.default = void 0;
|
|
5
|
+
var _WebBrowserDataStorage = _interopRequireDefault(require("./data-storage/WebBrowserDataStorage"));
|
|
6
|
+
var _WebBrowserScrollPosition = _interopRequireDefault(require("./scroll-position/WebBrowserScrollPosition"));
|
|
7
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
8
|
+
class WebBrowserEnvironment {
|
|
9
|
+
constructor() {
|
|
10
|
+
this.dataStorage = new _WebBrowserDataStorage.default();
|
|
11
|
+
this.scrollPosition = new _WebBrowserScrollPosition.default();
|
|
12
|
+
}
|
|
13
|
+
}
|
|
14
|
+
exports.default = WebBrowserEnvironment;
|
|
15
|
+
module.exports = exports.default;
|
|
@@ -0,0 +1,27 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
exports.__esModule = true;
|
|
4
|
+
exports.default = void 0;
|
|
5
|
+
class InMemoryDataStorage {
|
|
6
|
+
constructor() {
|
|
7
|
+
this._state = {};
|
|
8
|
+
}
|
|
9
|
+
|
|
10
|
+
// Returns either a `string` value or `null` if the key doesn't exist.
|
|
11
|
+
get(key) {
|
|
12
|
+
if (key in this._state) {
|
|
13
|
+
return this._state[key];
|
|
14
|
+
}
|
|
15
|
+
return null;
|
|
16
|
+
}
|
|
17
|
+
remove(key) {
|
|
18
|
+
if (key in this._state) {
|
|
19
|
+
delete this._state[key];
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
set(key, value) {
|
|
23
|
+
this._state[key] = value;
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
exports.default = InMemoryDataStorage;
|
|
27
|
+
module.exports = exports.default;
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
exports.__esModule = true;
|
|
4
|
+
exports.default = void 0;
|
|
5
|
+
class WebBrowserDataStorage {
|
|
6
|
+
// Returns either a `string` value or `null` if the key doesn't exist.
|
|
7
|
+
get(key) {
|
|
8
|
+
// `sessionStorage` persists across page reloads, and so does web browser navigation history.
|
|
9
|
+
return window.sessionStorage.getItem(key);
|
|
10
|
+
}
|
|
11
|
+
remove(key) {
|
|
12
|
+
// `sessionStorage` persists across page reloads, and so does web browser navigation history.
|
|
13
|
+
window.sessionStorage.removeItem(key);
|
|
14
|
+
}
|
|
15
|
+
set(key, value) {
|
|
16
|
+
// `sessionStorage` persists across page reloads, and so does web browser navigation history.
|
|
17
|
+
window.sessionStorage.setItem(key, value);
|
|
18
|
+
}
|
|
19
|
+
}
|
|
20
|
+
exports.default = WebBrowserDataStorage;
|
|
21
|
+
module.exports = exports.default;
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
exports.__esModule = true;
|
|
4
|
+
exports.default = void 0;
|
|
5
|
+
class InMemoryScrollPosition {
|
|
6
|
+
constructor() {
|
|
7
|
+
this.init();
|
|
8
|
+
}
|
|
9
|
+
getPageScrollPosition() {
|
|
10
|
+
return this._pageScrollPosition || [0, 0];
|
|
11
|
+
}
|
|
12
|
+
setPageScrollPosition(scrollPosition) {
|
|
13
|
+
this._pageScrollPosition = scrollPosition;
|
|
14
|
+
}
|
|
15
|
+
|
|
16
|
+
// eslint-disable-next-line no-unused-vars
|
|
17
|
+
setPageScrollPositionAtAnchor(anchor) {
|
|
18
|
+
this.setPageScrollPosition([0, 0]);
|
|
19
|
+
}
|
|
20
|
+
getScrollableContainerScrollPosition(key) {
|
|
21
|
+
return this._scrollableContainerScrollPositions[key] || [0, 0];
|
|
22
|
+
}
|
|
23
|
+
setScrollableContainerScrollPosition(key, scrollPosition) {
|
|
24
|
+
this._scrollableContainerScrollPositions[key] = scrollPosition;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
// eslint-disable-next-line no-unused-vars
|
|
28
|
+
addPageScrollListener(listener) {
|
|
29
|
+
return () => {};
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
// eslint-disable-next-line no-unused-vars
|
|
33
|
+
addScrollableContainerScrollListener(scrollableContainerElement, listener) {
|
|
34
|
+
return () => {};
|
|
35
|
+
}
|
|
36
|
+
enableAutomaticScrollRestoration() {}
|
|
37
|
+
disableAutomaticScrollRestoration() {}
|
|
38
|
+
init() {
|
|
39
|
+
this._pageScrollPosition = undefined;
|
|
40
|
+
this._scrollableContainerScrollPositions = {};
|
|
41
|
+
}
|
|
42
|
+
}
|
|
43
|
+
exports.default = InMemoryScrollPosition;
|
|
44
|
+
module.exports = exports.default;
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
exports.__esModule = true;
|
|
4
|
+
exports.default = void 0;
|
|
5
|
+
class WebBrowserScrollPosition {
|
|
6
|
+
getPageScrollPosition() {
|
|
7
|
+
return [window.pageXOffset, window.pageYOffset];
|
|
8
|
+
}
|
|
9
|
+
setPageScrollPosition(scrollPosition) {
|
|
10
|
+
const [scrollX, scrollY] = scrollPosition;
|
|
11
|
+
window.scrollTo(scrollX, scrollY);
|
|
12
|
+
}
|
|
13
|
+
setPageScrollPositionAtAnchor(anchor) {
|
|
14
|
+
const anchorElement = document.getElementById(anchor) || document.getElementsByName(anchor)[0];
|
|
15
|
+
if (anchorElement) {
|
|
16
|
+
// By default it scrolls the element into view
|
|
17
|
+
// so that it's visible at the top of the window.
|
|
18
|
+
anchorElement.scrollIntoView();
|
|
19
|
+
} else {
|
|
20
|
+
this.setPageScrollPosition([0, 0]);
|
|
21
|
+
}
|
|
22
|
+
}
|
|
23
|
+
getScrollableContainerScrollPosition(scrollableContainerElement) {
|
|
24
|
+
return [scrollableContainerElement.scrollLeft, scrollableContainerElement.scrollTop];
|
|
25
|
+
}
|
|
26
|
+
setScrollableContainerScrollPosition(scrollableContainerElement, scrollPosition) {
|
|
27
|
+
const [scrollX, scrollY] = scrollPosition;
|
|
28
|
+
scrollableContainerElement.scrollLeft = scrollX;
|
|
29
|
+
scrollableContainerElement.scrollTop = scrollY;
|
|
30
|
+
}
|
|
31
|
+
addPageScrollListener(listener) {
|
|
32
|
+
// eslint-disable-next-line no-unused-vars
|
|
33
|
+
const scrollListener = event => {
|
|
34
|
+
listener();
|
|
35
|
+
};
|
|
36
|
+
window.addEventListener('scroll', scrollListener);
|
|
37
|
+
return () => {
|
|
38
|
+
window.removeEventListener('scroll', scrollListener);
|
|
39
|
+
};
|
|
40
|
+
}
|
|
41
|
+
addScrollableContainerScrollListener(scrollableContainerElement, listener) {
|
|
42
|
+
// eslint-disable-next-line no-unused-vars
|
|
43
|
+
const scrollListener = event => {
|
|
44
|
+
listener();
|
|
45
|
+
};
|
|
46
|
+
scrollableContainerElement.addEventListener('scroll', scrollListener);
|
|
47
|
+
return () => {
|
|
48
|
+
scrollableContainerElement.removeEventListener('scroll', scrollListener);
|
|
49
|
+
};
|
|
50
|
+
}
|
|
51
|
+
enableAutomaticScrollRestoration() {
|
|
52
|
+
window.history.scrollRestoration = 'auto';
|
|
53
|
+
}
|
|
54
|
+
disableAutomaticScrollRestoration() {
|
|
55
|
+
window.history.scrollRestoration = 'manual';
|
|
56
|
+
}
|
|
57
|
+
init() {}
|
|
58
|
+
}
|
|
59
|
+
exports.default = WebBrowserScrollPosition;
|
|
60
|
+
module.exports = exports.default;
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
exports.__esModule = true;
|
|
4
|
+
exports.default = getLocationFromInternalLocation;
|
|
5
|
+
const _excluded = ["operation", "index", "delta"];
|
|
6
|
+
function _objectWithoutPropertiesLoose(r, e) { if (null == r) return {}; var t = {}; for (var n in r) if ({}.hasOwnProperty.call(r, n)) { if (-1 !== e.indexOf(n)) continue; t[n] = r[n]; } return t; }
|
|
7
|
+
// Converts `LocationInternal` object to a publicly-visible `Location` object.
|
|
8
|
+
// It hides non-essential properties of location such as `operation`, `index`, `delta`.
|
|
9
|
+
function getLocationFromInternalLocation(internalLocation) {
|
|
10
|
+
// eslint-disable-next-line no-unused-vars
|
|
11
|
+
const location = _objectWithoutPropertiesLoose(internalLocation, _excluded);
|
|
12
|
+
return location;
|
|
13
|
+
}
|
|
14
|
+
module.exports = exports.default;
|
package/lib/cjs/index.js
CHANGED
|
@@ -1,11 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
exports.__esModule = true;
|
|
4
|
-
exports.removeBasePath = exports.parseLocationUrl = exports.
|
|
5
|
-
var _Actions = _interopRequireDefault(require("./Actions"));
|
|
6
|
-
exports.Actions = _Actions.default;
|
|
7
|
-
var _ActionTypes = _interopRequireDefault(require("./ActionTypes"));
|
|
8
|
-
exports.ActionTypes = _ActionTypes.default;
|
|
4
|
+
exports.removeBasePath = exports.parseLocationUrl = exports.parseInputLocation = exports.getLocationUrl = exports.addNavigationBlocker = exports.addBasePath = exports.WebBrowserSession = exports.Session = exports.ServerSideRenderSession = exports.ServerSideNavigationError = exports.NavigationStack = exports.NavigationOutOfBoundsError = exports.LocationDataStorage = exports.InMemorySession = exports.DataStorage = void 0;
|
|
9
5
|
var _basePath = require("./basePath");
|
|
10
6
|
exports.addBasePath = _basePath.addBasePath;
|
|
11
7
|
exports.removeBasePath = _basePath.removeBasePath;
|
|
@@ -15,16 +11,24 @@ var _getLocationUrl = _interopRequireDefault(require("./getLocationUrl"));
|
|
|
15
11
|
exports.getLocationUrl = _getLocationUrl.default;
|
|
16
12
|
var _parseLocationUrl = _interopRequireDefault(require("./parseLocationUrl"));
|
|
17
13
|
exports.parseLocationUrl = _parseLocationUrl.default;
|
|
18
|
-
var
|
|
19
|
-
exports.
|
|
20
|
-
var
|
|
21
|
-
exports.
|
|
22
|
-
var
|
|
14
|
+
var _parseInputLocation = _interopRequireDefault(require("./parseInputLocation"));
|
|
15
|
+
exports.parseInputLocation = _parseInputLocation.default;
|
|
16
|
+
var _NavigationStack = _interopRequireDefault(require("./NavigationStack"));
|
|
17
|
+
exports.NavigationStack = _NavigationStack.default;
|
|
18
|
+
var _DataStorage = _interopRequireDefault(require("./data-storage/DataStorage"));
|
|
19
|
+
exports.DataStorage = _DataStorage.default;
|
|
20
|
+
var _LocationDataStorage = _interopRequireDefault(require("./data-storage/LocationDataStorage"));
|
|
23
21
|
exports.LocationDataStorage = _LocationDataStorage.default;
|
|
24
|
-
var
|
|
25
|
-
exports.
|
|
26
|
-
var
|
|
27
|
-
exports.
|
|
28
|
-
var
|
|
29
|
-
exports.
|
|
22
|
+
var _Session = _interopRequireDefault(require("./session/Session"));
|
|
23
|
+
exports.Session = _Session.default;
|
|
24
|
+
var _InMemorySession = _interopRequireDefault(require("./session/InMemorySession"));
|
|
25
|
+
exports.InMemorySession = _InMemorySession.default;
|
|
26
|
+
var _WebBrowserSession = _interopRequireDefault(require("./session/WebBrowserSession"));
|
|
27
|
+
exports.WebBrowserSession = _WebBrowserSession.default;
|
|
28
|
+
var _ServerSideRenderSession = _interopRequireDefault(require("./session/ServerSideRenderSession"));
|
|
29
|
+
exports.ServerSideRenderSession = _ServerSideRenderSession.default;
|
|
30
|
+
var _ServerSideNavigationError = _interopRequireDefault(require("./session/navigation/error/ServerSideNavigationError"));
|
|
31
|
+
exports.ServerSideNavigationError = _ServerSideNavigationError.default;
|
|
32
|
+
var _NavigationOutOfBoundsError = _interopRequireDefault(require("./session/navigation/error/NavigationOutOfBoundsError"));
|
|
33
|
+
exports.NavigationOutOfBoundsError = _NavigationOutOfBoundsError.default;
|
|
30
34
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
@@ -24,12 +24,12 @@ function removeNavigationBlockerFromTheList(blocker, session) {
|
|
|
24
24
|
}
|
|
25
25
|
}
|
|
26
26
|
function removeAllNavigationBlockers(session) {
|
|
27
|
-
if (getNavigationBlockers(session).some(blocker => blocker.
|
|
28
|
-
if (!session.
|
|
29
|
-
throw new Error('`
|
|
27
|
+
if (getNavigationBlockers(session).some(blocker => blocker.beforeTermination)) {
|
|
28
|
+
if (!session._removeTerminationBlocker) {
|
|
29
|
+
throw new Error('`_removeTerminationBlocker` property not found in the `session`');
|
|
30
30
|
}
|
|
31
|
-
session.
|
|
32
|
-
session.
|
|
31
|
+
session._removeTerminationBlocker();
|
|
32
|
+
session._removeTerminationBlocker = undefined;
|
|
33
33
|
}
|
|
34
34
|
session._navigationBlockersList = [];
|
|
35
35
|
}
|
|
@@ -92,33 +92,33 @@ function runNavigationBlockers(navigationBlockers, toLocation) {
|
|
|
92
92
|
}
|
|
93
93
|
|
|
94
94
|
/* istanbul ignore next: not testable with Karma */
|
|
95
|
-
function
|
|
95
|
+
function terminationBlocker(session) {
|
|
96
96
|
const result = runNavigationBlockers(getNavigationBlockers(session), null);
|
|
97
97
|
|
|
98
|
-
// If no blocker returned anything, don't prevent the
|
|
98
|
+
// If no blocker returned anything, so don't prevent the navigation.
|
|
99
99
|
if (!result) {
|
|
100
100
|
return undefined;
|
|
101
101
|
}
|
|
102
102
|
|
|
103
103
|
// Web browsers don't allow displaying a custom modal in "beforeunload" phase.
|
|
104
104
|
// They only allow displaying a standard one, with the default text.
|
|
105
|
-
// Hence, "asynchronous" blockers should be ignored.
|
|
105
|
+
// Hence, "asynchronous" blockers should be ignored because web browsers won't wait for those to finish anyway.
|
|
106
106
|
// https://developer.mozilla.org/en-US/docs/Web/API/Window/beforeunload_event
|
|
107
107
|
if ((0, _isPromise.default)(result)) {
|
|
108
108
|
return undefined;
|
|
109
109
|
}
|
|
110
110
|
|
|
111
|
-
//
|
|
111
|
+
// Block the navigation.
|
|
112
112
|
return true;
|
|
113
113
|
}
|
|
114
114
|
function addNavigationBlocker(session, blocker) {
|
|
115
|
-
// All navigation blockers also run on `
|
|
115
|
+
// All navigation blockers also run on `beforeTermination` event.
|
|
116
116
|
// If required, this could be a parameter of this function.
|
|
117
117
|
// The rationale could be that adding a `beforeunload` listener
|
|
118
118
|
// disables web page caching in some browsers like Firefox.
|
|
119
|
-
const
|
|
119
|
+
const beforeTermination = true;
|
|
120
120
|
|
|
121
|
-
// If it's the first "
|
|
121
|
+
// If it's the first "beforeTermination" blocker, add a `terminationBlocker`.
|
|
122
122
|
//
|
|
123
123
|
// Sidenote: Add the "beforeunload" event listener only as needed, as its presence
|
|
124
124
|
// prevents the page from being added to the page navigation cache:
|
|
@@ -128,27 +128,29 @@ function addNavigationBlocker(session, blocker) {
|
|
|
128
128
|
// and this is bad for performance."
|
|
129
129
|
//
|
|
130
130
|
// https://developer.mozilla.org/en-US/docs/Web/API/Window/beforeunload_event
|
|
131
|
-
if (
|
|
132
|
-
if (session.
|
|
133
|
-
throw new Error('Unexpected `
|
|
131
|
+
if (beforeTermination && !getNavigationBlockers(session).some(navigationBlocker => navigationBlocker.beforeTermination)) {
|
|
132
|
+
if (session._removeTerminationBlocker) {
|
|
133
|
+
throw new Error('Unexpected `_removeTerminationBlocker` property found in the `session`');
|
|
134
134
|
}
|
|
135
|
-
session.
|
|
135
|
+
session._removeTerminationBlocker = session.lifecycle.addTerminationBlocker(() => {
|
|
136
|
+
return terminationBlocker(session);
|
|
137
|
+
});
|
|
136
138
|
}
|
|
137
139
|
const newNavigationBlocker = {
|
|
138
140
|
blocker,
|
|
139
|
-
|
|
141
|
+
beforeTermination
|
|
140
142
|
};
|
|
141
143
|
addNavigationBlockerToTheList(newNavigationBlocker, session);
|
|
142
144
|
return () => {
|
|
143
145
|
removeNavigationBlockerFromTheList(newNavigationBlocker, session);
|
|
144
146
|
|
|
145
|
-
// If it was the last "
|
|
146
|
-
if (
|
|
147
|
-
if (!session.
|
|
148
|
-
throw new Error('`
|
|
147
|
+
// If it was the last "beforeTermination" blocker, remove navigation blocker.
|
|
148
|
+
if (beforeTermination && !getNavigationBlockers(session).some(navigationBlocker => navigationBlocker.beforeTermination)) {
|
|
149
|
+
if (!session._removeTerminationBlocker) {
|
|
150
|
+
throw new Error('`_removeTerminationBlocker` property not found in the `session`');
|
|
149
151
|
}
|
|
150
|
-
session.
|
|
151
|
-
session.
|
|
152
|
+
session._removeTerminationBlocker();
|
|
153
|
+
session._removeTerminationBlocker = undefined;
|
|
152
154
|
}
|
|
153
155
|
};
|
|
154
156
|
}
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
exports.__esModule = true;
|
|
4
|
-
exports.default =
|
|
4
|
+
exports.default = parseInputLocation;
|
|
5
5
|
var _createSearchFromQuery = _interopRequireDefault(require("./createSearchFromQuery"));
|
|
6
6
|
var _parseLocationUrl = _interopRequireDefault(require("./parseLocationUrl"));
|
|
7
7
|
var _parseQueryFromSearch = _interopRequireDefault(require("./parseQueryFromSearch"));
|
|
8
8
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
9
|
-
// * If `location` is a string, it parses it into a `
|
|
9
|
+
// * If `location` is a string, it parses it into a `LocationBase`.
|
|
10
10
|
// * If `location` is an object, it ensures that `search` and `hash` properties aren't `undefined`,
|
|
11
|
-
// i.e. it "ensures" that the `location` object can be used as a `
|
|
12
|
-
function
|
|
11
|
+
// i.e. it "ensures" that the `location` object can be used as a `LocationBase`.
|
|
12
|
+
function parseInputLocation(location) {
|
|
13
13
|
if (typeof location === 'string') {
|
|
14
14
|
return (0, _parseLocationUrl.default)(location);
|
|
15
15
|
}
|
|
@@ -17,7 +17,13 @@ function normalizeInputLocation(location) {
|
|
|
17
17
|
// Convert `query` property values to strings.
|
|
18
18
|
if (location.query) {
|
|
19
19
|
for (const key of Object.keys(location.query)) {
|
|
20
|
-
location.query[key]
|
|
20
|
+
if (typeof location.query[key] !== 'string') {
|
|
21
|
+
location = Object.assign({}, location, {
|
|
22
|
+
query: Object.assign({}, location.query, {
|
|
23
|
+
[key]: String(location.query[key])
|
|
24
|
+
})
|
|
25
|
+
});
|
|
26
|
+
}
|
|
21
27
|
}
|
|
22
28
|
}
|
|
23
29
|
|
|
@@ -36,12 +42,22 @@ function normalizeInputLocation(location) {
|
|
|
36
42
|
});
|
|
37
43
|
}
|
|
38
44
|
|
|
39
|
-
// Set default values
|
|
40
|
-
//
|
|
41
|
-
|
|
45
|
+
// Set default values for properties that're not present.
|
|
46
|
+
// Ignore unknown properties.
|
|
47
|
+
const {
|
|
48
|
+
state
|
|
49
|
+
} = location;
|
|
50
|
+
location = {
|
|
51
|
+
pathname: location.pathname,
|
|
42
52
|
query: location.query || {},
|
|
43
53
|
search: location.search || '',
|
|
44
54
|
hash: location.hash || ''
|
|
45
|
-
}
|
|
55
|
+
};
|
|
56
|
+
if (state) {
|
|
57
|
+
location.state = state;
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
// Return `location`.
|
|
61
|
+
return location;
|
|
46
62
|
}
|
|
47
63
|
module.exports = exports.default;
|