crelte 0.2.0 → 0.2.1
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/dist/index.d.ts +1 -0
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +7 -0
- package/dist/init/client.d.ts.map +1 -1
- package/dist/init/client.js +6 -0
- package/dist/routing/InnerRouter.d.ts +21 -15
- package/dist/routing/InnerRouter.d.ts.map +1 -1
- package/dist/routing/InnerRouter.js +76 -49
- package/dist/routing/Request.d.ts +6 -0
- package/dist/routing/Request.d.ts.map +1 -1
- package/dist/routing/Request.js +6 -0
- package/dist/routing/Route.d.ts +40 -17
- package/dist/routing/Route.d.ts.map +1 -1
- package/dist/routing/Route.js +69 -41
- package/dist/routing/Router.d.ts +30 -8
- package/dist/routing/Router.d.ts.map +1 -1
- package/dist/routing/Router.js +80 -19
- package/package.json +1 -1
- package/src/index.ts +9 -0
- package/src/init/client.ts +9 -0
- package/src/routing/InnerRouter.ts +81 -57
- package/src/routing/Request.ts +8 -0
- package/src/routing/Route.ts +91 -52
- package/src/routing/Router.ts +96 -23
- package/LICENSE.md +0 -41
package/dist/routing/Router.d.ts
CHANGED
|
@@ -12,6 +12,7 @@ export type RouterOptions = {
|
|
|
12
12
|
*/
|
|
13
13
|
type Internal = {
|
|
14
14
|
onLoaded: (success: boolean, req: Request, ready: () => any) => void;
|
|
15
|
+
onNothingLoaded: (req: Request, ready: () => void) => void;
|
|
15
16
|
onLoad: LoadFn;
|
|
16
17
|
domReady: (req: Request) => void;
|
|
17
18
|
initClient: () => void;
|
|
@@ -42,7 +43,6 @@ export default class Router {
|
|
|
42
43
|
* The loading progress, the value is between 0 and 1
|
|
43
44
|
*/
|
|
44
45
|
private _loadingProgress;
|
|
45
|
-
private _onRouteEv;
|
|
46
46
|
private _onRequest;
|
|
47
47
|
/** @hidden */
|
|
48
48
|
_internal: Internal;
|
|
@@ -72,10 +72,13 @@ export default class Router {
|
|
|
72
72
|
/**
|
|
73
73
|
* Open a new route
|
|
74
74
|
*
|
|
75
|
-
* @param target the target to open can be an url or a
|
|
75
|
+
* @param target the target to open can be an url, a route or a request
|
|
76
76
|
* the url needs to start with http or with a / which will be considered as
|
|
77
77
|
* the site baseUrl
|
|
78
78
|
*
|
|
79
|
+
* ## Note
|
|
80
|
+
* The origin will always be set to 'manual'
|
|
81
|
+
*
|
|
79
82
|
* ## Example
|
|
80
83
|
* ```
|
|
81
84
|
* import { getRouter } from 'crelte';
|
|
@@ -87,13 +90,18 @@ export default class Router {
|
|
|
87
90
|
* // the following page will be opened https://example.com/de/foo/bar
|
|
88
91
|
* ```
|
|
89
92
|
*/
|
|
90
|
-
open(target: string | URL | Route, opts?: RequestOptions): void;
|
|
93
|
+
open(target: string | URL | Route | Request, opts?: RequestOptions): void;
|
|
91
94
|
/**
|
|
92
|
-
* This pushes the
|
|
95
|
+
* This pushes the new route without triggering a new pageload
|
|
93
96
|
*
|
|
94
97
|
* You can use this when using pagination for example change the route object
|
|
95
98
|
* (search argument) and then call pushState
|
|
96
99
|
*
|
|
100
|
+
* ## Note
|
|
101
|
+
* This will always set the origin to 'push'
|
|
102
|
+
* And will clear the scrollY value if you not provide a new one via the `opts`
|
|
103
|
+
* This will disableLoadData by default if you not provide an override via the `opts`
|
|
104
|
+
*
|
|
97
105
|
* ## Example
|
|
98
106
|
* ```
|
|
99
107
|
* import { getRouter } from 'crelte';
|
|
@@ -106,12 +114,21 @@ export default class Router {
|
|
|
106
114
|
* router.pushState(route);
|
|
107
115
|
* ```
|
|
108
116
|
*/
|
|
109
|
-
|
|
117
|
+
push(route: Route | Request, opts?: RequestOptions): void;
|
|
118
|
+
/**
|
|
119
|
+
* @deprecated use push instead
|
|
120
|
+
*/
|
|
121
|
+
pushState(route: Route | Request): void;
|
|
110
122
|
/**
|
|
111
123
|
* This replaces the state of the route without triggering an event
|
|
112
124
|
*
|
|
113
125
|
* You can use this when using some filters for example a search filter
|
|
114
126
|
*
|
|
127
|
+
* ## Note
|
|
128
|
+
* This will always set the origin to 'replace'
|
|
129
|
+
* And will clear the scrollY value if you not provide a new one via the `opts`
|
|
130
|
+
* This will disableLoadData by default if you not provide an override via the `opts`
|
|
131
|
+
*
|
|
115
132
|
* ## Example
|
|
116
133
|
* ```
|
|
117
134
|
* import { getRouter } from 'crelte';
|
|
@@ -124,7 +141,11 @@ export default class Router {
|
|
|
124
141
|
* router.replaceState(route);
|
|
125
142
|
* ```
|
|
126
143
|
*/
|
|
127
|
-
|
|
144
|
+
replace(route: Route | Request, opts?: RequestOptions): void;
|
|
145
|
+
/**
|
|
146
|
+
* @deprecated use replace instead
|
|
147
|
+
*/
|
|
148
|
+
replaceState(route: Route | Request): void;
|
|
128
149
|
/**
|
|
129
150
|
* Checks if there are previous routes which would allow it to go back
|
|
130
151
|
*/
|
|
@@ -140,8 +161,8 @@ export default class Router {
|
|
|
140
161
|
/**
|
|
141
162
|
* Add a listener for the onRoute event
|
|
142
163
|
*
|
|
143
|
-
* This
|
|
144
|
-
*
|
|
164
|
+
* This will trigger every time a new route is set
|
|
165
|
+
* and is equivalent to router.route.subscribe(fn)
|
|
145
166
|
*
|
|
146
167
|
* @returns a function to remove the listener
|
|
147
168
|
*/
|
|
@@ -161,6 +182,7 @@ export default class Router {
|
|
|
161
182
|
private destroyRequest;
|
|
162
183
|
private _onPreload;
|
|
163
184
|
private _onLoaded;
|
|
185
|
+
private _onNothingLoaded;
|
|
164
186
|
private _onProgress;
|
|
165
187
|
}
|
|
166
188
|
export {};
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"Router.d.ts","sourceRoot":"","sources":["../../../../src/routing/Router.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,MAAM,YAAY,CAAC;AAC/B,OAAO,IAAI,EAAE,EAAE,eAAe,EAAE,MAAM,WAAW,CAAC;AAElD,OAAmB,EAAE,MAAM,EAAgB,MAAM,iBAAiB,CAAC;AAEnE,OAAO,EAAE,QAAQ,EAAY,MAAM,mBAAmB,CAAC;AAEvD,OAAO,OAAO,EAAE,EAAE,cAAc,EAAE,MAAM,cAAc,CAAC;AAEvD,MAAM,MAAM,aAAa,GAAG;IAC3B,kBAAkB,CAAC,EAAE,OAAO,CAAC;IAC7B,WAAW,CAAC,EAAE,OAAO,CAAC;CACtB,CAAC;AAWF;;GAEG;AACH,KAAK,QAAQ,GAAG;IACf,QAAQ,EAAE,CACT,OAAO,EAAE,OAAO,EAChB,GAAG,EAAE,OAAO,EAKZ,KAAK,EAAE,MAAM,GAAG,KACZ,IAAI,CAAC;IAEV,MAAM,EAAE,MAAM,CAAC;IAEf,QAAQ,EAAE,CAAC,GAAG,EAAE,OAAO,KAAK,IAAI,CAAC;IAEjC,UAAU,EAAE,MAAM,IAAI,CAAC;IAEvB,UAAU,EAAE,CAAC,GAAG,EAAE,MAAM,EAAE,UAAU,CAAC,EAAE,MAAM,KAAK,OAAO,CAAC,YAAY,CAAC,CAAC;CACxE,CAAC;AAEF,KAAK,YAAY,GAAG;IACnB,OAAO,EAAE,OAAO,CAAC;IAEjB,QAAQ,EAAE,OAAO,CAAC;IAClB,GAAG,EAAE,OAAO,CAAC;IACb,KAAK,EAAE,GAAG,CAAC;CACX,CAAC;AAGF,MAAM,CAAC,OAAO,OAAO,MAAM;IAC1B;;OAEG;IACH,OAAO,CAAC,MAAM,CAAkB;IAEhC;;OAEG;IACH,OAAO,CAAC,KAAK,CAAiB;IAG9B,OAAO,CAAC,QAAQ,CAAiB;IAEjC;;;OAGG;IACH,OAAO,CAAC,QAAQ,CAAoB;IAEpC;;OAEG;IACH,OAAO,CAAC,gBAAgB,CAAmB;IAE3C,OAAO,CAAC,UAAU,
|
|
1
|
+
{"version":3,"file":"Router.d.ts","sourceRoot":"","sources":["../../../../src/routing/Router.ts"],"names":[],"mappings":"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"}
|
package/dist/routing/Router.js
CHANGED
|
@@ -28,7 +28,6 @@ export default class Router {
|
|
|
28
28
|
* The loading progress, the value is between 0 and 1
|
|
29
29
|
*/
|
|
30
30
|
_loadingProgress;
|
|
31
|
-
_onRouteEv;
|
|
32
31
|
_onRequest;
|
|
33
32
|
/** @hidden */
|
|
34
33
|
_internal;
|
|
@@ -48,10 +47,10 @@ export default class Router {
|
|
|
48
47
|
this._request = null;
|
|
49
48
|
this._loading = new Writable(false);
|
|
50
49
|
this._loadingProgress = new Writable(0);
|
|
51
|
-
this._onRouteEv = new Listeners();
|
|
52
50
|
this._onRequest = new Listeners();
|
|
53
51
|
this._internal = {
|
|
54
52
|
onLoaded: () => { },
|
|
53
|
+
onNothingLoaded: () => { },
|
|
55
54
|
onLoad: () => { },
|
|
56
55
|
domReady: req => this.inner.domReady(req),
|
|
57
56
|
initClient: () => this._initClient(),
|
|
@@ -96,10 +95,13 @@ export default class Router {
|
|
|
96
95
|
/**
|
|
97
96
|
* Open a new route
|
|
98
97
|
*
|
|
99
|
-
* @param target the target to open can be an url or a
|
|
98
|
+
* @param target the target to open can be an url, a route or a request
|
|
100
99
|
* the url needs to start with http or with a / which will be considered as
|
|
101
100
|
* the site baseUrl
|
|
102
101
|
*
|
|
102
|
+
* ## Note
|
|
103
|
+
* The origin will always be set to 'manual'
|
|
104
|
+
*
|
|
103
105
|
* ## Example
|
|
104
106
|
* ```
|
|
105
107
|
* import { getRouter } from 'crelte';
|
|
@@ -112,14 +114,23 @@ export default class Router {
|
|
|
112
114
|
* ```
|
|
113
115
|
*/
|
|
114
116
|
open(target, opts = {}) {
|
|
115
|
-
this.inner.
|
|
117
|
+
const req = this.inner.targetToRequest(target, {
|
|
118
|
+
...opts,
|
|
119
|
+
origin: 'manual',
|
|
120
|
+
});
|
|
121
|
+
this.inner.open(req);
|
|
116
122
|
}
|
|
117
123
|
/**
|
|
118
|
-
* This pushes the
|
|
124
|
+
* This pushes the new route without triggering a new pageload
|
|
119
125
|
*
|
|
120
126
|
* You can use this when using pagination for example change the route object
|
|
121
127
|
* (search argument) and then call pushState
|
|
122
128
|
*
|
|
129
|
+
* ## Note
|
|
130
|
+
* This will always set the origin to 'push'
|
|
131
|
+
* And will clear the scrollY value if you not provide a new one via the `opts`
|
|
132
|
+
* This will disableLoadData by default if you not provide an override via the `opts`
|
|
133
|
+
*
|
|
123
134
|
* ## Example
|
|
124
135
|
* ```
|
|
125
136
|
* import { getRouter } from 'crelte';
|
|
@@ -132,17 +143,35 @@ export default class Router {
|
|
|
132
143
|
* router.pushState(route);
|
|
133
144
|
* ```
|
|
134
145
|
*/
|
|
135
|
-
|
|
146
|
+
push(route, opts = {}) {
|
|
147
|
+
// cancel previous request
|
|
136
148
|
this.pageLoader.discard();
|
|
137
|
-
this.inner.
|
|
149
|
+
const req = this.inner.targetToRequest(route, {
|
|
150
|
+
...opts,
|
|
151
|
+
origin: 'push',
|
|
152
|
+
scrollY: opts.scrollY ?? undefined,
|
|
153
|
+
disableLoadData: opts.disableLoadData ?? true,
|
|
154
|
+
});
|
|
155
|
+
this.inner.push(req);
|
|
138
156
|
this.destroyRequest();
|
|
139
157
|
this.setNewRoute(route);
|
|
140
158
|
}
|
|
159
|
+
/**
|
|
160
|
+
* @deprecated use push instead
|
|
161
|
+
*/
|
|
162
|
+
pushState(route) {
|
|
163
|
+
this.push(route);
|
|
164
|
+
}
|
|
141
165
|
/**
|
|
142
166
|
* This replaces the state of the route without triggering an event
|
|
143
167
|
*
|
|
144
168
|
* You can use this when using some filters for example a search filter
|
|
145
169
|
*
|
|
170
|
+
* ## Note
|
|
171
|
+
* This will always set the origin to 'replace'
|
|
172
|
+
* And will clear the scrollY value if you not provide a new one via the `opts`
|
|
173
|
+
* This will disableLoadData by default if you not provide an override via the `opts`
|
|
174
|
+
*
|
|
146
175
|
* ## Example
|
|
147
176
|
* ```
|
|
148
177
|
* import { getRouter } from 'crelte';
|
|
@@ -155,11 +184,23 @@ export default class Router {
|
|
|
155
184
|
* router.replaceState(route);
|
|
156
185
|
* ```
|
|
157
186
|
*/
|
|
158
|
-
|
|
187
|
+
replace(route, opts = {}) {
|
|
188
|
+
// cancel previous request
|
|
159
189
|
this.pageLoader.discard();
|
|
160
|
-
this.inner.
|
|
190
|
+
const req = this.inner.targetToRequest(route, {
|
|
191
|
+
origin: 'replace',
|
|
192
|
+
scrollY: opts.scrollY ?? undefined,
|
|
193
|
+
disableLoadData: opts.disableLoadData ?? true,
|
|
194
|
+
});
|
|
195
|
+
this.inner.replace(req);
|
|
161
196
|
this.destroyRequest();
|
|
162
|
-
this.setNewRoute(
|
|
197
|
+
this.setNewRoute(req);
|
|
198
|
+
}
|
|
199
|
+
/**
|
|
200
|
+
* @deprecated use replace instead
|
|
201
|
+
*/
|
|
202
|
+
replaceState(route) {
|
|
203
|
+
this.replace(route);
|
|
163
204
|
}
|
|
164
205
|
/**
|
|
165
206
|
* Checks if there are previous routes which would allow it to go back
|
|
@@ -182,13 +223,13 @@ export default class Router {
|
|
|
182
223
|
/**
|
|
183
224
|
* Add a listener for the onRoute event
|
|
184
225
|
*
|
|
185
|
-
* This
|
|
186
|
-
*
|
|
226
|
+
* This will trigger every time a new route is set
|
|
227
|
+
* and is equivalent to router.route.subscribe(fn)
|
|
187
228
|
*
|
|
188
229
|
* @returns a function to remove the listener
|
|
189
230
|
*/
|
|
190
231
|
onRoute(fn) {
|
|
191
|
-
return this.
|
|
232
|
+
return this.route.subscribe(fn);
|
|
192
233
|
}
|
|
193
234
|
/**
|
|
194
235
|
* Add a listener for the onRequest event
|
|
@@ -213,6 +254,9 @@ export default class Router {
|
|
|
213
254
|
}
|
|
214
255
|
async _initServer(url, acceptLang) {
|
|
215
256
|
this.inner.initServer();
|
|
257
|
+
this._internal.onNothingLoaded = (_req, ready) => {
|
|
258
|
+
ready();
|
|
259
|
+
};
|
|
216
260
|
const prom = new Promise(resolve => {
|
|
217
261
|
this._internal.onLoaded = (success, req, ready) => {
|
|
218
262
|
const props = ready();
|
|
@@ -263,7 +307,12 @@ export default class Router {
|
|
|
263
307
|
}
|
|
264
308
|
this._onRequest.trigger(req);
|
|
265
309
|
// route prepared
|
|
266
|
-
|
|
310
|
+
if (!req.disableLoadData) {
|
|
311
|
+
this.pageLoader.load(req, { changeHistory });
|
|
312
|
+
}
|
|
313
|
+
else {
|
|
314
|
+
this._onNothingLoaded(req, { changeHistory });
|
|
315
|
+
}
|
|
267
316
|
}
|
|
268
317
|
destroyRequest() {
|
|
269
318
|
if (!this._request)
|
|
@@ -283,15 +332,27 @@ export default class Router {
|
|
|
283
332
|
// in the meantime
|
|
284
333
|
more.changeHistory();
|
|
285
334
|
const route = req.toRoute();
|
|
286
|
-
|
|
287
|
-
this.setNewRoute(route);
|
|
288
|
-
this._onRouteEv.trigger(route.clone());
|
|
289
|
-
};
|
|
335
|
+
// call the client or server saying we are ready for a new render
|
|
290
336
|
this._internal.onLoaded(resp.success, req, () => {
|
|
291
|
-
|
|
337
|
+
this.setNewRoute(route);
|
|
292
338
|
return resp.data;
|
|
293
339
|
});
|
|
294
340
|
}
|
|
341
|
+
async _onNothingLoaded(req, more) {
|
|
342
|
+
// check if the render was cancelled
|
|
343
|
+
if (await req._renderBarrier.ready())
|
|
344
|
+
return;
|
|
345
|
+
// when the data is loaded let's update the route of the inner
|
|
346
|
+
// this is will only happen if no other route has been requested
|
|
347
|
+
// in the meantime
|
|
348
|
+
more.changeHistory();
|
|
349
|
+
const route = req.toRoute();
|
|
350
|
+
// call the client or server saying there was an update in the route
|
|
351
|
+
// but no new data was loaded so no render should happen
|
|
352
|
+
this._internal.onNothingLoaded(req, () => {
|
|
353
|
+
this.setNewRoute(route);
|
|
354
|
+
});
|
|
355
|
+
}
|
|
295
356
|
_onProgress(loading, progress) {
|
|
296
357
|
if (this._loading.get() !== loading)
|
|
297
358
|
this._loading.set(loading);
|
package/package.json
CHANGED
package/src/index.ts
CHANGED
|
@@ -143,6 +143,15 @@ export function getCookies(): Cookies {
|
|
|
143
143
|
return getCrelte().cookies;
|
|
144
144
|
}
|
|
145
145
|
|
|
146
|
+
export function onRoute(fn: (route: Route, crelte: Crelte) => void) {
|
|
147
|
+
const crelte = getCrelte();
|
|
148
|
+
const rmListener = crelte.router.onRoute(route => {
|
|
149
|
+
fn(route, crelte);
|
|
150
|
+
});
|
|
151
|
+
|
|
152
|
+
onDestroy(rmListener);
|
|
153
|
+
}
|
|
154
|
+
|
|
146
155
|
/**
|
|
147
156
|
* Listen for requests
|
|
148
157
|
*
|
package/src/init/client.ts
CHANGED
|
@@ -204,6 +204,15 @@ export function main(data: MainData) {
|
|
|
204
204
|
await render();
|
|
205
205
|
};
|
|
206
206
|
|
|
207
|
+
crelte.router._internal.onNothingLoaded = async (req, ready) => {
|
|
208
|
+
crelte.globals._updateSiteId(req.site.id);
|
|
209
|
+
ready();
|
|
210
|
+
|
|
211
|
+
await tick();
|
|
212
|
+
|
|
213
|
+
crelte.router._internal.domReady(req);
|
|
214
|
+
};
|
|
215
|
+
|
|
207
216
|
crelte.router._internal.initClient();
|
|
208
217
|
}
|
|
209
218
|
|
|
@@ -2,7 +2,7 @@ import Site, { SiteFromGraphQl } from './Site.js';
|
|
|
2
2
|
import History from './History.js';
|
|
3
3
|
import { ClientHistory, ServerHistory } from './History.js';
|
|
4
4
|
import Request, { isRequest, RequestOptions } from './Request.js';
|
|
5
|
-
import Route
|
|
5
|
+
import Route from './Route.js';
|
|
6
6
|
|
|
7
7
|
export type InnerRouterOpts = {
|
|
8
8
|
preloadOnMouseOver: boolean;
|
|
@@ -66,14 +66,9 @@ export default class InnerRouter {
|
|
|
66
66
|
req._fillFromState(window.history.state);
|
|
67
67
|
|
|
68
68
|
req.origin = 'init';
|
|
69
|
-
|
|
70
|
-
if (req.search.get('x-craft-live-preview')) {
|
|
71
|
-
req.origin = 'live-preview-init';
|
|
72
|
-
}
|
|
73
|
-
|
|
74
69
|
window.history.scrollRestoration = 'manual';
|
|
75
70
|
|
|
76
|
-
this.
|
|
71
|
+
this.setRoute(req);
|
|
77
72
|
}
|
|
78
73
|
|
|
79
74
|
/**
|
|
@@ -139,9 +134,10 @@ export default class InnerRouter {
|
|
|
139
134
|
}
|
|
140
135
|
|
|
141
136
|
/**
|
|
142
|
-
* Resolve a url or Route and convert it to a
|
|
137
|
+
* Resolve a url or Route and convert it to a Request
|
|
143
138
|
*
|
|
144
139
|
* @param target
|
|
140
|
+
* @param opts, any option present will override the value in target
|
|
145
141
|
* @return Returns null if the url does not match our host (the protocol get's ignored)
|
|
146
142
|
*/
|
|
147
143
|
targetToRequest(
|
|
@@ -221,12 +217,20 @@ export default class InnerRouter {
|
|
|
221
217
|
|
|
222
218
|
e.preventDefault();
|
|
223
219
|
|
|
224
|
-
const
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
route
|
|
220
|
+
const req = this.targetToRequest(link.href, { origin: 'click' });
|
|
221
|
+
const routeEq =
|
|
222
|
+
this.route && this.route.eqUrl(req) && this.route.eqSearch(req);
|
|
223
|
+
// the route is the same don't do anything
|
|
224
|
+
// or maybe scroll the page to the hash? todo
|
|
225
|
+
if (routeEq && this.route?.eqHash(req)) return;
|
|
226
|
+
|
|
227
|
+
// this means the hash did not match, so we wan't to just scroll but not load
|
|
228
|
+
// data
|
|
229
|
+
if (routeEq) {
|
|
230
|
+
req.disableLoadData = true;
|
|
231
|
+
}
|
|
228
232
|
|
|
229
|
-
this.open(
|
|
233
|
+
this.open(req);
|
|
230
234
|
});
|
|
231
235
|
|
|
232
236
|
if (this.preloadOnMouseOver) {
|
|
@@ -270,7 +274,7 @@ export default class InnerRouter {
|
|
|
270
274
|
// use the latest state
|
|
271
275
|
this.history.replaceState(this.route._toState());
|
|
272
276
|
|
|
273
|
-
if (current.
|
|
277
|
+
if (current.inLivePreview()) {
|
|
274
278
|
sessionStorage.setItem(
|
|
275
279
|
'live-preview-scroll',
|
|
276
280
|
// use the latest scrollY
|
|
@@ -286,31 +290,28 @@ export default class InnerRouter {
|
|
|
286
290
|
window.addEventListener('popstate', async e => {
|
|
287
291
|
if (!('route' in e.state)) return;
|
|
288
292
|
|
|
289
|
-
const
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
// since the pop event replaced our state we can't replace the state
|
|
294
|
-
// for the scrollY in our open call so we just clear the current
|
|
295
|
-
// route since it is now already the new route
|
|
296
|
-
this.route = null;
|
|
293
|
+
const req = this.targetToRequest(window.location.href);
|
|
294
|
+
req._fillFromState(e.state);
|
|
295
|
+
req.origin = 'pop';
|
|
297
296
|
|
|
298
|
-
this.
|
|
297
|
+
this.setRoute(req);
|
|
299
298
|
});
|
|
300
299
|
}
|
|
301
300
|
|
|
302
301
|
/**
|
|
303
|
-
* Open
|
|
302
|
+
* Open a new route
|
|
304
303
|
*
|
|
305
304
|
* @param route a route object or an url or uri, never input the same route object again
|
|
306
305
|
* @param pushState if true pushed the state to the window.history
|
|
306
|
+
*
|
|
307
|
+
* ## Important
|
|
308
|
+
* Make sure a req always has the correct origin,
|
|
309
|
+
* `push` and `replace` will cause this function to throw an error
|
|
307
310
|
*/
|
|
308
|
-
open(
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
) {
|
|
313
|
-
const req = this.targetToRequest(target, opts);
|
|
311
|
+
open(req: Request) {
|
|
312
|
+
if (['push', 'replace'].includes(req.origin)) {
|
|
313
|
+
throw new Error('Do not use open with push or replace');
|
|
314
|
+
}
|
|
314
315
|
|
|
315
316
|
const current = this.route;
|
|
316
317
|
if (current) {
|
|
@@ -340,14 +341,10 @@ export default class InnerRouter {
|
|
|
340
341
|
return;
|
|
341
342
|
}
|
|
342
343
|
|
|
343
|
-
|
|
344
|
-
|
|
345
|
-
this.
|
|
346
|
-
|
|
347
|
-
});
|
|
348
|
-
} else {
|
|
349
|
-
this.setRoute(req);
|
|
350
|
-
}
|
|
344
|
+
req.index = (current?.index ?? 0) + 1;
|
|
345
|
+
this.onRoute(req, () => {
|
|
346
|
+
this.push(req, true);
|
|
347
|
+
});
|
|
351
348
|
}
|
|
352
349
|
|
|
353
350
|
/**
|
|
@@ -358,47 +355,70 @@ export default class InnerRouter {
|
|
|
358
355
|
*
|
|
359
356
|
* @param req
|
|
360
357
|
*/
|
|
361
|
-
setRoute(req: Request) {
|
|
358
|
+
setRoute(req: Request, preventOnRoute = false) {
|
|
362
359
|
this.route = req.toRoute();
|
|
363
360
|
|
|
364
|
-
this.onRoute(req, () => {});
|
|
361
|
+
if (!preventOnRoute) this.onRoute(req, () => {});
|
|
365
362
|
}
|
|
366
363
|
|
|
367
364
|
/**
|
|
368
|
-
* This pushes
|
|
369
|
-
* or currentSiteId change
|
|
365
|
+
* This pushes a new route to the history
|
|
370
366
|
*
|
|
371
|
-
*
|
|
372
|
-
* (search argument) and then call pushState
|
|
367
|
+
* @param req, never input the same route object again
|
|
373
368
|
*
|
|
374
|
-
*
|
|
369
|
+
* ## Important
|
|
370
|
+
* Make sure the route has the correct origin
|
|
375
371
|
*/
|
|
376
|
-
|
|
377
|
-
const url =
|
|
372
|
+
push(req: Request, preventOnRoute = false) {
|
|
373
|
+
const url = req.url;
|
|
374
|
+
// todo a push should also store the previous scrollY
|
|
375
|
+
|
|
376
|
+
let nReq = req;
|
|
377
|
+
if (req.scrollY === null) {
|
|
378
|
+
// if there is no scrollY stored we store the current scrollY
|
|
379
|
+
// since a push does not cause a scroll top
|
|
380
|
+
// todo: probably should refactor something probably
|
|
381
|
+
// should not be here
|
|
382
|
+
nReq = req.clone();
|
|
383
|
+
nReq.scrollY = this.history.scrollY();
|
|
384
|
+
}
|
|
378
385
|
|
|
379
386
|
this.history.pushState(
|
|
380
|
-
|
|
387
|
+
nReq._toState(),
|
|
381
388
|
url.pathname + url.search + url.hash,
|
|
382
389
|
);
|
|
383
390
|
|
|
384
|
-
this.
|
|
391
|
+
this.setRoute(req, preventOnRoute);
|
|
385
392
|
}
|
|
386
393
|
|
|
387
394
|
/**
|
|
388
|
-
* This replaces the
|
|
389
|
-
* or currentSiteId change
|
|
395
|
+
* This replaces the current route
|
|
390
396
|
*
|
|
391
|
-
* @param
|
|
397
|
+
* @param req, never input the same route object again
|
|
398
|
+
*
|
|
399
|
+
* ## Important
|
|
400
|
+
* Make sure the route has the correct origin
|
|
392
401
|
*/
|
|
393
|
-
|
|
394
|
-
const url =
|
|
402
|
+
replace(req: Request) {
|
|
403
|
+
const url = req.url;
|
|
404
|
+
|
|
405
|
+
let nReq = req;
|
|
406
|
+
if (req.scrollY === null) {
|
|
407
|
+
// if there is no scrollY stored we store the current scrollY
|
|
408
|
+
// since a replace does not cause a scrollTo and we wan't
|
|
409
|
+
// history back to work as intended
|
|
410
|
+
// todo: probably should refactor something probably
|
|
411
|
+
// should not be here
|
|
412
|
+
nReq = req.clone();
|
|
413
|
+
nReq.scrollY = this.history.scrollY();
|
|
414
|
+
}
|
|
395
415
|
|
|
396
416
|
this.history.replaceState(
|
|
397
|
-
|
|
417
|
+
nReq._toState(),
|
|
398
418
|
url.pathname + url.search + url.hash,
|
|
399
419
|
);
|
|
400
420
|
|
|
401
|
-
this.
|
|
421
|
+
this.setRoute(req);
|
|
402
422
|
}
|
|
403
423
|
|
|
404
424
|
/**
|
|
@@ -430,7 +450,7 @@ export default class InnerRouter {
|
|
|
430
450
|
|
|
431
451
|
// if the route is a live preview init and we have a scrollY stored
|
|
432
452
|
// scroll to that
|
|
433
|
-
if (req.
|
|
453
|
+
if (req.inLivePreview()) {
|
|
434
454
|
const scrollY = sessionStorage.getItem('live-preview-scroll');
|
|
435
455
|
if (scrollY) {
|
|
436
456
|
scrollTo = {
|
|
@@ -465,6 +485,10 @@ export default class InnerRouter {
|
|
|
465
485
|
};
|
|
466
486
|
}
|
|
467
487
|
|
|
488
|
+
// make sure push and replace don't cause a scroll if it is not intended
|
|
489
|
+
if (!scrollTo && (req.origin === 'push' || req.origin === 'replace'))
|
|
490
|
+
return;
|
|
491
|
+
|
|
468
492
|
// scroll to the top if nothing else matches
|
|
469
493
|
if (!scrollTo) {
|
|
470
494
|
scrollTo = {
|
package/src/routing/Request.ts
CHANGED
|
@@ -10,6 +10,7 @@ export type RequestOptions = {
|
|
|
10
10
|
index?: number;
|
|
11
11
|
origin?: RouteOrigin;
|
|
12
12
|
disableScroll?: boolean;
|
|
13
|
+
disableLoadData?: boolean;
|
|
13
14
|
statusCode?: number;
|
|
14
15
|
};
|
|
15
16
|
|
|
@@ -25,6 +26,12 @@ export default class Request extends Route {
|
|
|
25
26
|
*/
|
|
26
27
|
disableScroll: boolean;
|
|
27
28
|
|
|
29
|
+
/**
|
|
30
|
+
* Disable loading data
|
|
31
|
+
* @default false
|
|
32
|
+
*/
|
|
33
|
+
disableLoadData: boolean;
|
|
34
|
+
|
|
28
35
|
/**
|
|
29
36
|
* The Status code that should be returned for a redirect
|
|
30
37
|
*/
|
|
@@ -40,6 +47,7 @@ export default class Request extends Route {
|
|
|
40
47
|
super(url, site, opts);
|
|
41
48
|
|
|
42
49
|
this.disableScroll = opts.disableScroll ?? false;
|
|
50
|
+
this.disableLoadData = opts.disableLoadData ?? false;
|
|
43
51
|
this.statusCode = opts.statusCode ?? null;
|
|
44
52
|
this._renderBarrier = new RenderBarrier();
|
|
45
53
|
}
|