navigation-stack 0.3.0 → 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.
Files changed (253) hide show
  1. package/README.md +603 -163
  2. package/data-storage/package.json +6 -0
  3. package/karma.conf.cjs +21 -4
  4. package/lib/cjs/NavigationStack.js +73 -0
  5. package/lib/cjs/data-storage/DataStorage.js +71 -0
  6. package/lib/cjs/data-storage/LocationDataStorage.js +29 -0
  7. package/lib/cjs/data-storage/index.js +9 -0
  8. package/lib/cjs/environment/InMemoryEnvironment.js +15 -0
  9. package/lib/cjs/environment/WebBrowserEnvironment.js +15 -0
  10. package/lib/cjs/environment/data-storage/InMemoryDataStorage.js +27 -0
  11. package/lib/cjs/environment/data-storage/WebBrowserDataStorage.js +21 -0
  12. package/lib/cjs/environment/scroll-position/InMemoryScrollPosition.js +44 -0
  13. package/lib/cjs/environment/scroll-position/WebBrowserScrollPosition.js +60 -0
  14. package/lib/cjs/getLocationFromInternalLocation.js +14 -0
  15. package/lib/cjs/index.js +20 -16
  16. package/lib/cjs/navigationBlockers.js +25 -23
  17. package/lib/cjs/{normalizeInputLocation.js → parseInputLocation.js} +25 -9
  18. package/lib/cjs/{ActionTypes.js → redux/ActionTypes.js} +1 -1
  19. package/lib/cjs/redux/ActionTypesInternal.js +8 -0
  20. package/lib/cjs/{Actions.js → redux/Actions.js} +5 -4
  21. package/lib/cjs/redux/createMiddlewares.js +60 -0
  22. package/lib/cjs/redux/index.js +13 -0
  23. package/lib/cjs/redux/internalLocationReducer.js +14 -0
  24. package/lib/cjs/redux/middleware/createAddInputLocationBasePathMiddleware.js +32 -0
  25. package/lib/cjs/redux/middleware/createNonProgrammaticNavigationBlockerMiddleware.js +113 -0
  26. package/lib/cjs/redux/middleware/createProgrammaticNavigationBlockerMiddleware.js +94 -0
  27. package/lib/cjs/redux/middleware/createRemoveOutputLocationBasePathMiddleware.js +30 -0
  28. package/lib/cjs/redux/middleware/createUpdateInternalLocationMiddleware.js +73 -0
  29. package/lib/cjs/{middleware/navigationActionMiddleware.js → redux/middleware/navigationOperationMiddleware.js} +11 -8
  30. package/lib/cjs/{middleware/normalizeInputLocationMiddleware.js → redux/middleware/parseInputLocationMiddleware.js} +6 -4
  31. package/lib/cjs/redux/middleware/updateLocationMiddleware.js +34 -0
  32. package/lib/cjs/scroll-position/PageScrollPositionSetter.js +97 -0
  33. package/lib/cjs/scroll-position/ScrollPositionAutoSaver.js +130 -0
  34. package/lib/cjs/scroll-position/ScrollPositionRestoration.js +383 -0
  35. package/lib/cjs/scroll-position/ScrollPositionSaver.js +81 -0
  36. package/lib/cjs/scroll-position/ScrollPositionSetter.js +16 -0
  37. package/lib/cjs/scroll-position/constants.js +5 -0
  38. package/lib/cjs/scroll-position/index.js +7 -0
  39. package/lib/cjs/scroll-position/scheduleNextTick.js +11 -0
  40. package/lib/cjs/session/InMemorySession.js +22 -0
  41. package/lib/cjs/session/ServerSideRenderSession.js +17 -0
  42. package/lib/cjs/session/Session.js +196 -0
  43. package/lib/cjs/session/WebBrowserSession.js +20 -0
  44. package/lib/cjs/session/key/createSessionKey.js +23 -0
  45. package/lib/cjs/session/lifecycle/InMemorySessionLifecycle.js +19 -0
  46. package/lib/cjs/session/lifecycle/WebBrowserSessionLifecycle.js +128 -0
  47. package/lib/cjs/session/lifecycle/page-lifecycle/PageLifecycle.js +269 -0
  48. package/lib/cjs/session/lifecycle/page-lifecycle/PageLifecycleInstance.js +8 -0
  49. package/lib/cjs/session/lifecycle/page-lifecycle/supportsConstructableEventTarget.js +33 -0
  50. package/lib/cjs/session/navigation/InMemoryNavigation.js +104 -0
  51. package/lib/cjs/session/navigation/ServerSideNavigation.js +61 -0
  52. package/lib/cjs/session/navigation/WebBrowserNavigation.js +221 -0
  53. package/lib/cjs/session/navigation/error/NavigationOutOfBoundsError.js +12 -0
  54. package/lib/cjs/session/navigation/error/ServerSideNavigationError.js +21 -0
  55. package/lib/cjs/session/navigation/operation/operations.js +11 -0
  56. package/lib/cjs/session/subscription/Subscription.js +81 -0
  57. package/lib/data-storage/index.d.ts +35 -0
  58. package/lib/esm/NavigationStack.js +66 -0
  59. package/lib/esm/data-storage/DataStorage.js +65 -0
  60. package/lib/esm/data-storage/LocationDataStorage.js +22 -0
  61. package/lib/esm/data-storage/index.js +2 -0
  62. package/lib/esm/environment/InMemoryEnvironment.js +8 -0
  63. package/lib/esm/environment/WebBrowserEnvironment.js +8 -0
  64. package/lib/esm/environment/data-storage/InMemoryDataStorage.js +21 -0
  65. package/lib/esm/environment/data-storage/WebBrowserDataStorage.js +15 -0
  66. package/lib/esm/environment/scroll-position/InMemoryScrollPosition.js +38 -0
  67. package/lib/esm/environment/scroll-position/WebBrowserScrollPosition.js +54 -0
  68. package/lib/esm/getLocationFromInternalLocation.js +9 -0
  69. package/lib/esm/index.js +10 -8
  70. package/lib/esm/navigationBlockers.js +25 -23
  71. package/lib/esm/{normalizeInputLocation.js → parseInputLocation.js} +24 -8
  72. package/lib/esm/{ActionTypes.js → redux/ActionTypes.js} +1 -1
  73. package/lib/esm/redux/ActionTypesInternal.js +3 -0
  74. package/lib/esm/{Actions.js → redux/Actions.js} +5 -4
  75. package/lib/esm/redux/createMiddlewares.js +54 -0
  76. package/lib/esm/redux/index.js +4 -0
  77. package/lib/esm/redux/internalLocationReducer.js +8 -0
  78. package/lib/esm/redux/middleware/createAddInputLocationBasePathMiddleware.js +27 -0
  79. package/lib/esm/redux/middleware/createNonProgrammaticNavigationBlockerMiddleware.js +108 -0
  80. package/lib/esm/redux/middleware/createProgrammaticNavigationBlockerMiddleware.js +88 -0
  81. package/lib/esm/redux/middleware/createRemoveOutputLocationBasePathMiddleware.js +25 -0
  82. package/lib/esm/redux/middleware/createUpdateInternalLocationMiddleware.js +68 -0
  83. package/lib/esm/{middleware/navigationActionMiddleware.js → redux/middleware/navigationOperationMiddleware.js} +10 -7
  84. package/lib/esm/{middleware/normalizeInputLocationMiddleware.js → redux/middleware/parseInputLocationMiddleware.js} +5 -3
  85. package/lib/esm/redux/middleware/updateLocationMiddleware.js +28 -0
  86. package/lib/esm/scroll-position/PageScrollPositionSetter.js +91 -0
  87. package/lib/esm/scroll-position/ScrollPositionAutoSaver.js +123 -0
  88. package/lib/esm/scroll-position/ScrollPositionRestoration.js +376 -0
  89. package/lib/esm/scroll-position/ScrollPositionSaver.js +74 -0
  90. package/lib/esm/scroll-position/ScrollPositionSetter.js +10 -0
  91. package/lib/esm/scroll-position/constants.js +1 -0
  92. package/lib/esm/scroll-position/index.js +1 -0
  93. package/lib/esm/scroll-position/scheduleNextTick.js +6 -0
  94. package/lib/esm/session/InMemorySession.js +15 -0
  95. package/lib/esm/session/ServerSideRenderSession.js +11 -0
  96. package/lib/esm/session/Session.js +189 -0
  97. package/lib/esm/session/WebBrowserSession.js +13 -0
  98. package/lib/esm/session/key/createSessionKey.js +18 -0
  99. package/lib/esm/session/lifecycle/InMemorySessionLifecycle.js +13 -0
  100. package/lib/esm/session/lifecycle/WebBrowserSessionLifecycle.js +120 -0
  101. package/lib/esm/session/lifecycle/page-lifecycle/PageLifecycle.js +263 -0
  102. package/lib/esm/session/lifecycle/page-lifecycle/PageLifecycleInstance.js +2 -0
  103. package/lib/esm/session/lifecycle/page-lifecycle/supportsConstructableEventTarget.js +30 -0
  104. package/lib/esm/session/navigation/InMemoryNavigation.js +97 -0
  105. package/lib/esm/session/navigation/ServerSideNavigation.js +54 -0
  106. package/lib/esm/session/navigation/WebBrowserNavigation.js +213 -0
  107. package/lib/esm/session/navigation/error/NavigationOutOfBoundsError.js +6 -0
  108. package/lib/esm/session/navigation/error/ServerSideNavigationError.js +14 -0
  109. package/lib/esm/session/navigation/operation/operations.js +6 -0
  110. package/lib/esm/session/subscription/Subscription.js +75 -0
  111. package/lib/index.d.ts +178 -157
  112. package/lib/redux/index.d.ts +90 -0
  113. package/lib/scroll-position/index.d.ts +107 -0
  114. package/package.json +9 -5
  115. package/redux/package.json +6 -0
  116. package/scroll-position/package.json +6 -0
  117. package/src/NavigationStack.js +84 -0
  118. package/src/data-storage/DataStorage.js +69 -0
  119. package/src/data-storage/LocationDataStorage.js +23 -0
  120. package/src/data-storage/index.js +2 -0
  121. package/src/environment/InMemoryEnvironment.js +9 -0
  122. package/src/environment/WebBrowserEnvironment.js +9 -0
  123. package/src/environment/data-storage/InMemoryDataStorage.js +23 -0
  124. package/src/environment/data-storage/WebBrowserDataStorage.js +17 -0
  125. package/src/environment/scroll-position/InMemoryScrollPosition.js +45 -0
  126. package/src/environment/scroll-position/WebBrowserScrollPosition.js +72 -0
  127. package/src/getLocationFromInternalLocation.js +7 -0
  128. package/src/index.js +10 -8
  129. package/src/navigationBlockers.js +28 -27
  130. package/src/{normalizeInputLocation.js → parseInputLocation.js} +23 -8
  131. package/src/{ActionTypes.js → redux/ActionTypes.js} +1 -1
  132. package/src/redux/ActionTypesInternal.js +3 -0
  133. package/src/{Actions.js → redux/Actions.js} +4 -3
  134. package/src/redux/createMiddlewares.js +65 -0
  135. package/src/redux/index.js +4 -0
  136. package/src/redux/internalLocationReducer.js +9 -0
  137. package/src/redux/middleware/createAddInputLocationBasePathMiddleware.js +27 -0
  138. package/src/redux/middleware/createNonProgrammaticNavigationBlockerMiddleware.js +119 -0
  139. package/src/redux/middleware/createProgrammaticNavigationBlockerMiddleware.js +94 -0
  140. package/src/redux/middleware/createRemoveOutputLocationBasePathMiddleware.js +26 -0
  141. package/src/redux/middleware/createUpdateInternalLocationMiddleware.js +72 -0
  142. package/src/{middleware/navigationActionMiddleware.js → redux/middleware/navigationOperationMiddleware.js} +10 -3
  143. package/src/{middleware/normalizeInputLocationMiddleware.js → redux/middleware/parseInputLocationMiddleware.js} +5 -3
  144. package/src/redux/middleware/updateLocationMiddleware.js +28 -0
  145. package/src/scroll-position/PageScrollPositionSetter.js +110 -0
  146. package/src/scroll-position/ScrollPositionAutoSaver.js +151 -0
  147. package/src/scroll-position/ScrollPositionRestoration.js +506 -0
  148. package/src/scroll-position/ScrollPositionSaver.js +100 -0
  149. package/src/scroll-position/ScrollPositionSetter.js +16 -0
  150. package/src/scroll-position/constants.js +1 -0
  151. package/src/scroll-position/index.js +1 -0
  152. package/src/scroll-position/scheduleNextTick.js +6 -0
  153. package/src/session/InMemorySession.js +13 -0
  154. package/src/session/ServerSideRenderSession.js +9 -0
  155. package/src/session/Session.js +216 -0
  156. package/src/session/WebBrowserSession.js +13 -0
  157. package/src/session/key/createSessionKey.js +18 -0
  158. package/src/session/lifecycle/InMemorySessionLifecycle.js +13 -0
  159. package/src/session/lifecycle/WebBrowserSessionLifecycle.js +126 -0
  160. package/src/session/lifecycle/page-lifecycle/PageLifecycle.js +291 -0
  161. package/src/session/lifecycle/page-lifecycle/PageLifecycleInstance.js +3 -0
  162. package/src/session/lifecycle/page-lifecycle/supportsConstructableEventTarget.js +32 -0
  163. package/src/session/navigation/InMemoryNavigation.js +78 -0
  164. package/src/session/navigation/ServerSideNavigation.js +43 -0
  165. package/src/session/navigation/WebBrowserNavigation.js +224 -0
  166. package/src/session/navigation/error/NavigationOutOfBoundsError.js +7 -0
  167. package/src/session/navigation/error/ServerSideNavigationError.js +18 -0
  168. package/src/session/navigation/operation/operations.js +6 -0
  169. package/src/session/subscription/Subscription.js +76 -0
  170. package/test/NavigationStack.test.js +296 -0
  171. package/test/{LocationDataStorage.test.js → data-storage/LocationDataStorage.test.js} +3 -3
  172. package/test/data-storage/index.test.js +8 -0
  173. package/test/index.js +12 -0
  174. package/test/index.test.js +8 -7
  175. package/test/{helpers.js → middlewareTestUtil.js} +9 -12
  176. package/test/{normalizeInputLocation.test.js → parseInputLocationMiddleware.test.js} +9 -9
  177. package/test/{Action.test.js → redux/Action.test.js} +7 -6
  178. package/test/{ActionTypes.test.js → redux/ActionTypes.test.js} +2 -2
  179. package/test/redux/createMiddlewares.test.js +96 -0
  180. package/test/redux/index.test.js +10 -0
  181. package/test/{locationReducer.test.js → redux/locationReducer.test.js} +4 -7
  182. package/test/redux/middleware/createAddInputLocationBasePathMiddleware.test.js +40 -0
  183. package/test/redux/middleware/createNonProgrammaticNavigationBlockerMiddleware.test.js +264 -0
  184. package/test/redux/middleware/createProgrammaticNavigationBlockerMiddleware.test.js +312 -0
  185. package/test/redux/middleware/createRemoveOutputLocationBasePathMiddleware.test.js +51 -0
  186. package/test/{middleware/navigationActionMiddleware.test.js → redux/middleware/navigationOperationMiddleware.test.js} +16 -12
  187. package/test/{middleware/normalizeInputLocationMiddleware.test.js → redux/middleware/parseInputLocationMiddleware.test.js} +4 -4
  188. package/test/scroll-position/ScrollPositionRestoration.test.js +418 -0
  189. package/test/scroll-position/addScrollableContainer.js +36 -0
  190. package/test/scroll-position/addScrollableContainerWithHyperlink.js +50 -0
  191. package/test/scroll-position/createApp.js +112 -0
  192. package/test/scroll-position/delay.js +9 -0
  193. package/test/scroll-position/mockPageLifecycle.js +17 -0
  194. package/test/scroll-position/runApp.js +24 -0
  195. package/test/scroll-position/withScrollableContainerAtIndexPage.js +62 -0
  196. package/test/session/InMemorySession.test.js +348 -0
  197. package/test/session/ServerSession.test.js +17 -9
  198. package/test/session/WebBrowserSession.test.js +265 -0
  199. package/test/testUtil.js +3 -0
  200. package/types/data-storage/index.d.ts +35 -0
  201. package/types/index.d.ts +178 -157
  202. package/types/redux/index.d.ts +90 -0
  203. package/types/scroll-position/index.d.ts +107 -0
  204. package/types/tsconfig.json +1 -1
  205. package/lib/cjs/LocationDataStorage.js +0 -60
  206. package/lib/cjs/addBeforeLocationChangeListener.js +0 -7
  207. package/lib/cjs/beforeLocationChangeListeners.js +0 -51
  208. package/lib/cjs/createMiddlewares.js +0 -47
  209. package/lib/cjs/middleware/createBasePathMiddleware.js +0 -24
  210. package/lib/cjs/middleware/createBeforeLocationChangeListenerMiddleware.js +0 -39
  211. package/lib/cjs/middleware/createLocationMiddleware.js +0 -56
  212. package/lib/cjs/middleware/createNavigationBlockerMiddleware.js +0 -161
  213. package/lib/cjs/middleware/createTransformLocationMiddleware.js +0 -38
  214. package/lib/cjs/onlyAllowedOnClientSide.js +0 -10
  215. package/lib/cjs/session/BrowserSession.js +0 -235
  216. package/lib/cjs/session/MemorySession.js +0 -223
  217. package/lib/cjs/session/ServerSession.js +0 -65
  218. package/lib/esm/LocationDataStorage.js +0 -53
  219. package/lib/esm/addBeforeLocationChangeListener.js +0 -2
  220. package/lib/esm/beforeLocationChangeListeners.js +0 -44
  221. package/lib/esm/createMiddlewares.js +0 -41
  222. package/lib/esm/middleware/createBasePathMiddleware.js +0 -19
  223. package/lib/esm/middleware/createBeforeLocationChangeListenerMiddleware.js +0 -34
  224. package/lib/esm/middleware/createLocationMiddleware.js +0 -50
  225. package/lib/esm/middleware/createNavigationBlockerMiddleware.js +0 -156
  226. package/lib/esm/middleware/createTransformLocationMiddleware.js +0 -33
  227. package/lib/esm/onlyAllowedOnClientSide.js +0 -5
  228. package/lib/esm/session/BrowserSession.js +0 -229
  229. package/lib/esm/session/MemorySession.js +0 -217
  230. package/lib/esm/session/ServerSession.js +0 -58
  231. package/src/LocationDataStorage.js +0 -59
  232. package/src/addBeforeLocationChangeListener.js +0 -2
  233. package/src/beforeLocationChangeListeners.js +0 -54
  234. package/src/createMiddlewares.js +0 -45
  235. package/src/middleware/createBasePathMiddleware.js +0 -20
  236. package/src/middleware/createBeforeLocationChangeListenerMiddleware.js +0 -40
  237. package/src/middleware/createLocationMiddleware.js +0 -55
  238. package/src/middleware/createNavigationBlockerMiddleware.js +0 -168
  239. package/src/middleware/createTransformLocationMiddleware.js +0 -29
  240. package/src/onlyAllowedOnClientSide.js +0 -5
  241. package/src/session/BrowserSession.js +0 -235
  242. package/src/session/MemorySession.js +0 -219
  243. package/src/session/ServerSession.js +0 -67
  244. package/test/createMiddlewares.test.js +0 -62
  245. package/test/middleware/createBasePathMiddleware.test.js +0 -67
  246. package/test/middleware/createBeforeLocationChangeListenerMiddleware.test.js +0 -141
  247. package/test/middleware/createNavigationBlockerMiddleware.test.js +0 -471
  248. package/test/middleware/createTransformLocationMiddleware.test.js +0 -44
  249. package/test/session/BrowserSession.test.js +0 -182
  250. package/test/session/MemorySession.test.js +0 -244
  251. /package/lib/cjs/{locationReducer.js → redux/locationReducer.js} +0 -0
  252. /package/lib/esm/{locationReducer.js → redux/locationReducer.js} +0 -0
  253. /package/src/{locationReducer.js → redux/locationReducer.js} +0 -0
@@ -0,0 +1,97 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+ exports.default = void 0;
5
+ var _scheduleNextTick = _interopRequireDefault(require("./scheduleNextTick"));
6
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
7
+ /* eslint-disable no-underscore-dangle */
8
+
9
+ // The original author of `scroll-behavior` package wrote:
10
+ //
11
+ // "Updating the window scroll position is really flaky.
12
+ // Just trying to scroll it isn't enough.
13
+ // Instead, try to scroll a few times until it works."
14
+ //
15
+ // What it does here is it scrolls two times:
16
+ // * First time at the moment of calling the `.set()` method.
17
+ // * Second time after a momentary delay.
18
+ //
19
+ class PageScrollPositionSetter {
20
+ // Sets page scroll position either at an "anchor" or at given coordinates.
21
+ _setPageScrollPositionTo(scrollPositionOrAnchor, environmentScrollPosition) {
22
+ if (typeof scrollPositionOrAnchor === 'string') {
23
+ // Scrolls page to an "ahcnor".
24
+ environmentScrollPosition.setPageScrollPositionAtAnchor(scrollPositionOrAnchor);
25
+ } else {
26
+ // Scrolls page to given coordinates.
27
+ environmentScrollPosition.setPageScrollPosition(scrollPositionOrAnchor);
28
+ }
29
+ }
30
+ _setPageScrollPosition(environmentScrollPosition) {
31
+ const isDelayedCall = Boolean(this._cancelDelayedSetPageScrollPosition);
32
+
33
+ // If this function was triggered in a delayed fashion,
34
+ // clear the reference to the "cancel" function because it's no longer of use.
35
+ if (isDelayedCall) {
36
+ this._cancelDelayedSetPageScrollPosition = null;
37
+ }
38
+
39
+ // It's not really possible for `this._pageScrollPositionOrAnchorToSet` to be `null` or `undefined` at this point.
40
+ // Still, this `if` condition acts as a "foolproof" redundant check.
41
+ /* istanbul ignore if: paranoid guard */
42
+ if (!this._pageScrollPositionOrAnchorToSet) {
43
+ return Promise.resolve();
44
+ }
45
+
46
+ // The original author of `scroll-behavior` package wrote:
47
+ //
48
+ // "Updating the window scroll position is really flaky.
49
+ // Just trying to scroll it isn't enough.
50
+ // Instead, try to scroll a few times until it works."
51
+ //
52
+ this._setPageScrollPositionTo(this._pageScrollPositionOrAnchorToSet, environmentScrollPosition);
53
+
54
+ // If it was a delayed call, stop.
55
+ if (isDelayedCall) {
56
+ this._resetScrollPositionOrAnchorToSet();
57
+ return Promise.resolve();
58
+ }
59
+
60
+ // Repeat the attempt to set scroll position after a momentary delay.
61
+ return new Promise(resolve => {
62
+ this._cancelDelayedSetPageScrollPosition = (0, _scheduleNextTick.default)(() => resolve(this._setPageScrollPosition(environmentScrollPosition)));
63
+ });
64
+ }
65
+
66
+ // Sets scroll position at an anchor or at given coordinates.
67
+ set(scrollableContainer, pageScrollPositionOrAnchor, environmentScrollPosition) {
68
+ // Prevents empty string anchor.
69
+ if (!pageScrollPositionOrAnchor) {
70
+ throw new Error('Argument is required');
71
+ }
72
+
73
+ // Validate that no `scrollableContainer` is passed.
74
+ if (scrollableContainer) {
75
+ throw new Error('`scrollableContainer` argument should not be provided because `PageScrollPositionSetter` was only designed to set scroll position of a page');
76
+ }
77
+ this.cancel();
78
+ this._pageScrollPositionOrAnchorToSet = pageScrollPositionOrAnchor;
79
+ return this._setPageScrollPosition(environmentScrollPosition);
80
+ }
81
+
82
+ // This function should be "idempotent", i.e. be able to be called multiple times.
83
+ cancel() {
84
+ if (this._pageScrollPositionOrAnchorToSet) {
85
+ this._resetScrollPositionOrAnchorToSet();
86
+ if (this._cancelDelayedSetPageScrollPosition) {
87
+ this._cancelDelayedSetPageScrollPosition();
88
+ this._cancelDelayedSetPageScrollPosition = undefined;
89
+ }
90
+ }
91
+ }
92
+ _resetScrollPositionOrAnchorToSet() {
93
+ this._pageScrollPositionOrAnchorToSet = undefined;
94
+ }
95
+ }
96
+ exports.default = PageScrollPositionSetter;
97
+ module.exports = exports.default;
@@ -0,0 +1,130 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+ exports.default = void 0;
5
+ var _constants = require("./constants");
6
+ var _scheduleNextTick = _interopRequireDefault(require("./scheduleNextTick"));
7
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
8
+ /* eslint-disable no-underscore-dangle */
9
+
10
+ class ScrollPositionAutoSaver {
11
+ constructor({
12
+ scrollPosition,
13
+ scrollPositionSaver,
14
+ getScrollableContainers,
15
+ shouldSaveScrollPosition
16
+ }) {
17
+ this._scrollPosition = scrollPosition;
18
+ this._scrollPositionSaver = scrollPositionSaver;
19
+ this._shouldSaveScrollPosition = shouldSaveScrollPosition;
20
+ this._getScrollableContainers = getScrollableContainers;
21
+ }
22
+
23
+ // Starts auto-saving of scroll positions.
24
+ start() {
25
+ // Get scrollable containers.
26
+ const scrollableContainers = this._getScrollableContainers();
27
+
28
+ // Set up scroll listeners on scrollable containers.
29
+ for (const scrollableContainerKey of Object.keys(scrollableContainers)) {
30
+ if (scrollableContainerKey === _constants.PAGE_SCROLLABLE_CONTAINER_KEY) {
31
+ this.addPageScrollListener();
32
+ } else {
33
+ this.addScrollableContainerScrollListener(scrollableContainerKey);
34
+ }
35
+ }
36
+ }
37
+
38
+ // Stops auto-saving of scroll positions.
39
+ stop() {
40
+ // Get scrollable containers.
41
+ const scrollableContainers = this._getScrollableContainers();
42
+
43
+ // Remove scroll listeners on scrollable containers.
44
+ for (const scrollableContainerKey of Object.keys(scrollableContainers)) {
45
+ if (scrollableContainerKey === _constants.PAGE_SCROLLABLE_CONTAINER_KEY) {
46
+ // If there's any scheduled saving of page scroll position, cancel it.
47
+ this.cancelSavePageScrollPosition();
48
+ // Remove scroll listener on the page.
49
+ this.removePageScrollListener();
50
+ } else {
51
+ this.cancelSaveScrollableContainerScrollPosition(scrollableContainerKey);
52
+ this.removeScrollableContainerScrollListener(scrollableContainerKey);
53
+ }
54
+ }
55
+ }
56
+ cancelScheduledAutoSave() {
57
+ for (const scrollableContainerKey of Object.keys(this._getScrollableContainers())) {
58
+ if (scrollableContainerKey === _constants.PAGE_SCROLLABLE_CONTAINER_KEY) {
59
+ this.cancelSavePageScrollPosition();
60
+ } else {
61
+ this.cancelSaveScrollableContainerScrollPosition(scrollableContainerKey);
62
+ }
63
+ }
64
+ }
65
+ cancelSavePageScrollPosition() {
66
+ if (this._cancelSavePageScrollPosition) {
67
+ this._cancelSavePageScrollPosition();
68
+ this._cancelSavePageScrollPosition = null;
69
+ }
70
+ }
71
+ cancelSaveScrollableContainerScrollPosition(scrollableContainerKey) {
72
+ const scrollableContainerEntry = this._getScrollableContainers()[scrollableContainerKey];
73
+ if (scrollableContainerEntry.cancelSaveScrollPosition) {
74
+ scrollableContainerEntry.cancelSaveScrollPosition();
75
+ scrollableContainerEntry.cancelSaveScrollPosition = null;
76
+ }
77
+ }
78
+ removePageScrollListener() {
79
+ // Remove scroll listener on the page.
80
+ if (this._removePageScrollListener) {
81
+ this._removePageScrollListener();
82
+ this._removePageScrollListener = null;
83
+ }
84
+ }
85
+ removeScrollableContainerScrollListener(scrollableContainerKey) {
86
+ const scrollableContainerEntry = this._getScrollableContainers()[scrollableContainerKey];
87
+ if (scrollableContainerEntry.removeScrollListener) {
88
+ scrollableContainerEntry.removeScrollListener();
89
+ scrollableContainerEntry.removeScrollListener = null;
90
+ }
91
+ }
92
+ addScrollableContainerScrollListener(scrollableContainerKey) {
93
+ const scrollableContainerEntry = this._getScrollableContainers()[scrollableContainerKey];
94
+ scrollableContainerEntry.removeScrollListener = this._scrollPosition.addScrollableContainerScrollListener(scrollableContainerEntry.scrollableContainer, () => {
95
+ // This flag is not used in real life and is only used in tests (for some reason).
96
+ if (!this._shouldSaveScrollPosition()) {
97
+ return;
98
+ }
99
+ // Use `scheduleNextTick()` function to "throttle" incoming scroll events.
100
+ // There would be no use in reacting to every incoming scroll event
101
+ // because there might be too many in a given short period of time
102
+ // which could affect the performance of the application.
103
+ if (!scrollableContainerEntry.cancelSaveScrollPosition) {
104
+ scrollableContainerEntry.cancelSaveScrollPosition = (0, _scheduleNextTick.default)(() => {
105
+ this._scrollPositionSaver.saveScrollableContainerScrollPosition(scrollableContainerKey, scrollableContainerEntry.scrollableContainer);
106
+ });
107
+ }
108
+ });
109
+ }
110
+ addPageScrollListener() {
111
+ // Set up scroll listener on the page.
112
+ this._removePageScrollListener = this._scrollPosition.addPageScrollListener(() => {
113
+ // This flag is not used in real life and is only used in tests (for some reason).
114
+ if (!this._shouldSaveScrollPosition()) {
115
+ return;
116
+ }
117
+ // Use `scheduleNextTick()` function to "throttle" incoming scroll events.
118
+ // There would be no use in reacting to every incoming scroll event
119
+ // because there might be too many in a given short period of time
120
+ // which could affect the performance of the application.
121
+ if (!this._cancelSavePageScrollPosition) {
122
+ this._cancelSavePageScrollPosition = (0, _scheduleNextTick.default)(() => {
123
+ this._scrollPositionSaver.savePageScrollPosition();
124
+ });
125
+ }
126
+ });
127
+ }
128
+ }
129
+ exports.default = ScrollPositionAutoSaver;
130
+ module.exports = exports.default;
@@ -0,0 +1,383 @@
1
+ "use strict";
2
+
3
+ exports.__esModule = true;
4
+ exports.default = void 0;
5
+ var _PageScrollPositionSetter = _interopRequireDefault(require("./PageScrollPositionSetter"));
6
+ var _ScrollPositionSaver = _interopRequireDefault(require("./ScrollPositionSaver"));
7
+ var _ScrollPositionSetter = _interopRequireDefault(require("./ScrollPositionSetter"));
8
+ var _constants = require("./constants");
9
+ var _LocationDataStorage = _interopRequireDefault(require("../data-storage/LocationDataStorage"));
10
+ function _interopRequireDefault(e) { return e && e.__esModule ? e : { default: e }; }
11
+ /* eslint-disable no-underscore-dangle */
12
+
13
+ function areEqualScrollPositions(scrollPosition1, scrollPosition2) {
14
+ let i = 0;
15
+ while (i < scrollPosition1.length) {
16
+ if (scrollPosition1[i] !== scrollPosition2[i]) {
17
+ return false;
18
+ }
19
+ i++;
20
+ }
21
+ return true;
22
+ }
23
+ class ScrollPositionRestoration {
24
+ constructor(session, _options) {
25
+ // Once configured, scroll restoration mode persists across page reloads.
26
+ // I.e. even if a user refreshes the page in a web browser, the custom
27
+ // `window.history.scrollRestoration` value will still remain.
28
+ //
29
+ // And since it's set to a custom value of "manual", the web browser
30
+ // won't attempt to restore the scroll position on page load
31
+ // which it would otherwise normally do.
32
+ //
33
+ // So what happens if the website is fully server-side rendered?
34
+ // It will wait for the javascript code to be downloaded an executed first
35
+ // and only then that javascript code will programmatically restore the
36
+ // previously-saved scroll position.
37
+ //
38
+ // That would work but it also wouldn't be the most efficient way to do that.
39
+ // Instead, `window.history.scrollRestoration` value could be reset to default beforehand
40
+ // so that when the page finishes refreshing, the web browser could automatically
41
+ // restore the scroll position without waiting for the javascript code to download and run.
42
+ //
43
+ // To reset `window.history.scrollRestoration` value to default beforehand,
44
+ // the code should be notified when the browser tab is about to be terminated or suspended.
45
+ // Terminating could happen for various reasons such as not enough memory, code crash, etc.
46
+ // Suspending is treated equally to terminating because once suspended, it could potentially be
47
+ // terminated afterwards without the code being able to do its stuff while it's suspended.
48
+ //
49
+ // One could consider this feature a minor user experience optimization that relies on the web browser
50
+ // to correctly restore the page scroll every time on page refresh, which it normally does.
51
+ //
52
+ this._sessionExecutionStatusListener = ({
53
+ running
54
+ }) => {
55
+ if (running) {
56
+ this._disableAutomaticScrollRestoration();
57
+ } else {
58
+ this._enableAutomaticScrollRestoration();
59
+
60
+ // There might be previous scroll position already saved in the data storage.
61
+ // Overwrite that previously-saved scroll position with the most up-to-date one
62
+ // just so that there's no stale scroll position left over in the data storage.
63
+ // Alternatively, it could just clear any saved scroll position for this page,
64
+ // since the web browser's automatic scroll restoration is now enabled.
65
+ this._scrollPositionSaver.saveScrollPosition();
66
+ }
67
+ };
68
+ // Overrides the default `window.history.scrollRestoration` value.
69
+ // This prevents the web browser from interfering by disabling its
70
+ // automatic scroll position restoration on "Back"/"Forward" navigation.
71
+ // Instead, the application will have to do it manually.
72
+ // The reason is that when the web browser performs "Back" or "Forward" navigation,
73
+ // it updates the URL in the address bar immediately, and it also attempts to
74
+ // automatically restore scroll position immediately, but the thing is that
75
+ // the application might have delayed rendering of the page due to various reasons
76
+ // such as performance considerations or the architecture of the rendering framework.
77
+ // For example, React framework by design renders pages in "asynchronous" fashion.
78
+ // Hence, by the time the web browser attempts to restore the scroll position,
79
+ // the page might not yet be rendered which would result in incorrect scroll position restoration.
80
+ // That's why the application has to take over this functionality from the web browser.
81
+ this._disableAutomaticScrollRestoration = () => {
82
+ try {
83
+ this._scrollPosition.disableAutomaticScrollRestoration();
84
+ } catch (error) {
85
+ // eslint-disable-next-line no-console
86
+ console.error('[navigation-stack] could not disable default scroll restoration mode');
87
+ }
88
+ };
89
+ this._enableAutomaticScrollRestoration = () => {
90
+ try {
91
+ this._scrollPosition.enableAutomaticScrollRestoration();
92
+ } catch (error) {
93
+ // eslint-disable-next-line no-console
94
+ console.error('[navigation-stack] could not enable default scroll restoration mode');
95
+ }
96
+ };
97
+ this._saveScrollPositionForLocation = (location, scrollableContainerKey, scrollPosition) => {
98
+ this._locationDataStorage.set(location, scrollableContainerKey || _constants.PAGE_SCROLLABLE_CONTAINER_KEY, scrollPosition);
99
+ };
100
+ this._scrollPosition = session.environment.scrollPosition;
101
+ this._sessionLifecycle = session.lifecycle;
102
+ this._locationDataStorage = new _LocationDataStorage.default(session, {
103
+ namespace: 'navigation-stack/scroll-position'
104
+ });
105
+ this._scrollPositionSaver = new _ScrollPositionSaver.default({
106
+ scrollPosition: this._scrollPosition,
107
+ saveScrollPositionForLocation: this._saveScrollPositionForLocation,
108
+ getScrollableContainers: () => this._scrollableContainers,
109
+ getLocation: () => this._location,
110
+ shouldSaveScrollPosition: () => !this._doNotSaveScrollPosition
111
+ });
112
+
113
+ // Originally, `scrollableContainerKey` was auto-generated,
114
+ // but then it didn't work with the concept of dynamically adding or removing
115
+ // scrollable containers after `ScrollPositionRestoration` has already started.
116
+ //
117
+ // this._scrollableContainerKeyCounter = 0;
118
+
119
+ this._scrollableContainers = {};
120
+
121
+ // Add page scrollable container.
122
+ this._scrollableContainers[_constants.PAGE_SCROLLABLE_CONTAINER_KEY] = {
123
+ scrollableContainer: undefined,
124
+ // Using this option, a developer could theoretically provide their own implementation
125
+ // of setting a scroll position. For example, it could use "smooth" (animated) scrolling, etc.
126
+ // This could be part of the public API if anyone provided a sensible real-world use case for it.
127
+ scrollPositionSetter: _options && _options._pageScrollPositionSetter ||
128
+ // The default page scroll position setter.
129
+ new _PageScrollPositionSetter.default(),
130
+ // This function is only used in tests.
131
+ // There seems to be no use of it in real life, hence it's not public API.
132
+ // It's only used in tests.
133
+ _getScrollPositionForLocation: _options && _options._getPageScrollPositionForLocation,
134
+ // This function is only used in tests.
135
+ // There seems to be no use of it in real life, hence it's not public API.
136
+ // It's only used in tests.
137
+ _shouldUpdateScrollPositionForLocation: _options && _options._shouldUpdatePageScrollPositionForLocation
138
+ };
139
+ }
140
+ addScrollableContainer(scrollableContainerKey, scrollableContainer, _options) {
141
+ // Originally, `scrollableContainerKey` was auto-generated,
142
+ // but then it didn't work with the concept of dynamically adding or removing
143
+ // scrollable containers after `ScrollPositionRestoration` has already started.
144
+ //
145
+ // this._scrollableContainerKeyCounter++;
146
+ // const scrollableContainerKey = String(this._scrollableContainerKeyCounter);
147
+
148
+ if (scrollableContainerKey === _constants.PAGE_SCROLLABLE_CONTAINER_KEY) {
149
+ throw new Error(`Scrollable container key "${scrollableContainerKey}" is not allowed`);
150
+ }
151
+
152
+ // Add scrollable container entry.
153
+ this._scrollableContainers[scrollableContainerKey] = {
154
+ // Scrollable container element.
155
+ scrollableContainer,
156
+ // Using this option, a developer could theoretically provide their own implementation
157
+ // of setting a scroll position. For example, it could use "smooth" (animated) scrolling, etc.
158
+ // This could be part of the public API if anyone provided a sensible real-world use case for it.
159
+ scrollPositionSetter: _options && _options._scrollPositionSetter ||
160
+ // The default basic "immediate" scroll position setter.
161
+ new _ScrollPositionSetter.default(),
162
+ // This function is only used in tests.
163
+ // There seems to be no use of it in real life, hence it's not public API.
164
+ // It's only used in tests.
165
+ _shouldUpdateScrollPositionForLocation: _options && _options._shouldUpdateScrollPositionForLocation,
166
+ // This function is only used in tests.
167
+ // There seems to be no use of it in real life, hence it's not public API.
168
+ // It's only used in tests.
169
+ _getScrollPositionForLocation: _options && _options._getScrollPositionForLocation
170
+ };
171
+
172
+ // Scrollable containers could be added at any time, including page mount.
173
+ // For example, a user navigates "Back" to a previous page where there's
174
+ // a "unique" scrollable container that's only present on that page.
175
+ // In that case, the previously-saved scroll position inside the scrollable container
176
+ // should be restored, if it pre-exists. Otherwise, if it doesn't pre-exist,
177
+ // the initial scroll position should be saved for the scrollable container.
178
+ if (this._location) {
179
+ const previouslySavedScrollPosition = this._getSavedScrollPositionForLocation(this._location, scrollableContainerKey);
180
+ if (previouslySavedScrollPosition) {
181
+ this._scrollPosition.setScrollableContainerScrollPosition(scrollableContainer, previouslySavedScrollPosition);
182
+ } else {
183
+ this._scrollPositionSaver.saveScrollableContainerScrollPosition(scrollableContainerKey, scrollableContainer);
184
+ }
185
+ }
186
+ if (this._started) {
187
+ this._scrollPositionSaver._scrollPositionAutoSaver.addScrollableContainerScrollListener(scrollableContainerKey);
188
+ }
189
+
190
+ // Removes the scrollable container.
191
+ return () => {
192
+ this._scrollPositionSaver._scrollPositionAutoSaver.cancelSaveScrollableContainerScrollPosition(scrollableContainerKey);
193
+ this._scrollPositionSaver._scrollPositionAutoSaver.removeScrollableContainerScrollListener(scrollableContainerKey);
194
+ delete this._scrollableContainers[scrollableContainerKey];
195
+ };
196
+ }
197
+ start() {
198
+ // "Foolproof" check.
199
+ if (this._started) {
200
+ throw new Error('Already started');
201
+ }
202
+ this._started = true;
203
+ this._disableAutomaticScrollRestoration();
204
+ this._scrollPositionSaver.start();
205
+ this._removePageStatusListener = this._sessionLifecycle.addExecutionStatusListener(this._sessionExecutionStatusListener);
206
+ }
207
+
208
+ // This method is "idempotent", i.e. it can be called multiple times.
209
+ stop() {
210
+ // "Foolproof" check.
211
+ if (!this._started) {
212
+ return;
213
+ // throw new Error('Not started');
214
+ }
215
+ this._started = false;
216
+ this._enableAutomaticScrollRestoration();
217
+
218
+ // If there's any scroll position still scheduled to be set, cancel it.
219
+ this._cancelAnyPendingSettingOfScrollPosition();
220
+ this._scrollPositionSaver.stop();
221
+ this._removePageStatusListener();
222
+ }
223
+ _cancelAnyPendingSettingOfScrollPosition() {
224
+ for (const scrollableContainerEntry of Object.values(this._scrollableContainers)) {
225
+ scrollableContainerEntry.scrollPositionSetter.cancel();
226
+ }
227
+ }
228
+ // willRenderLocation = (location) => {
229
+ // // "Foolproof" check.
230
+ // if (!this._started) {
231
+ // throw new Error('`ScrollPositionRestoration` not started');
232
+ // }
233
+ //
234
+ // // For the initial location, it doesn't do anything.
235
+ // if (location.operation === Operations.INIT) {
236
+ // return;
237
+ // }
238
+ //
239
+ // // Since the current page will no longer be rendered,
240
+ // // cancel any scheduled setting of scroll position on it.
241
+ // this._cancelAnyPendingSettingOfScrollPosition();
242
+ //
243
+ // // The previous page may have scheduled an auto-save of scroll position.
244
+ // // Since the previous page is no longer rendered, its scroll position can no longer be obtained,
245
+ // // so any scheduled scroll position auto-save produres are irrelevant now.
246
+ // this._scrollPositionSaver.cancelPreviouslyScheduledAutoSave();
247
+ //
248
+ // // Save the current scroll position on the current page while it's still rendered.
249
+ // // This saved scroll position could later be restored in case of returing to this page.
250
+ // this._scrollPositionSaver.saveScrollPosition();
251
+ // };
252
+
253
+ locationRendered(location) {
254
+ // Validate that `location` has a `key`.
255
+ if (!location.key) {
256
+ throw new Error('`location` must have a `key`');
257
+ }
258
+ this._prevLocation = this._location;
259
+ this._location = location;
260
+ this._scrollPosition.init();
261
+ if (!this._started) {
262
+ // `this.start()` requires `this._location` to be set.
263
+ this.start();
264
+
265
+ // The initial page might've been server-side rendered which means that
266
+ // by the time this javascript code is downloaded and executed by the web browser,
267
+ // the user might've already scrolled the page to some position,
268
+ // and all those pre-javascript scroll events won't be registered by `ScrollPositionSaver`.
269
+ // If the user doesn't scroll after javascript is loaded and just navigates to a new page,
270
+ // the initial page won't have any saved scroll position to restore on "Back" navigation.
271
+ // Hence, it should explicitly save the current scroll position at the start of operation.
272
+ if (!this._isDefaultScrollPosition()) {
273
+ // `this._scrollPositionSaver.saveScrollPosition()` requires `this._location` to be set.
274
+ this._scrollPositionSaver.saveScrollPosition();
275
+ }
276
+ }
277
+
278
+ // The previous page may have scheduled an auto-save of scroll position.
279
+ // Since the previous page is no longer rendered, its scroll position can no longer be obtained,
280
+ // so any scheduled scroll position auto-save produres are irrelevant now.
281
+ this._scrollPositionSaver.cancelPreviouslyScheduledAutoSave();
282
+
283
+ // If it was in the middle of setting scroll position for a previous location, cancel it.
284
+ this._cancelAnyPendingSettingOfScrollPosition();
285
+
286
+ // Set the scroll position for the new page:
287
+ // either restore a previously-saved one or set it to a default scroll position.
288
+ this._setScrollPosition();
289
+ }
290
+
291
+ // Tells if the current scroll position is the default one.
292
+ _isDefaultScrollPosition() {
293
+ for (const scrollableContainerKey of Object.keys(this._scrollableContainers)) {
294
+ if (scrollableContainerKey === _constants.PAGE_SCROLLABLE_CONTAINER_KEY) {
295
+ if (!areEqualScrollPositions(this._scrollPosition.getPageScrollPosition(), this._getDefaultScrollPosition())) {
296
+ return false;
297
+ }
298
+ } else {
299
+ const scrollableContainerEntry = this._scrollableContainers[scrollableContainerKey];
300
+ if (!areEqualScrollPositions(this._scrollPosition.getScrollableContainerScrollPosition(scrollableContainerEntry.scrollableContainer), this._getDefaultScrollPosition())) {
301
+ return false;
302
+ }
303
+ }
304
+ }
305
+ return true;
306
+ }
307
+ _setScrollPosition() {
308
+ for (const scrollableContainerKey of Object.keys(this._scrollableContainers)) {
309
+ const scrollableContainerEntry = this._scrollableContainers[scrollableContainerKey];
310
+
311
+ // This function is only used in tests.
312
+ // There seems to be no use of it in real life, hence it's not public API.
313
+ // It's only used in tests.
314
+ if (scrollableContainerEntry._shouldUpdateScrollPositionForLocation) {
315
+ if (!scrollableContainerEntry._shouldUpdateScrollPositionForLocation(this._location, this._prevLocation)) {
316
+ continue;
317
+ }
318
+ }
319
+
320
+ // Scroll position (or anchor) to set.
321
+ let scrollPositionOrAnchorToSet;
322
+
323
+ // This function is only used in tests.
324
+ // There seems to be no use of it in real life, hence it's not public API.
325
+ // It's only used in tests.
326
+ if (scrollableContainerEntry._getScrollPositionForLocation) {
327
+ scrollPositionOrAnchorToSet = scrollableContainerEntry._getScrollPositionForLocation(this._location, this._prevLocation);
328
+ }
329
+
330
+ // Get scroll position (or anchor) to set.
331
+ if (!scrollPositionOrAnchorToSet) {
332
+ scrollPositionOrAnchorToSet = scrollableContainerKey === _constants.PAGE_SCROLLABLE_CONTAINER_KEY ? this._getPageScrollPositionOrAnchorToSet(this._location) : this._getScrollableContainerScrollPositionToSet(this._location, scrollableContainerKey);
333
+ }
334
+
335
+ // Set scroll position of scrollable container.
336
+ scrollableContainerEntry.scrollPositionSetter.set(scrollableContainerEntry.scrollableContainer, scrollPositionOrAnchorToSet, this._scrollPosition);
337
+ }
338
+ }
339
+ _getSavedScrollPositionForLocation(location, scrollableContainerKey = _constants.PAGE_SCROLLABLE_CONTAINER_KEY) {
340
+ return this._locationDataStorage.get(location, scrollableContainerKey);
341
+ }
342
+ // Returns scroll position coordinates or an anchor name.
343
+ _getPageScrollPositionOrAnchorToSet(location) {
344
+ // If it's a return to a previously-visited location,
345
+ // read the saved scroll position from session data store.
346
+ return this._getSavedScrollPositionForLocation(location) || this._getAnchor(location) || this._getDefaultScrollPosition();
347
+ }
348
+
349
+ // Returns scroll position coordinates.
350
+ _getScrollableContainerScrollPositionToSet(location, scrollableContainerKey) {
351
+ // If it's a return to a previously-visited location,
352
+ // read the saved scroll position from session data store.
353
+ return this._getSavedScrollPositionForLocation(location, scrollableContainerKey) || this._getDefaultScrollPosition();
354
+ }
355
+ _getAnchor(location) {
356
+ const {
357
+ hash
358
+ } = location;
359
+ if (hash && hash !== '#') {
360
+ return hash.slice('#'.length);
361
+ }
362
+ return undefined;
363
+ }
364
+ _getDefaultScrollPosition() {
365
+ return [0, 0];
366
+ }
367
+
368
+ // `_enableSavingScrollPosition()` and `_disableSavingScrollPosition()`
369
+ // aren't used in real life and are not part of the public API.
370
+ // They're only used in tests.
371
+ _enableSavingScrollPosition() {
372
+ this._doNotSaveScrollPosition = undefined;
373
+ }
374
+
375
+ // `_enableSavingScrollPosition()` and `_disableSavingScrollPosition()`
376
+ // aren't used in real life and are not part of the public API.
377
+ // They're only used in tests.
378
+ _disableSavingScrollPosition() {
379
+ this._doNotSaveScrollPosition = true;
380
+ }
381
+ }
382
+ exports.default = ScrollPositionRestoration;
383
+ module.exports = exports.default;