navigation-stack 0.3.1 → 0.5.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/CHANGELOG.md +12 -0
- package/README.md +611 -163
- package/data-storage/package.json +6 -0
- package/karma.conf.cjs +21 -4
- package/lib/cjs/NavigationStack.js +88 -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/debug.js +12 -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 +28 -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 +141 -0
- package/lib/cjs/scroll-position/ScrollPositionRestoration.js +407 -0
- package/lib/cjs/scroll-position/ScrollPositionSaver.js +87 -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 +202 -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 +81 -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/debug.js +7 -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 +28 -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 +134 -0
- package/lib/esm/scroll-position/ScrollPositionRestoration.js +400 -0
- package/lib/esm/scroll-position/ScrollPositionSaver.js +80 -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 +195 -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 +179 -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 +100 -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/debug.js +8 -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 +31 -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 +168 -0
- package/src/scroll-position/ScrollPositionRestoration.js +551 -0
- package/src/scroll-position/ScrollPositionSaver.js +120 -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 +238 -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 +435 -0
- package/test/scroll-position/addScrollableContainer.js +39 -0
- package/test/scroll-position/addScrollableContainerWithAnchors.js +56 -0
- package/test/scroll-position/createApp.js +132 -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/withScrollableContainerAtIndexPageWithDisabledAutomaticScrollPositionRestoration.js +72 -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 +179 -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,88 @@
|
|
|
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
|
+
const _excluded = ["maintainScrollPosition"];
|
|
11
|
+
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
12
|
+
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; }
|
|
13
|
+
function getCreateMiddlewaresOptions(navigationStackOptions) {
|
|
14
|
+
if (!navigationStackOptions) {
|
|
15
|
+
return undefined;
|
|
16
|
+
}
|
|
17
|
+
// eslint-disable-next-line no-unused-vars
|
|
18
|
+
const restOptions = _objectWithoutPropertiesLoose(navigationStackOptions, _excluded);
|
|
19
|
+
return restOptions;
|
|
20
|
+
}
|
|
21
|
+
class NavigationStack {
|
|
22
|
+
constructor(session, options) {
|
|
23
|
+
this._session = session;
|
|
24
|
+
|
|
25
|
+
// Create a Redux store.
|
|
26
|
+
this._store = (0, _redux.createStore)(_locationReducer.default, (0, _redux.applyMiddleware)(...(0, _createMiddlewares.default)(session, getCreateMiddlewaresOptions(options))));
|
|
27
|
+
|
|
28
|
+
// Create `ScrollPositionRestoration`.
|
|
29
|
+
if (options && options.maintainScrollPosition) {
|
|
30
|
+
this._scrollPositionRestoration = new _ScrollPositionRestoration.default(session);
|
|
31
|
+
}
|
|
32
|
+
}
|
|
33
|
+
addScrollableContainer(scrollableContainerKey, scrollableContainer) {
|
|
34
|
+
if (!this._scrollPositionRestoration) {
|
|
35
|
+
throw new Error('`maintainScrollPosition: true` option not passed');
|
|
36
|
+
}
|
|
37
|
+
return this._scrollPositionRestoration.addScrollableContainer(scrollableContainerKey, scrollableContainer);
|
|
38
|
+
}
|
|
39
|
+
subscribe(listener) {
|
|
40
|
+
// Subscribe to any potential Redux state changes.
|
|
41
|
+
return this._store.subscribe(() => {
|
|
42
|
+
// Initially, calls the listener when setting the initial location.
|
|
43
|
+
// After that, calls it on any location change.
|
|
44
|
+
const location = this.current();
|
|
45
|
+
if (!this._latestLocation || location !== this._latestLocation) {
|
|
46
|
+
this._latestLocation = location;
|
|
47
|
+
listener(location);
|
|
48
|
+
}
|
|
49
|
+
});
|
|
50
|
+
}
|
|
51
|
+
init(initialLocation) {
|
|
52
|
+
if (this._latestLocation) {
|
|
53
|
+
throw new Error('Already initialized');
|
|
54
|
+
}
|
|
55
|
+
this._store.dispatch(_Actions.default.init(initialLocation));
|
|
56
|
+
this._latestLocation = this.current();
|
|
57
|
+
}
|
|
58
|
+
current() {
|
|
59
|
+
return this._store.getState();
|
|
60
|
+
}
|
|
61
|
+
push(location) {
|
|
62
|
+
this._store.dispatch(_Actions.default.push(location));
|
|
63
|
+
}
|
|
64
|
+
replace(location) {
|
|
65
|
+
this._store.dispatch(_Actions.default.replace(location));
|
|
66
|
+
}
|
|
67
|
+
shift(delta) {
|
|
68
|
+
this._store.dispatch(_Actions.default.shift(delta));
|
|
69
|
+
}
|
|
70
|
+
stop() {
|
|
71
|
+
if (this._scrollPositionRestoration) {
|
|
72
|
+
this._scrollPositionRestoration.stop();
|
|
73
|
+
}
|
|
74
|
+
this._store.dispatch(_Actions.default.stop());
|
|
75
|
+
}
|
|
76
|
+
locationRendered() {
|
|
77
|
+
if (this._scrollPositionRestoration) {
|
|
78
|
+
const location = this.current();
|
|
79
|
+
if (!location) {
|
|
80
|
+
throw new Error('Not initialized');
|
|
81
|
+
}
|
|
82
|
+
return this._scrollPositionRestoration.locationRendered(location);
|
|
83
|
+
}
|
|
84
|
+
return Promise.resolve();
|
|
85
|
+
}
|
|
86
|
+
}
|
|
87
|
+
exports.default = NavigationStack;
|
|
88
|
+
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 }; }
|
package/lib/cjs/debug.js
ADDED
|
@@ -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", "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` and `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 }; }
|
|
@@ -5,6 +5,7 @@ exports.addNavigationBlocker = addNavigationBlocker;
|
|
|
5
5
|
exports.getNavigationBlockers = getNavigationBlockers;
|
|
6
6
|
exports.removeAllNavigationBlockers = removeAllNavigationBlockers;
|
|
7
7
|
exports.runNavigationBlockers = runNavigationBlockers;
|
|
8
|
+
var _debug = _interopRequireDefault(require("./debug"));
|
|
8
9
|
var _isPromise = _interopRequireDefault(require("./isPromise"));
|
|
9
10
|
function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
|
|
10
11
|
/* eslint-disable no-underscore-dangle */
|
|
@@ -24,12 +25,12 @@ function removeNavigationBlockerFromTheList(blocker, session) {
|
|
|
24
25
|
}
|
|
25
26
|
}
|
|
26
27
|
function removeAllNavigationBlockers(session) {
|
|
27
|
-
if (getNavigationBlockers(session).some(blocker => blocker.
|
|
28
|
-
if (!session.
|
|
29
|
-
throw new Error('`
|
|
28
|
+
if (getNavigationBlockers(session).some(blocker => blocker.beforeTermination)) {
|
|
29
|
+
if (!session._removeTerminationBlocker) {
|
|
30
|
+
throw new Error('`_removeTerminationBlocker` property not found in the `session`');
|
|
30
31
|
}
|
|
31
|
-
session.
|
|
32
|
-
session.
|
|
32
|
+
session._removeTerminationBlocker();
|
|
33
|
+
session._removeTerminationBlocker = undefined;
|
|
33
34
|
}
|
|
34
35
|
session._navigationBlockersList = [];
|
|
35
36
|
}
|
|
@@ -80,45 +81,47 @@ function runNavigationBlockers(navigationBlockers, toLocation) {
|
|
|
80
81
|
if ((0, _isPromise.default)(result)) {
|
|
81
82
|
return result.then(resultValue => {
|
|
82
83
|
if (resultValue) {
|
|
84
|
+
(0, _debug.default)('Navigation blocked', toLocation.pathname);
|
|
83
85
|
return resultValue;
|
|
84
86
|
}
|
|
85
87
|
return next();
|
|
86
88
|
});
|
|
87
89
|
}
|
|
88
90
|
if (result) {
|
|
91
|
+
(0, _debug.default)('Navigation blocked', toLocation.pathname);
|
|
89
92
|
return result;
|
|
90
93
|
}
|
|
91
94
|
return next();
|
|
92
95
|
}
|
|
93
96
|
|
|
94
97
|
/* istanbul ignore next: not testable with Karma */
|
|
95
|
-
function
|
|
98
|
+
function terminationBlocker(session) {
|
|
96
99
|
const result = runNavigationBlockers(getNavigationBlockers(session), null);
|
|
97
100
|
|
|
98
|
-
// If no blocker returned anything, don't prevent the
|
|
101
|
+
// If no blocker returned anything, so don't prevent the navigation.
|
|
99
102
|
if (!result) {
|
|
100
103
|
return undefined;
|
|
101
104
|
}
|
|
102
105
|
|
|
103
106
|
// Web browsers don't allow displaying a custom modal in "beforeunload" phase.
|
|
104
107
|
// They only allow displaying a standard one, with the default text.
|
|
105
|
-
// Hence, "asynchronous" blockers should be ignored.
|
|
108
|
+
// Hence, "asynchronous" blockers should be ignored because web browsers won't wait for those to finish anyway.
|
|
106
109
|
// https://developer.mozilla.org/en-US/docs/Web/API/Window/beforeunload_event
|
|
107
110
|
if ((0, _isPromise.default)(result)) {
|
|
108
111
|
return undefined;
|
|
109
112
|
}
|
|
110
113
|
|
|
111
|
-
//
|
|
114
|
+
// Block the navigation.
|
|
112
115
|
return true;
|
|
113
116
|
}
|
|
114
117
|
function addNavigationBlocker(session, blocker) {
|
|
115
|
-
// All navigation blockers also run on `
|
|
118
|
+
// All navigation blockers also run on `beforeTermination` event.
|
|
116
119
|
// If required, this could be a parameter of this function.
|
|
117
120
|
// The rationale could be that adding a `beforeunload` listener
|
|
118
121
|
// disables web page caching in some browsers like Firefox.
|
|
119
|
-
const
|
|
122
|
+
const beforeTermination = true;
|
|
120
123
|
|
|
121
|
-
// If it's the first "
|
|
124
|
+
// If it's the first "beforeTermination" blocker, add a `terminationBlocker`.
|
|
122
125
|
//
|
|
123
126
|
// Sidenote: Add the "beforeunload" event listener only as needed, as its presence
|
|
124
127
|
// prevents the page from being added to the page navigation cache:
|
|
@@ -128,27 +131,29 @@ function addNavigationBlocker(session, blocker) {
|
|
|
128
131
|
// and this is bad for performance."
|
|
129
132
|
//
|
|
130
133
|
// https://developer.mozilla.org/en-US/docs/Web/API/Window/beforeunload_event
|
|
131
|
-
if (
|
|
132
|
-
if (session.
|
|
133
|
-
throw new Error('Unexpected `
|
|
134
|
+
if (beforeTermination && !getNavigationBlockers(session).some(navigationBlocker => navigationBlocker.beforeTermination)) {
|
|
135
|
+
if (session._removeTerminationBlocker) {
|
|
136
|
+
throw new Error('Unexpected `_removeTerminationBlocker` property found in the `session`');
|
|
134
137
|
}
|
|
135
|
-
session.
|
|
138
|
+
session._removeTerminationBlocker = session.lifecycle.addTerminationBlocker(() => {
|
|
139
|
+
return terminationBlocker(session);
|
|
140
|
+
});
|
|
136
141
|
}
|
|
137
142
|
const newNavigationBlocker = {
|
|
138
143
|
blocker,
|
|
139
|
-
|
|
144
|
+
beforeTermination
|
|
140
145
|
};
|
|
141
146
|
addNavigationBlockerToTheList(newNavigationBlocker, session);
|
|
142
147
|
return () => {
|
|
143
148
|
removeNavigationBlockerFromTheList(newNavigationBlocker, session);
|
|
144
149
|
|
|
145
|
-
// If it was the last "
|
|
146
|
-
if (
|
|
147
|
-
if (!session.
|
|
148
|
-
throw new Error('`
|
|
150
|
+
// If it was the last "beforeTermination" blocker, remove navigation blocker.
|
|
151
|
+
if (beforeTermination && !getNavigationBlockers(session).some(navigationBlocker => navigationBlocker.beforeTermination)) {
|
|
152
|
+
if (!session._removeTerminationBlocker) {
|
|
153
|
+
throw new Error('`_removeTerminationBlocker` property not found in the `session`');
|
|
149
154
|
}
|
|
150
|
-
session.
|
|
151
|
-
session.
|
|
155
|
+
session._removeTerminationBlocker();
|
|
156
|
+
session._removeTerminationBlocker = undefined;
|
|
152
157
|
}
|
|
153
158
|
};
|
|
154
159
|
}
|