navigation-stack 0.4.0 → 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.
Files changed (49) hide show
  1. package/CHANGELOG.md +12 -0
  2. package/README.md +20 -12
  3. package/lib/cjs/NavigationStack.js +17 -2
  4. package/lib/cjs/debug.js +12 -0
  5. package/lib/cjs/getLocationFromInternalLocation.js +2 -2
  6. package/lib/cjs/navigationBlockers.js +3 -0
  7. package/lib/cjs/scroll-position/ScrollPositionAutoSaver.js +13 -2
  8. package/lib/cjs/scroll-position/ScrollPositionRestoration.js +29 -5
  9. package/lib/cjs/scroll-position/ScrollPositionSaver.js +8 -2
  10. package/lib/cjs/session/Session.js +6 -0
  11. package/lib/cjs/session/navigation/operation/operations.js +4 -4
  12. package/lib/esm/NavigationStack.js +17 -2
  13. package/lib/esm/debug.js +7 -0
  14. package/lib/esm/getLocationFromInternalLocation.js +2 -2
  15. package/lib/esm/navigationBlockers.js +3 -0
  16. package/lib/esm/scroll-position/ScrollPositionAutoSaver.js +13 -2
  17. package/lib/esm/scroll-position/ScrollPositionRestoration.js +29 -5
  18. package/lib/esm/scroll-position/ScrollPositionSaver.js +8 -2
  19. package/lib/esm/session/Session.js +6 -0
  20. package/lib/esm/session/navigation/operation/operations.js +4 -4
  21. package/lib/index.d.ts +10 -9
  22. package/lib/scroll-position/index.d.ts +3 -3
  23. package/package.json +1 -1
  24. package/src/NavigationStack.js +18 -2
  25. package/src/debug.js +8 -0
  26. package/src/getLocationFromInternalLocation.js +2 -2
  27. package/src/navigationBlockers.js +3 -0
  28. package/src/scroll-position/ScrollPositionAutoSaver.js +19 -2
  29. package/src/scroll-position/ScrollPositionRestoration.js +92 -47
  30. package/src/scroll-position/ScrollPositionSaver.js +21 -1
  31. package/src/session/Session.js +22 -0
  32. package/src/session/navigation/operation/operations.js +4 -4
  33. package/test/NavigationStack.test.js +14 -14
  34. package/test/middlewareTestUtil.js +1 -1
  35. package/test/redux/locationReducer.test.js +1 -1
  36. package/test/redux/middleware/createNonProgrammaticNavigationBlockerMiddleware.test.js +5 -5
  37. package/test/redux/middleware/createProgrammaticNavigationBlockerMiddleware.test.js +2 -2
  38. package/test/redux/middleware/navigationOperationMiddleware.test.js +2 -2
  39. package/test/scroll-position/ScrollPositionRestoration.test.js +73 -56
  40. package/test/scroll-position/addScrollableContainer.js +5 -2
  41. package/test/scroll-position/{addScrollableContainerWithHyperlink.js → addScrollableContainerWithAnchors.js} +8 -2
  42. package/test/scroll-position/createApp.js +20 -0
  43. package/test/scroll-position/withScrollableContainerAtIndexPageWithDisabledAutomaticScrollPositionRestoration.js +72 -0
  44. package/test/session/InMemorySession.test.js +28 -28
  45. package/test/session/ServerSession.test.js +1 -1
  46. package/test/session/WebBrowserSession.test.js +17 -17
  47. package/types/index.d.ts +10 -9
  48. package/types/scroll-position/index.d.ts +3 -3
  49. package/test/scroll-position/withScrollableContainerAtIndexPage.js +0 -62
@@ -62,7 +62,7 @@ describe('WebBrowserSession', () => {
62
62
  session.start(parseInputLocation(window.location));
63
63
 
64
64
  expect(location).to.deep.include({
65
- operation: 'INIT',
65
+ operation: 'init',
66
66
  pathname: '/initial',
67
67
  search: '?bar=baz',
68
68
  query: {
@@ -78,7 +78,7 @@ describe('WebBrowserSession', () => {
78
78
  session = new WebBrowserSession();
79
79
 
80
80
  expect(() =>
81
- session.navigate('PUSH', {
81
+ session.navigate('push', {
82
82
  pathname: '/new',
83
83
  search: '?search',
84
84
  hash: '#hash',
@@ -103,14 +103,14 @@ describe('WebBrowserSession', () => {
103
103
 
104
104
  expect(listener).to.have.been.calledOnce();
105
105
  expect(listener.firstCall.args[0]).to.deep.include({
106
- operation: 'INIT',
106
+ operation: 'init',
107
107
  pathname: '/initial',
108
108
  index: 0,
109
109
  delta: 0,
110
110
  });
111
111
  listener.resetHistory();
112
112
 
113
- session.navigate('PUSH', {
113
+ session.navigate('push', {
114
114
  pathname: '/new',
115
115
  search: '?search',
116
116
  hash: '#hash',
@@ -124,7 +124,7 @@ describe('WebBrowserSession', () => {
124
124
  hash: '#hash',
125
125
  });
126
126
  expect(newLocation).to.deep.include({
127
- operation: 'PUSH',
127
+ operation: 'push',
128
128
  pathname: '/new',
129
129
  search: '?search',
130
130
  hash: '#hash',
@@ -135,21 +135,21 @@ describe('WebBrowserSession', () => {
135
135
 
136
136
  expect(listener).to.have.been.calledOnce();
137
137
  expect(listener.firstCall.args[0]).to.deep.include({
138
- operation: 'PUSH',
138
+ operation: 'push',
139
139
  pathname: '/new',
140
140
  index: 1,
141
141
  delta: 1,
142
142
  });
143
143
  listener.resetHistory();
144
144
 
145
- session.navigate('PUSH', {
145
+ session.navigate('push', {
146
146
  pathname: '/new-2',
147
147
  search: '',
148
148
  hash: '',
149
149
  });
150
150
 
151
151
  expect(location).to.include({
152
- operation: 'PUSH',
152
+ operation: 'push',
153
153
  pathname: '/new-2',
154
154
  index: 2,
155
155
  delta: 1,
@@ -157,7 +157,7 @@ describe('WebBrowserSession', () => {
157
157
 
158
158
  expect(listener).to.have.been.calledOnce();
159
159
  expect(listener.firstCall.args[0]).to.deep.include({
160
- operation: 'PUSH',
160
+ operation: 'push',
161
161
  pathname: '/new-2',
162
162
  index: 2,
163
163
  delta: 1,
@@ -166,14 +166,14 @@ describe('WebBrowserSession', () => {
166
166
 
167
167
  expect(window.location.pathname).to.equal('/new-2');
168
168
 
169
- session.navigate('REPLACE', {
169
+ session.navigate('replace', {
170
170
  pathname: '/new-3',
171
171
  search: '',
172
172
  hash: '',
173
173
  });
174
174
 
175
175
  expect(location).to.include({
176
- operation: 'REPLACE',
176
+ operation: 'replace',
177
177
  pathname: '/new-3',
178
178
  index: 2,
179
179
  delta: 0,
@@ -184,7 +184,7 @@ describe('WebBrowserSession', () => {
184
184
 
185
185
  expect(listener).to.have.been.calledOnce();
186
186
  expect(listener.firstCall.args[0]).to.deep.include({
187
- operation: 'REPLACE',
187
+ operation: 'replace',
188
188
  pathname: '/new-3',
189
189
  index: 2,
190
190
  delta: 0,
@@ -202,7 +202,7 @@ describe('WebBrowserSession', () => {
202
202
 
203
203
  expect(listener).to.have.been.calledOnce();
204
204
  expect(listener.firstCall.args[0]).to.deep.include({
205
- operation: 'SHIFT',
205
+ operation: 'shift',
206
206
  pathname: '/new',
207
207
  search: '?search',
208
208
  hash: '#hash',
@@ -219,7 +219,7 @@ describe('WebBrowserSession', () => {
219
219
 
220
220
  expect(listener).to.have.been.calledOnce();
221
221
  expect(listener.firstCall.args[0]).to.deep.include({
222
- operation: 'SHIFT',
222
+ operation: 'shift',
223
223
  pathname: '/initial',
224
224
  index: 0,
225
225
  delta: -1,
@@ -231,12 +231,12 @@ describe('WebBrowserSession', () => {
231
231
  window.history.replaceState(null, null, '/');
232
232
  session = new WebBrowserSession();
233
233
  session.start(parseInputLocation(window.location));
234
- session.navigate('PUSH', {
234
+ session.navigate('push', {
235
235
  pathname: '/new',
236
236
  search: '',
237
237
  hash: '',
238
238
  });
239
- session.navigate('PUSH', {
239
+ session.navigate('push', {
240
240
  pathname: '/new-2',
241
241
  search: '',
242
242
  hash: '',
@@ -250,7 +250,7 @@ describe('WebBrowserSession', () => {
250
250
 
251
251
  expect(listener).to.have.been.calledOnce();
252
252
  expect(listener.firstCall.args[0]).to.include({
253
- operation: 'SHIFT',
253
+ operation: 'shift',
254
254
  pathname: '/new',
255
255
  });
256
256
  listener.resetHistory();
package/types/index.d.ts CHANGED
@@ -35,22 +35,23 @@ export interface Location extends LocationBase {
35
35
  * a unique key identifying the current history entry
36
36
  */
37
37
  key: string;
38
+
39
+ /**
40
+ * the current index of the history entry, starting at 0 for the initial
41
+ * entry; this increments on `.push()` but not on `.replace()`
42
+ */
43
+ index: number;
38
44
  }
39
45
 
40
- type PushOrReplaceOperation = 'PUSH' | 'REPLACE';
46
+ type PushOrReplaceOperation = 'push' | 'replace';
41
47
 
42
48
  export interface LocationInternal extends Location {
43
49
  /**
44
50
  * `navigation-stack` operation.
45
51
  */
46
- operation: PushOrReplaceOperation | 'SHIFT' | 'INIT';
47
- /**
48
- * the current index of the history entry, starting at 0 for the initial
49
- * entry; this increments on `.push()` but not on `.replace()`
50
- */
51
- index: number;
52
+ operation: PushOrReplaceOperation | 'shift' | 'init';
52
53
  /**
53
- * the difference between the current index and the index of the previous location
54
+ * the difference between the index of the current location and the index of the previous location.
54
55
  */
55
56
  delta: number;
56
57
  }
@@ -155,7 +156,7 @@ export class NavigationStack<ScrollableContainer = any, Anchor = any> {
155
156
 
156
157
  shift(delta: number): void;
157
158
 
158
- locationRendered(): void;
159
+ locationRendered(): Promise<void>;
159
160
 
160
161
  stop(): void;
161
162
  }
@@ -29,7 +29,7 @@ export class ScrollPositionRestoration<
29
29
  _getPageScrollPositionForLocation?: (
30
30
  location: Location,
31
31
  prevLocation: Location | undefined,
32
- ) => boolean;
32
+ ) => [number, number] | undefined;
33
33
 
34
34
  // Using this option, a developer could theoretically provide their own implementation
35
35
  // of setting a scroll position. For example, it could use "smooth" (animated) scrolling, etc.
@@ -61,7 +61,7 @@ export class ScrollPositionRestoration<
61
61
  _getScrollPositionForLocation?: (
62
62
  location: Location,
63
63
  prevLocation: Location | undefined,
64
- ) => boolean;
64
+ ) => [number, number] | undefined;
65
65
 
66
66
  // Using this option, a developer could theoretically provide their own implementation
67
67
  // of setting a scroll position. For example, it could use "smooth" (animated) scrolling, etc.
@@ -70,7 +70,7 @@ export class ScrollPositionRestoration<
70
70
  },
71
71
  ): () => void;
72
72
 
73
- locationRendered: (location: Location) => void;
73
+ locationRendered: (location: Location) => Promise<void>;
74
74
 
75
75
  stop(): void;
76
76
 
@@ -1,62 +0,0 @@
1
- // Adds a 100x100 scrollable container on the website.
2
- //
3
- // * When the current location is "/", it renders a large amount of content
4
- // (20000x20000 to be specific) inside the container, making it scrollable.
5
- //
6
- // * At any other location, it doesn't render anything in the container.
7
- //
8
- export default function withScrollableContainerAtIndexPage(app) {
9
- const container = document.createElement('div');
10
- container.style.height = '100px';
11
- container.style.width = '100px';
12
- container.style.overflow = 'hidden';
13
- document.body.appendChild(container);
14
-
15
- let element;
16
- let unregister;
17
-
18
- // This will only be called once, so no need to guard.
19
- function listen(listener) {
20
- function shouldUpdatePageScrollPositionForLocation(
21
- location,
22
- prevLocation,
23
- ) {
24
- // Disable the automatic scroll restoration after a SHIFT, to check the
25
- // scroll-on-register behavior.
26
- if (prevLocation && location.operation === 'SHIFT') {
27
- return false;
28
- }
29
-
30
- return true;
31
- }
32
-
33
- const unlisten = app.listen((location) => {
34
- listener(location);
35
-
36
- if (location.pathname === '/') {
37
- element = document.createElement('div');
38
- element.style.height = '20000px';
39
- element.style.width = '20000px';
40
- container.appendChild(element);
41
-
42
- unregister = app.registerScrollableContainer('container', container, {
43
- shouldUpdatePageScrollPositionForLocation,
44
- });
45
- } else {
46
- container.removeChild(element);
47
- unregister();
48
- }
49
- });
50
-
51
- return () => {
52
- unlisten();
53
- document.body.removeChild(container);
54
- };
55
- }
56
-
57
- return {
58
- ...app,
59
- container,
60
- listen,
61
- };
62
- }