@viewfly/router 2.0.0-alpha.1 → 2.0.0-alpha.4
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/bundles/index.d.ts +74 -20
- package/bundles/index.esm.js +442 -195
- package/bundles/index.js +442 -193
- package/package.json +3 -3
package/bundles/index.esm.js
CHANGED
|
@@ -1,6 +1,107 @@
|
|
|
1
|
-
import {
|
|
2
|
-
import { Injectable, inject, createSignal, onUnmounted, makeError, createContext } from '@viewfly/core';
|
|
1
|
+
import { makeError, Injectable, inject, readonlyProxyHandler, comparePropsWithCallbacks, internalWrite, onUnmounted, reactive, createContext, shallowReactive } from '@viewfly/core';
|
|
3
2
|
import { Subject, Subscription, fromEvent } from '@tanbo/stream';
|
|
3
|
+
import { jsx } from '@viewfly/core/jsx-runtime';
|
|
4
|
+
|
|
5
|
+
const routerErrorFn$1 = makeError('Router');
|
|
6
|
+
class Router {
|
|
7
|
+
get deep() {
|
|
8
|
+
return this.parent ? this.parent.deep + 1 : 0;
|
|
9
|
+
}
|
|
10
|
+
get path() {
|
|
11
|
+
return this.navigator.urlTree.paths.at(this.deep) || '';
|
|
12
|
+
}
|
|
13
|
+
constructor(navigator, parent) {
|
|
14
|
+
Object.defineProperty(this, "navigator", {
|
|
15
|
+
enumerable: true,
|
|
16
|
+
configurable: true,
|
|
17
|
+
writable: true,
|
|
18
|
+
value: navigator
|
|
19
|
+
});
|
|
20
|
+
Object.defineProperty(this, "parent", {
|
|
21
|
+
enumerable: true,
|
|
22
|
+
configurable: true,
|
|
23
|
+
writable: true,
|
|
24
|
+
value: parent
|
|
25
|
+
});
|
|
26
|
+
Object.defineProperty(this, "onRefresh", {
|
|
27
|
+
enumerable: true,
|
|
28
|
+
configurable: true,
|
|
29
|
+
writable: true,
|
|
30
|
+
value: void 0
|
|
31
|
+
});
|
|
32
|
+
Object.defineProperty(this, "refreshEvent", {
|
|
33
|
+
enumerable: true,
|
|
34
|
+
configurable: true,
|
|
35
|
+
writable: true,
|
|
36
|
+
value: new Subject()
|
|
37
|
+
});
|
|
38
|
+
this.onRefresh = this.refreshEvent.asObservable();
|
|
39
|
+
}
|
|
40
|
+
navigateTo(path, params, fragment) {
|
|
41
|
+
this.navigator.to(path, this, params, fragment || void 0);
|
|
42
|
+
}
|
|
43
|
+
replaceTo(path, params) {
|
|
44
|
+
this.navigator.replace(path, this, params);
|
|
45
|
+
}
|
|
46
|
+
refresh() {
|
|
47
|
+
this.refreshEvent.next();
|
|
48
|
+
}
|
|
49
|
+
consumeConfig(routes) {
|
|
50
|
+
return this.matchRoute(routes, this.path);
|
|
51
|
+
}
|
|
52
|
+
back() {
|
|
53
|
+
this.navigator.back();
|
|
54
|
+
}
|
|
55
|
+
forward() {
|
|
56
|
+
this.navigator.forward();
|
|
57
|
+
}
|
|
58
|
+
go(offset) {
|
|
59
|
+
this.navigator.go(offset);
|
|
60
|
+
}
|
|
61
|
+
matchRoute(configs, pathname) {
|
|
62
|
+
let matchedConfig = null;
|
|
63
|
+
let defaultConfig = null;
|
|
64
|
+
let fallbackConfig = null;
|
|
65
|
+
for (const item of configs) {
|
|
66
|
+
if (item.path === pathname) {
|
|
67
|
+
matchedConfig = item;
|
|
68
|
+
break;
|
|
69
|
+
}
|
|
70
|
+
else if (item.path === '*') {
|
|
71
|
+
if (!fallbackConfig) {
|
|
72
|
+
fallbackConfig = item;
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
else if (item.path === '') {
|
|
76
|
+
if (!defaultConfig) {
|
|
77
|
+
defaultConfig = item;
|
|
78
|
+
}
|
|
79
|
+
}
|
|
80
|
+
}
|
|
81
|
+
const config = matchedConfig || defaultConfig || fallbackConfig;
|
|
82
|
+
if (!config) {
|
|
83
|
+
return config;
|
|
84
|
+
}
|
|
85
|
+
if (typeof config.redirectTo === 'function') {
|
|
86
|
+
const p = config.redirectTo(pathname);
|
|
87
|
+
if (typeof p === 'string') {
|
|
88
|
+
this.navigateTo(p);
|
|
89
|
+
}
|
|
90
|
+
else if (typeof p === 'object') {
|
|
91
|
+
this.navigateTo(p.pathname, p.queryParams, p.fragment);
|
|
92
|
+
}
|
|
93
|
+
else {
|
|
94
|
+
throw routerErrorFn$1(`Router redirect to '${pathname}' not supported`);
|
|
95
|
+
}
|
|
96
|
+
return null;
|
|
97
|
+
}
|
|
98
|
+
if (typeof config.redirectTo === 'string') {
|
|
99
|
+
this.navigateTo(config.redirectTo);
|
|
100
|
+
return null;
|
|
101
|
+
}
|
|
102
|
+
return config;
|
|
103
|
+
}
|
|
104
|
+
}
|
|
4
105
|
|
|
5
106
|
/******************************************************************************
|
|
6
107
|
Copyright (c) Microsoft Corporation.
|
|
@@ -30,11 +131,187 @@ function __metadata(metadataKey, metadataValue) {
|
|
|
30
131
|
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(metadataKey, metadataValue);
|
|
31
132
|
}
|
|
32
133
|
|
|
134
|
+
function __awaiter(thisArg, _arguments, P, generator) {
|
|
135
|
+
function adopt(value) { return value instanceof P ? value : new P(function (resolve) { resolve(value); }); }
|
|
136
|
+
return new (P || (P = Promise))(function (resolve, reject) {
|
|
137
|
+
function fulfilled(value) { try { step(generator.next(value)); } catch (e) { reject(e); } }
|
|
138
|
+
function rejected(value) { try { step(generator["throw"](value)); } catch (e) { reject(e); } }
|
|
139
|
+
function step(result) { result.done ? resolve(result.value) : adopt(result.value).then(fulfilled, rejected); }
|
|
140
|
+
step((generator = generator.apply(thisArg, _arguments || [])).next());
|
|
141
|
+
});
|
|
142
|
+
}
|
|
143
|
+
|
|
33
144
|
typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
|
|
34
145
|
var e = new Error(message);
|
|
35
146
|
return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
|
|
36
147
|
};
|
|
37
148
|
|
|
149
|
+
class UrlParser {
|
|
150
|
+
constructor() {
|
|
151
|
+
Object.defineProperty(this, "index", {
|
|
152
|
+
enumerable: true,
|
|
153
|
+
configurable: true,
|
|
154
|
+
writable: true,
|
|
155
|
+
value: 0
|
|
156
|
+
});
|
|
157
|
+
Object.defineProperty(this, "url", {
|
|
158
|
+
enumerable: true,
|
|
159
|
+
configurable: true,
|
|
160
|
+
writable: true,
|
|
161
|
+
value: ''
|
|
162
|
+
});
|
|
163
|
+
Object.defineProperty(this, "tokens", {
|
|
164
|
+
enumerable: true,
|
|
165
|
+
configurable: true,
|
|
166
|
+
writable: true,
|
|
167
|
+
value: []
|
|
168
|
+
});
|
|
169
|
+
}
|
|
170
|
+
parse(url) {
|
|
171
|
+
this.index = 0;
|
|
172
|
+
this.url = url;
|
|
173
|
+
this.tokens = [];
|
|
174
|
+
while (this.index < this.url.length) {
|
|
175
|
+
this.ignore('/');
|
|
176
|
+
if (this.peek('../')) {
|
|
177
|
+
this.tokens.push({
|
|
178
|
+
type: 'toParent'
|
|
179
|
+
});
|
|
180
|
+
this.index += 3;
|
|
181
|
+
}
|
|
182
|
+
else if (this.peek('?')) {
|
|
183
|
+
this.index++;
|
|
184
|
+
this.tokens.push({
|
|
185
|
+
type: 'query',
|
|
186
|
+
params: this.readQuery()
|
|
187
|
+
});
|
|
188
|
+
}
|
|
189
|
+
else if (this.peek('#')) {
|
|
190
|
+
this.index++;
|
|
191
|
+
this.tokens.push({
|
|
192
|
+
type: 'hash',
|
|
193
|
+
value: this.readHash()
|
|
194
|
+
});
|
|
195
|
+
}
|
|
196
|
+
else {
|
|
197
|
+
if (this.peek('./')) {
|
|
198
|
+
this.index += 2;
|
|
199
|
+
}
|
|
200
|
+
const path = this.readPath();
|
|
201
|
+
if (path) {
|
|
202
|
+
this.tokens.push({
|
|
203
|
+
type: 'toChild',
|
|
204
|
+
value: path
|
|
205
|
+
});
|
|
206
|
+
}
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
const urlTree = {
|
|
210
|
+
paths: [],
|
|
211
|
+
queryParams: {},
|
|
212
|
+
hash: null
|
|
213
|
+
};
|
|
214
|
+
for (const item of this.tokens) {
|
|
215
|
+
switch (item.type) {
|
|
216
|
+
case 'toParent':
|
|
217
|
+
urlTree.paths.pop();
|
|
218
|
+
break;
|
|
219
|
+
case 'toChild':
|
|
220
|
+
urlTree.paths.push(item.value);
|
|
221
|
+
break;
|
|
222
|
+
case 'query':
|
|
223
|
+
urlTree.queryParams = item.params;
|
|
224
|
+
break;
|
|
225
|
+
case 'hash':
|
|
226
|
+
urlTree.hash = item.value;
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
return urlTree;
|
|
230
|
+
}
|
|
231
|
+
readHash() {
|
|
232
|
+
const hash = this.url.substring(this.index);
|
|
233
|
+
this.index = this.url.length;
|
|
234
|
+
return hash;
|
|
235
|
+
}
|
|
236
|
+
readQuery() {
|
|
237
|
+
const query = {};
|
|
238
|
+
while (this.index < this.url.length) {
|
|
239
|
+
const key = this.readQueryKey();
|
|
240
|
+
let value = '';
|
|
241
|
+
if (this.peek('=')) {
|
|
242
|
+
this.index++;
|
|
243
|
+
value = this.readQueryValue();
|
|
244
|
+
}
|
|
245
|
+
const oldValue = query[key];
|
|
246
|
+
if (oldValue) {
|
|
247
|
+
if (Array.isArray(oldValue)) {
|
|
248
|
+
oldValue.push(value);
|
|
249
|
+
}
|
|
250
|
+
else {
|
|
251
|
+
query[key] = [oldValue, value];
|
|
252
|
+
}
|
|
253
|
+
}
|
|
254
|
+
else {
|
|
255
|
+
query[key] = value;
|
|
256
|
+
}
|
|
257
|
+
if (this.peek('&')) {
|
|
258
|
+
this.index++;
|
|
259
|
+
continue;
|
|
260
|
+
}
|
|
261
|
+
break;
|
|
262
|
+
}
|
|
263
|
+
return query;
|
|
264
|
+
}
|
|
265
|
+
readQueryValue() {
|
|
266
|
+
const chars = [];
|
|
267
|
+
while (this.index < this.url.length) {
|
|
268
|
+
if (this.not('&#')) {
|
|
269
|
+
chars.push(this.url.at(this.index));
|
|
270
|
+
this.index++;
|
|
271
|
+
continue;
|
|
272
|
+
}
|
|
273
|
+
break;
|
|
274
|
+
}
|
|
275
|
+
return chars.join('');
|
|
276
|
+
}
|
|
277
|
+
readQueryKey() {
|
|
278
|
+
const chars = [];
|
|
279
|
+
while (this.index < this.url.length) {
|
|
280
|
+
if (this.not('=&#')) {
|
|
281
|
+
chars.push(this.url.at(this.index));
|
|
282
|
+
this.index++;
|
|
283
|
+
continue;
|
|
284
|
+
}
|
|
285
|
+
break;
|
|
286
|
+
}
|
|
287
|
+
return chars.join('');
|
|
288
|
+
}
|
|
289
|
+
readPath() {
|
|
290
|
+
const chars = [];
|
|
291
|
+
while (this.index < this.url.length) {
|
|
292
|
+
if (this.not('./?#')) {
|
|
293
|
+
chars.push(this.url.at(this.index));
|
|
294
|
+
this.index++;
|
|
295
|
+
continue;
|
|
296
|
+
}
|
|
297
|
+
break;
|
|
298
|
+
}
|
|
299
|
+
return chars.join('');
|
|
300
|
+
}
|
|
301
|
+
not(text) {
|
|
302
|
+
const ch = this.url.at(this.index);
|
|
303
|
+
return text.indexOf(ch) === -1;
|
|
304
|
+
}
|
|
305
|
+
peek(str) {
|
|
306
|
+
return this.url.slice(this.index, this.index + str.length) === str;
|
|
307
|
+
}
|
|
308
|
+
ignore(str) {
|
|
309
|
+
while (this.peek(str)) {
|
|
310
|
+
this.index++;
|
|
311
|
+
}
|
|
312
|
+
}
|
|
313
|
+
}
|
|
314
|
+
|
|
38
315
|
class Navigator {
|
|
39
316
|
constructor(baseUrl) {
|
|
40
317
|
Object.defineProperty(this, "baseUrl", {
|
|
@@ -67,16 +344,35 @@ function formatQueryParams(queryParams) {
|
|
|
67
344
|
}
|
|
68
345
|
let BrowserNavigator = class BrowserNavigator extends Navigator {
|
|
69
346
|
get pathname() {
|
|
70
|
-
|
|
347
|
+
const pathname = location.pathname;
|
|
348
|
+
return pathname.startsWith(this.baseUrl) ? pathname.substring(this.baseUrl.length) : pathname;
|
|
71
349
|
}
|
|
72
|
-
constructor(baseUrl) {
|
|
350
|
+
constructor(baseUrl, hooks = {}) {
|
|
73
351
|
super(baseUrl);
|
|
352
|
+
Object.defineProperty(this, "hooks", {
|
|
353
|
+
enumerable: true,
|
|
354
|
+
configurable: true,
|
|
355
|
+
writable: true,
|
|
356
|
+
value: hooks
|
|
357
|
+
});
|
|
74
358
|
Object.defineProperty(this, "onUrlChanged", {
|
|
75
359
|
enumerable: true,
|
|
76
360
|
configurable: true,
|
|
77
361
|
writable: true,
|
|
78
362
|
value: void 0
|
|
79
363
|
});
|
|
364
|
+
Object.defineProperty(this, "urlParser", {
|
|
365
|
+
enumerable: true,
|
|
366
|
+
configurable: true,
|
|
367
|
+
writable: true,
|
|
368
|
+
value: new UrlParser()
|
|
369
|
+
});
|
|
370
|
+
Object.defineProperty(this, "urlTree", {
|
|
371
|
+
enumerable: true,
|
|
372
|
+
configurable: true,
|
|
373
|
+
writable: true,
|
|
374
|
+
value: this.getUrlTree()
|
|
375
|
+
});
|
|
80
376
|
Object.defineProperty(this, "urlChangeEvent", {
|
|
81
377
|
enumerable: true,
|
|
82
378
|
configurable: true,
|
|
@@ -91,6 +387,7 @@ let BrowserNavigator = class BrowserNavigator extends Navigator {
|
|
|
91
387
|
});
|
|
92
388
|
this.onUrlChanged = this.urlChangeEvent.asObservable();
|
|
93
389
|
this.subscription.add(fromEvent(window, 'popstate').subscribe(() => {
|
|
390
|
+
this.urlTree = this.getUrlTree();
|
|
94
391
|
this.urlChangeEvent.next();
|
|
95
392
|
}));
|
|
96
393
|
if (!this.pathname.startsWith(this.baseUrl)) {
|
|
@@ -102,8 +399,19 @@ let BrowserNavigator = class BrowserNavigator extends Navigator {
|
|
|
102
399
|
if (location.origin + url === location.href) {
|
|
103
400
|
return true;
|
|
104
401
|
}
|
|
105
|
-
|
|
106
|
-
|
|
402
|
+
this.runHooks({
|
|
403
|
+
pathname: this.pathname,
|
|
404
|
+
queryParams: this.urlTree.queryParams,
|
|
405
|
+
fragment: this.urlTree.hash
|
|
406
|
+
}, {
|
|
407
|
+
pathname: pathName,
|
|
408
|
+
queryParams: queryParams || {},
|
|
409
|
+
fragment: fragment || null
|
|
410
|
+
}, () => {
|
|
411
|
+
history.pushState(null, '', url);
|
|
412
|
+
this.urlTree = this.getUrlTree();
|
|
413
|
+
this.urlChangeEvent.next();
|
|
414
|
+
});
|
|
107
415
|
return true;
|
|
108
416
|
}
|
|
109
417
|
replace(pathName, relative, queryParams, fragment) {
|
|
@@ -111,15 +419,26 @@ let BrowserNavigator = class BrowserNavigator extends Navigator {
|
|
|
111
419
|
if (location.origin + url === location.href) {
|
|
112
420
|
return true;
|
|
113
421
|
}
|
|
114
|
-
|
|
115
|
-
|
|
422
|
+
this.runHooks({
|
|
423
|
+
pathname: this.pathname,
|
|
424
|
+
queryParams: this.urlTree.queryParams,
|
|
425
|
+
fragment: this.urlTree.hash
|
|
426
|
+
}, {
|
|
427
|
+
pathname: pathName,
|
|
428
|
+
queryParams: queryParams || {},
|
|
429
|
+
fragment: fragment || null
|
|
430
|
+
}, () => {
|
|
431
|
+
history.replaceState(null, '', url);
|
|
432
|
+
this.urlTree = this.getUrlTree();
|
|
433
|
+
this.urlChangeEvent.next();
|
|
434
|
+
});
|
|
116
435
|
return true;
|
|
117
436
|
}
|
|
118
437
|
join(pathname, relative, queryParams, fragment) {
|
|
119
438
|
if (pathname.startsWith('/')) {
|
|
120
439
|
return formatUrl(this.baseUrl + pathname, { queryParams, fragment });
|
|
121
440
|
}
|
|
122
|
-
|
|
441
|
+
const beforePath = this.urlTree.paths.slice(0, relative.deep);
|
|
123
442
|
while (true) {
|
|
124
443
|
if (pathname.startsWith('./')) {
|
|
125
444
|
pathname = pathname.substring(2);
|
|
@@ -127,21 +446,12 @@ let BrowserNavigator = class BrowserNavigator extends Navigator {
|
|
|
127
446
|
}
|
|
128
447
|
if (pathname.startsWith('../')) {
|
|
129
448
|
pathname = pathname.substring(3);
|
|
130
|
-
|
|
131
|
-
beforePath = relative.parent.beforePath;
|
|
132
|
-
relative = relative.parent;
|
|
133
|
-
}
|
|
134
|
-
else {
|
|
135
|
-
beforePath = '';
|
|
136
|
-
}
|
|
137
|
-
if (!beforePath) {
|
|
138
|
-
break;
|
|
139
|
-
}
|
|
449
|
+
beforePath.pop();
|
|
140
450
|
continue;
|
|
141
451
|
}
|
|
142
452
|
break;
|
|
143
453
|
}
|
|
144
|
-
return formatUrl(this.baseUrl + '/' + beforePath + '/' + pathname, { queryParams, fragment });
|
|
454
|
+
return formatUrl(this.baseUrl + '/' + beforePath.join('/') + '/' + pathname, { queryParams, fragment });
|
|
145
455
|
}
|
|
146
456
|
back() {
|
|
147
457
|
history.back();
|
|
@@ -155,124 +465,53 @@ let BrowserNavigator = class BrowserNavigator extends Navigator {
|
|
|
155
465
|
destroy() {
|
|
156
466
|
this.subscription.unsubscribe();
|
|
157
467
|
}
|
|
468
|
+
runHooks(beforeParams, currentParams, next) {
|
|
469
|
+
var _a, _b, _c, _d;
|
|
470
|
+
if (typeof this.hooks.beforeEach === 'function') {
|
|
471
|
+
(_b = (_a = this.hooks).beforeEach) === null || _b === void 0 ? void 0 : _b.call(_a, beforeParams, currentParams, () => {
|
|
472
|
+
var _a, _b;
|
|
473
|
+
next();
|
|
474
|
+
(_b = (_a = this.hooks).afterEach) === null || _b === void 0 ? void 0 : _b.call(_a, currentParams);
|
|
475
|
+
});
|
|
476
|
+
}
|
|
477
|
+
else {
|
|
478
|
+
next();
|
|
479
|
+
(_d = (_c = this.hooks).afterEach) === null || _d === void 0 ? void 0 : _d.call(_c, currentParams);
|
|
480
|
+
}
|
|
481
|
+
}
|
|
482
|
+
getUrlTree() {
|
|
483
|
+
return this.urlParser.parse(this.pathname + location.search + location.hash);
|
|
484
|
+
}
|
|
158
485
|
};
|
|
159
486
|
BrowserNavigator = __decorate([
|
|
160
487
|
Injectable(),
|
|
161
|
-
__metadata("design:paramtypes", [String])
|
|
488
|
+
__metadata("design:paramtypes", [String, Object])
|
|
162
489
|
], BrowserNavigator);
|
|
163
490
|
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
enumerable: true,
|
|
183
|
-
configurable: true,
|
|
184
|
-
writable: true,
|
|
185
|
-
value: navigator
|
|
186
|
-
});
|
|
187
|
-
Object.defineProperty(this, "parent", {
|
|
188
|
-
enumerable: true,
|
|
189
|
-
configurable: true,
|
|
190
|
-
writable: true,
|
|
191
|
-
value: parent
|
|
192
|
-
});
|
|
193
|
-
Object.defineProperty(this, "path", {
|
|
194
|
-
enumerable: true,
|
|
195
|
-
configurable: true,
|
|
196
|
-
writable: true,
|
|
197
|
-
value: path
|
|
198
|
-
});
|
|
199
|
-
Object.defineProperty(this, "onRefresh", {
|
|
200
|
-
enumerable: true,
|
|
201
|
-
configurable: true,
|
|
202
|
-
writable: true,
|
|
203
|
-
value: void 0
|
|
204
|
-
});
|
|
205
|
-
Object.defineProperty(this, "refreshEvent", {
|
|
206
|
-
enumerable: true,
|
|
207
|
-
configurable: true,
|
|
208
|
-
writable: true,
|
|
209
|
-
value: new Subject()
|
|
491
|
+
function useQueryParams() {
|
|
492
|
+
const router = inject(Router);
|
|
493
|
+
const navigator = inject(Navigator);
|
|
494
|
+
const params = Object.assign({}, navigator.urlTree.queryParams);
|
|
495
|
+
const queryParams = new Proxy(params, readonlyProxyHandler);
|
|
496
|
+
const subscription = router.onRefresh.subscribe(() => {
|
|
497
|
+
comparePropsWithCallbacks(params, navigator.urlTree.queryParams, key => {
|
|
498
|
+
internalWrite(() => {
|
|
499
|
+
Reflect.deleteProperty(params, key);
|
|
500
|
+
});
|
|
501
|
+
}, (key, value) => {
|
|
502
|
+
internalWrite(() => {
|
|
503
|
+
params[key] = value;
|
|
504
|
+
});
|
|
505
|
+
}, (key, value) => {
|
|
506
|
+
internalWrite(() => {
|
|
507
|
+
params[key] = value;
|
|
508
|
+
});
|
|
210
509
|
});
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
replaceTo(path, params) {
|
|
217
|
-
this.navigator.replace(path, this, params);
|
|
218
|
-
}
|
|
219
|
-
refresh(path) {
|
|
220
|
-
this.path = path;
|
|
221
|
-
this.refreshEvent.next();
|
|
222
|
-
}
|
|
223
|
-
consumeConfig(routes) {
|
|
224
|
-
const routeConfig = this.matchRoute(routes);
|
|
225
|
-
if (!routeConfig) {
|
|
226
|
-
return null;
|
|
227
|
-
}
|
|
228
|
-
let remainingPath = '';
|
|
229
|
-
if (routeConfig.path === '') {
|
|
230
|
-
remainingPath = this.path;
|
|
231
|
-
}
|
|
232
|
-
else if (routeConfig.path === '*') {
|
|
233
|
-
remainingPath = '';
|
|
234
|
-
}
|
|
235
|
-
else {
|
|
236
|
-
remainingPath = this.path.substring(routeConfig.path.length + 1);
|
|
237
|
-
}
|
|
238
|
-
return {
|
|
239
|
-
remainingPath,
|
|
240
|
-
routeConfig
|
|
241
|
-
};
|
|
242
|
-
}
|
|
243
|
-
back() {
|
|
244
|
-
this.navigator.back();
|
|
245
|
-
}
|
|
246
|
-
forward() {
|
|
247
|
-
this.navigator.forward();
|
|
248
|
-
}
|
|
249
|
-
go(offset) {
|
|
250
|
-
this.navigator.go(offset);
|
|
251
|
-
}
|
|
252
|
-
matchRoute(configs) {
|
|
253
|
-
var _a;
|
|
254
|
-
let matchedConfig = null;
|
|
255
|
-
let defaultConfig = null;
|
|
256
|
-
let fallbackConfig = null;
|
|
257
|
-
const pathname = ((_a = (this.path || '').match(/[^\/?#]+/)) === null || _a === void 0 ? void 0 : _a[0]) || '';
|
|
258
|
-
for (const item of configs) {
|
|
259
|
-
if (item.path === pathname) {
|
|
260
|
-
matchedConfig = item;
|
|
261
|
-
break;
|
|
262
|
-
}
|
|
263
|
-
else if (item.path === '*') {
|
|
264
|
-
if (!fallbackConfig) {
|
|
265
|
-
fallbackConfig = item;
|
|
266
|
-
}
|
|
267
|
-
}
|
|
268
|
-
else if (item.path === '') {
|
|
269
|
-
if (!defaultConfig) {
|
|
270
|
-
defaultConfig = item;
|
|
271
|
-
}
|
|
272
|
-
}
|
|
273
|
-
}
|
|
274
|
-
return matchedConfig || defaultConfig || fallbackConfig;
|
|
275
|
-
}
|
|
510
|
+
});
|
|
511
|
+
onUnmounted(() => {
|
|
512
|
+
subscription.unsubscribe();
|
|
513
|
+
});
|
|
514
|
+
return queryParams;
|
|
276
515
|
}
|
|
277
516
|
|
|
278
517
|
function Link(props) {
|
|
@@ -284,9 +523,11 @@ function Link(props) {
|
|
|
284
523
|
(navigator.pathname + '/') === navigator.join(props.to, router)) :
|
|
285
524
|
navigator.pathname.startsWith(navigator.join(props.to, router));
|
|
286
525
|
}
|
|
287
|
-
const isActive =
|
|
526
|
+
const isActive = reactive({
|
|
527
|
+
value: getActive()
|
|
528
|
+
});
|
|
288
529
|
const subscription = navigator.onUrlChanged.subscribe(() => {
|
|
289
|
-
isActive.
|
|
530
|
+
isActive.value = getActive();
|
|
290
531
|
});
|
|
291
532
|
onUnmounted(() => {
|
|
292
533
|
subscription.unsubscribe();
|
|
@@ -308,65 +549,15 @@ function Link(props) {
|
|
|
308
549
|
if (Tag === 'a') {
|
|
309
550
|
attrs.href = navigator.join(props.to, router, props.queryParams, props.fragment);
|
|
310
551
|
}
|
|
311
|
-
if (isActive
|
|
552
|
+
if (isActive.value && props.active) {
|
|
312
553
|
attrs.class = [attrs.class, props.active];
|
|
313
554
|
}
|
|
314
555
|
return jsx(Tag, Object.assign({}, attrs, { children: props.children }));
|
|
315
556
|
};
|
|
316
557
|
}
|
|
317
558
|
|
|
318
|
-
const routerErrorFn = makeError('RouterOutlet');
|
|
319
|
-
function RouterOutlet(props) {
|
|
320
|
-
const router = inject(Router, null);
|
|
321
|
-
if (router === null) {
|
|
322
|
-
throw routerErrorFn('cannot found parent Router.');
|
|
323
|
-
}
|
|
324
|
-
const navigator = inject(Navigator);
|
|
325
|
-
const childRouter = new Router(navigator, router, '');
|
|
326
|
-
const Context = createContext([{
|
|
327
|
-
provide: Router,
|
|
328
|
-
useValue: childRouter
|
|
329
|
-
}]);
|
|
330
|
-
const children = createSignal(null);
|
|
331
|
-
const subscription = router.onRefresh.subscribe(() => {
|
|
332
|
-
updateChildren();
|
|
333
|
-
});
|
|
334
|
-
onUnmounted(() => {
|
|
335
|
-
subscription.unsubscribe();
|
|
336
|
-
});
|
|
337
|
-
let currentComponent = null;
|
|
338
|
-
function updateChildren() {
|
|
339
|
-
const result = router.consumeConfig(props.config);
|
|
340
|
-
if (!result) {
|
|
341
|
-
currentComponent = null;
|
|
342
|
-
children.set(props.children || null);
|
|
343
|
-
return;
|
|
344
|
-
}
|
|
345
|
-
const { routeConfig, remainingPath } = result;
|
|
346
|
-
if (routeConfig.component) {
|
|
347
|
-
_updateChildren(routeConfig.component, remainingPath);
|
|
348
|
-
}
|
|
349
|
-
else if (routeConfig.asyncComponent) {
|
|
350
|
-
routeConfig.asyncComponent().then(c => {
|
|
351
|
-
_updateChildren(c, remainingPath);
|
|
352
|
-
});
|
|
353
|
-
}
|
|
354
|
-
}
|
|
355
|
-
function _updateChildren(Component, remainingPath) {
|
|
356
|
-
childRouter.refresh(remainingPath);
|
|
357
|
-
if (Component !== currentComponent) {
|
|
358
|
-
children.set(jsx(Component, {}));
|
|
359
|
-
}
|
|
360
|
-
currentComponent = Component;
|
|
361
|
-
}
|
|
362
|
-
updateChildren();
|
|
363
|
-
return () => {
|
|
364
|
-
return jsx(Context, { children: children() });
|
|
365
|
-
};
|
|
366
|
-
}
|
|
367
|
-
|
|
368
559
|
class RouterModule {
|
|
369
|
-
constructor(baseUrl = '') {
|
|
560
|
+
constructor(baseUrl = '', hooks = {}) {
|
|
370
561
|
Object.defineProperty(this, "baseUrl", {
|
|
371
562
|
enumerable: true,
|
|
372
563
|
configurable: true,
|
|
@@ -385,18 +576,13 @@ class RouterModule {
|
|
|
385
576
|
writable: true,
|
|
386
577
|
value: void 0
|
|
387
578
|
});
|
|
388
|
-
this.navigator = new BrowserNavigator(this.baseUrl);
|
|
579
|
+
this.navigator = new BrowserNavigator(this.baseUrl, hooks);
|
|
389
580
|
}
|
|
390
581
|
setup(app) {
|
|
391
|
-
const baseUrl = this.baseUrl;
|
|
392
582
|
const navigator = this.navigator;
|
|
393
|
-
|
|
394
|
-
const pathname = navigator.pathname;
|
|
395
|
-
return pathname.startsWith(baseUrl) ? pathname.substring(baseUrl.length) : pathname;
|
|
396
|
-
}
|
|
397
|
-
const router = new Router(navigator, null, getPath());
|
|
583
|
+
const router = new Router(navigator, null);
|
|
398
584
|
this.subscription.add(navigator.onUrlChanged.subscribe(() => {
|
|
399
|
-
router.refresh(
|
|
585
|
+
router.refresh();
|
|
400
586
|
}));
|
|
401
587
|
app.provide([
|
|
402
588
|
{
|
|
@@ -415,4 +601,65 @@ class RouterModule {
|
|
|
415
601
|
}
|
|
416
602
|
}
|
|
417
603
|
|
|
418
|
-
|
|
604
|
+
const routerErrorFn = makeError('RouterOutlet');
|
|
605
|
+
function RouterOutlet(props) {
|
|
606
|
+
const router = inject(Router, null);
|
|
607
|
+
if (router === null) {
|
|
608
|
+
throw routerErrorFn('cannot found parent Router.');
|
|
609
|
+
}
|
|
610
|
+
const navigator = inject(Navigator);
|
|
611
|
+
const childRouter = new Router(navigator, router);
|
|
612
|
+
const Context = createContext([{
|
|
613
|
+
provide: Router,
|
|
614
|
+
useValue: childRouter
|
|
615
|
+
}]);
|
|
616
|
+
const children = shallowReactive({
|
|
617
|
+
value: null
|
|
618
|
+
});
|
|
619
|
+
const subscription = router.onRefresh.subscribe(() => {
|
|
620
|
+
updateChildren();
|
|
621
|
+
});
|
|
622
|
+
onUnmounted(() => {
|
|
623
|
+
subscription.unsubscribe();
|
|
624
|
+
});
|
|
625
|
+
let currentComponent = null;
|
|
626
|
+
function updateChildren() {
|
|
627
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
628
|
+
const routeConfig = router.consumeConfig(props.config);
|
|
629
|
+
if (!routeConfig) {
|
|
630
|
+
currentComponent = null;
|
|
631
|
+
children.value = props.children || null;
|
|
632
|
+
return;
|
|
633
|
+
}
|
|
634
|
+
if (typeof routeConfig.beforeEach === 'function') {
|
|
635
|
+
const is = yield routeConfig.beforeEach();
|
|
636
|
+
if (!is) {
|
|
637
|
+
return;
|
|
638
|
+
}
|
|
639
|
+
}
|
|
640
|
+
if (routeConfig.component) {
|
|
641
|
+
_updateChildren(routeConfig.component);
|
|
642
|
+
}
|
|
643
|
+
else if (routeConfig.asyncComponent) {
|
|
644
|
+
const c = yield routeConfig.asyncComponent();
|
|
645
|
+
_updateChildren(c);
|
|
646
|
+
}
|
|
647
|
+
if (typeof routeConfig.afterEach === 'function') {
|
|
648
|
+
routeConfig.afterEach();
|
|
649
|
+
}
|
|
650
|
+
});
|
|
651
|
+
}
|
|
652
|
+
function _updateChildren(Component) {
|
|
653
|
+
childRouter.refresh();
|
|
654
|
+
if (Component !== currentComponent) {
|
|
655
|
+
children.value = jsx(Component, {});
|
|
656
|
+
}
|
|
657
|
+
currentComponent = Component;
|
|
658
|
+
}
|
|
659
|
+
updateChildren();
|
|
660
|
+
return () => {
|
|
661
|
+
return jsx(Context, { children: children.value });
|
|
662
|
+
};
|
|
663
|
+
}
|
|
664
|
+
|
|
665
|
+
export { BrowserNavigator, Link, Navigator, Router, RouterModule, RouterOutlet, UrlParser, formatQueryParams, formatUrl, useQueryParams };
|