@viewfly/router 2.1.0 → 3.0.0-alpha.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.js ADDED
@@ -0,0 +1,494 @@
1
+ Object.defineProperty(exports, Symbol.toStringTag, { value: "Module" });
2
+ let _viewfly_core = require("@viewfly/core");
3
+ let _tanbo_stream = require("@tanbo/stream");
4
+ //#region src/providers/router.ts
5
+ var routerErrorFn$1 = (0, _viewfly_core.makeError)("Router");
6
+ var Router = class {
7
+ onRefresh;
8
+ get deep() {
9
+ return this.parent ? this.parent.deep + 1 : 0;
10
+ }
11
+ get path() {
12
+ return this.navigator.urlTree.paths.at(this.deep) || "";
13
+ }
14
+ refreshEvent = new _tanbo_stream.Subject();
15
+ constructor(navigator, parent) {
16
+ this.navigator = navigator;
17
+ this.parent = parent;
18
+ this.onRefresh = this.refreshEvent.asObservable();
19
+ }
20
+ navigateTo(path, params, fragment) {
21
+ this.navigator.to(path, this, params, fragment || void 0);
22
+ }
23
+ replaceTo(path, params) {
24
+ this.navigator.replace(path, this, params);
25
+ }
26
+ refresh() {
27
+ this.refreshEvent.next();
28
+ }
29
+ consumeConfig(routes) {
30
+ return this.matchRoute(routes, this.path);
31
+ }
32
+ back() {
33
+ this.navigator.back();
34
+ }
35
+ forward() {
36
+ this.navigator.forward();
37
+ }
38
+ go(offset) {
39
+ this.navigator.go(offset);
40
+ }
41
+ matchRoute(configs, pathname) {
42
+ let matchedConfig = null;
43
+ let defaultConfig = null;
44
+ let fallbackConfig = null;
45
+ for (const item of configs) if (item.path === pathname) {
46
+ matchedConfig = item;
47
+ break;
48
+ } else if (item.path === "*") {
49
+ if (!fallbackConfig) fallbackConfig = item;
50
+ } else if (item.path === "") {
51
+ if (!defaultConfig) defaultConfig = item;
52
+ }
53
+ const config = matchedConfig || defaultConfig || fallbackConfig;
54
+ if (!config) return config;
55
+ if (typeof config.redirectTo === "function") {
56
+ const p = config.redirectTo(pathname);
57
+ if (typeof p === "string") this.navigateTo(p);
58
+ else if (typeof p === "object") this.navigateTo(p.pathname, p.queryParams, p.fragment);
59
+ else throw routerErrorFn$1(`Router redirect to '${pathname}' not supported`);
60
+ return null;
61
+ }
62
+ if (typeof config.redirectTo === "string") {
63
+ this.navigateTo(config.redirectTo);
64
+ return null;
65
+ }
66
+ return config;
67
+ }
68
+ };
69
+ //#endregion
70
+ //#region src/providers/url-parser.ts
71
+ var UrlParser = class {
72
+ index = 0;
73
+ url = "";
74
+ tokens = [];
75
+ parse(url) {
76
+ this.index = 0;
77
+ this.url = url;
78
+ this.tokens = [];
79
+ while (this.index < this.url.length) {
80
+ this.ignore("/");
81
+ if (this.peek("../")) {
82
+ this.tokens.push({ type: "toParent" });
83
+ this.index += 3;
84
+ } else if (this.peek("?")) {
85
+ this.index++;
86
+ this.tokens.push({
87
+ type: "query",
88
+ params: this.readQuery()
89
+ });
90
+ } else if (this.peek("#")) {
91
+ this.index++;
92
+ this.tokens.push({
93
+ type: "hash",
94
+ value: this.readHash()
95
+ });
96
+ } else {
97
+ if (this.peek("./")) this.index += 2;
98
+ const path = this.readPath();
99
+ if (path) this.tokens.push({
100
+ type: "toChild",
101
+ value: path
102
+ });
103
+ }
104
+ }
105
+ const urlTree = {
106
+ paths: [],
107
+ queryParams: {},
108
+ hash: null
109
+ };
110
+ for (const item of this.tokens) switch (item.type) {
111
+ case "toParent":
112
+ urlTree.paths.pop();
113
+ break;
114
+ case "toChild":
115
+ urlTree.paths.push(item.value);
116
+ break;
117
+ case "query":
118
+ urlTree.queryParams = item.params;
119
+ break;
120
+ case "hash": urlTree.hash = item.value;
121
+ }
122
+ return urlTree;
123
+ }
124
+ readHash() {
125
+ const hash = this.url.substring(this.index);
126
+ this.index = this.url.length;
127
+ return hash;
128
+ }
129
+ readQuery() {
130
+ const query = {};
131
+ while (this.index < this.url.length) {
132
+ const key = this.readQueryKey();
133
+ let value = "";
134
+ if (this.peek("=")) {
135
+ this.index++;
136
+ value = this.readQueryValue();
137
+ }
138
+ const oldValue = query[key];
139
+ if (oldValue) if (Array.isArray(oldValue)) oldValue.push(value);
140
+ else query[key] = [oldValue, value];
141
+ else query[key] = value;
142
+ if (this.peek("&")) {
143
+ this.index++;
144
+ continue;
145
+ }
146
+ break;
147
+ }
148
+ return query;
149
+ }
150
+ readQueryValue() {
151
+ const chars = [];
152
+ while (this.index < this.url.length) {
153
+ if (this.not("&#")) {
154
+ chars.push(this.url.at(this.index));
155
+ this.index++;
156
+ continue;
157
+ }
158
+ break;
159
+ }
160
+ return chars.join("");
161
+ }
162
+ readQueryKey() {
163
+ const chars = [];
164
+ while (this.index < this.url.length) {
165
+ if (this.not("=&#")) {
166
+ chars.push(this.url.at(this.index));
167
+ this.index++;
168
+ continue;
169
+ }
170
+ break;
171
+ }
172
+ return chars.join("");
173
+ }
174
+ readPath() {
175
+ const chars = [];
176
+ while (this.index < this.url.length) {
177
+ if (this.not("./?#")) {
178
+ chars.push(this.url.at(this.index));
179
+ this.index++;
180
+ continue;
181
+ }
182
+ break;
183
+ }
184
+ return chars.join("");
185
+ }
186
+ not(text) {
187
+ const ch = this.url.at(this.index);
188
+ return text.indexOf(ch) === -1;
189
+ }
190
+ peek(str) {
191
+ return this.url.slice(this.index, this.index + str.length) === str;
192
+ }
193
+ ignore(str) {
194
+ while (this.peek(str)) this.index++;
195
+ }
196
+ };
197
+ //#endregion
198
+ //#region \0@oxc-project+runtime@0.126.0/helpers/decorateMetadata.js
199
+ function __decorateMetadata(k, v) {
200
+ if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
201
+ }
202
+ //#endregion
203
+ //#region \0@oxc-project+runtime@0.126.0/helpers/decorate.js
204
+ function __decorate(decorators, target, key, desc) {
205
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
206
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
207
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
208
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
209
+ }
210
+ //#endregion
211
+ //#region src/providers/navigator.ts
212
+ var Navigator = class {
213
+ constructor(baseUrl) {
214
+ this.baseUrl = baseUrl;
215
+ }
216
+ };
217
+ function formatUrl(pathname, urlFormatParams) {
218
+ pathname = pathname.replace(/\/+/g, "/");
219
+ const { queryParams, fragment } = urlFormatParams;
220
+ return pathname + (queryParams ? "?" + formatQueryParams(queryParams) : "") + (fragment ? "#" + fragment : "");
221
+ }
222
+ function formatQueryParams(queryParams) {
223
+ const params = [];
224
+ Object.keys(queryParams).forEach((key) => {
225
+ const values = queryParams[key];
226
+ if (Array.isArray(values)) values.forEach((i) => {
227
+ params.push(`${key}=${decodeURIComponent(i)}`);
228
+ });
229
+ else params.push(`${key}=${decodeURIComponent(values)}`);
230
+ });
231
+ return params.join("&");
232
+ }
233
+ var BrowserNavigator = class BrowserNavigator extends Navigator {
234
+ onUrlChanged;
235
+ /** 挂载在 location 上的路径前缀;'' 或 '/' 表示站点根,不做剥离 */
236
+ get basePathPrefix() {
237
+ return this.baseUrl === "/" || this.baseUrl === "" ? "" : this.baseUrl;
238
+ }
239
+ get pathname() {
240
+ const pathname = location.pathname;
241
+ if (!this.basePathPrefix) return pathname;
242
+ return pathname.startsWith(this.basePathPrefix) ? pathname.substring(this.basePathPrefix.length) : pathname;
243
+ }
244
+ urlParser = new UrlParser();
245
+ urlTree = this.getUrlTree();
246
+ urlChangeEvent = new _tanbo_stream.Subject();
247
+ subscription = new _tanbo_stream.Subscription();
248
+ constructor(baseUrl, hooks = {}) {
249
+ super(baseUrl);
250
+ this.hooks = hooks;
251
+ this.onUrlChanged = this.urlChangeEvent.asObservable();
252
+ this.subscription.add((0, _tanbo_stream.fromEvent)(window, "popstate").subscribe(() => {
253
+ this.urlTree = this.getUrlTree();
254
+ this.urlChangeEvent.next();
255
+ }));
256
+ if (this.basePathPrefix && !location.pathname.startsWith(this.basePathPrefix)) history.replaceState(null, "", this.baseUrl);
257
+ }
258
+ to(pathName, relative, queryParams, fragment) {
259
+ const url = this.join(pathName, relative, queryParams, fragment);
260
+ if (location.origin + url === location.href) return true;
261
+ this.runHooks({
262
+ pathname: this.pathname,
263
+ queryParams: this.urlTree.queryParams,
264
+ fragment: this.urlTree.hash
265
+ }, {
266
+ pathname: pathName,
267
+ queryParams: queryParams || {},
268
+ fragment: fragment || null
269
+ }, () => {
270
+ history.pushState(null, "", url);
271
+ this.urlTree = this.getUrlTree();
272
+ this.urlChangeEvent.next();
273
+ });
274
+ return true;
275
+ }
276
+ replace(pathName, relative, queryParams, fragment) {
277
+ const url = this.join(pathName, relative, queryParams, fragment);
278
+ if (location.origin + url === location.href) return true;
279
+ this.runHooks({
280
+ pathname: this.pathname,
281
+ queryParams: this.urlTree.queryParams,
282
+ fragment: this.urlTree.hash
283
+ }, {
284
+ pathname: pathName,
285
+ queryParams: queryParams || {},
286
+ fragment: fragment || null
287
+ }, () => {
288
+ history.replaceState(null, "", url);
289
+ this.urlTree = this.getUrlTree();
290
+ this.urlChangeEvent.next();
291
+ });
292
+ return true;
293
+ }
294
+ join(pathname, relative, queryParams, fragment) {
295
+ if (pathname.startsWith("/")) return formatUrl(this.baseUrl + pathname, {
296
+ queryParams,
297
+ fragment
298
+ });
299
+ const beforePath = this.urlTree.paths.slice(0, relative.deep);
300
+ while (true) {
301
+ if (pathname.startsWith("./")) {
302
+ pathname = pathname.substring(2);
303
+ continue;
304
+ }
305
+ if (pathname.startsWith("../")) {
306
+ pathname = pathname.substring(3);
307
+ beforePath.pop();
308
+ continue;
309
+ }
310
+ break;
311
+ }
312
+ return formatUrl(this.baseUrl + "/" + beforePath.join("/") + "/" + pathname, {
313
+ queryParams,
314
+ fragment
315
+ });
316
+ }
317
+ back() {
318
+ history.back();
319
+ }
320
+ forward() {
321
+ history.forward();
322
+ }
323
+ go(offset) {
324
+ history.go(offset);
325
+ }
326
+ destroy() {
327
+ this.subscription.unsubscribe();
328
+ }
329
+ runHooks(beforeParams, currentParams, next) {
330
+ if (typeof this.hooks.beforeEach === "function") this.hooks.beforeEach?.(beforeParams, currentParams, () => {
331
+ next();
332
+ this.hooks.afterEach?.(currentParams);
333
+ });
334
+ else {
335
+ next();
336
+ this.hooks.afterEach?.(currentParams);
337
+ }
338
+ }
339
+ getUrlTree() {
340
+ return this.urlParser.parse(this.pathname + location.search + location.hash);
341
+ }
342
+ };
343
+ BrowserNavigator = __decorate([(0, _viewfly_core.Injectable)(), __decorateMetadata("design:paramtypes", [String, Object])], BrowserNavigator);
344
+ //#endregion
345
+ //#region src/hooks/use-query-params.ts
346
+ function useQueryParams() {
347
+ const router = (0, _viewfly_core.inject)(Router);
348
+ const navigator = (0, _viewfly_core.inject)(Navigator);
349
+ const params = { ...navigator.urlTree.queryParams };
350
+ const queryParams = new Proxy(params, _viewfly_core.readonlyProxyHandler);
351
+ const subscription = router.onRefresh.subscribe(() => {
352
+ (0, _viewfly_core.comparePropsWithCallbacks)(params, navigator.urlTree.queryParams, (key) => {
353
+ (0, _viewfly_core.internalWrite)(() => {
354
+ Reflect.deleteProperty(params, key);
355
+ });
356
+ }, (key, value) => {
357
+ (0, _viewfly_core.internalWrite)(() => {
358
+ params[key] = value;
359
+ });
360
+ }, (key, value) => {
361
+ (0, _viewfly_core.internalWrite)(() => {
362
+ params[key] = value;
363
+ });
364
+ });
365
+ });
366
+ (0, _viewfly_core.onUnmounted)(() => {
367
+ subscription.unsubscribe();
368
+ });
369
+ return queryParams;
370
+ }
371
+ //#endregion
372
+ //#region src/link.tsx
373
+ function Link(props) {
374
+ const navigator = (0, _viewfly_core.inject)(Navigator);
375
+ const router = (0, _viewfly_core.inject)(Router);
376
+ function getActive() {
377
+ return props.exact ? navigator.pathname === navigator.join(props.to, router) || navigator.pathname + "/" === navigator.join(props.to, router) : navigator.pathname.startsWith(navigator.join(props.to, router));
378
+ }
379
+ const isActive = (0, _viewfly_core.reactive)({ value: getActive() });
380
+ const subscription = navigator.onUrlChanged.subscribe(() => {
381
+ isActive.value = getActive();
382
+ });
383
+ (0, _viewfly_core.onUnmounted)(() => {
384
+ subscription.unsubscribe();
385
+ });
386
+ function navigate(ev) {
387
+ if ((!props.tag || props.tag === "a") && props.target === "_blank") return;
388
+ ev.preventDefault();
389
+ router.navigateTo(props.to, props.queryParams, props.fragment);
390
+ }
391
+ return () => {
392
+ const Tag = props.tag || "a";
393
+ const attrs = Object.assign({}, props, {
394
+ onClick(ev) {
395
+ navigate(ev);
396
+ props.onClick?.(ev);
397
+ },
398
+ ...props
399
+ });
400
+ if (Tag === "a") attrs.href = navigator.join(props.to, router, props.queryParams, props.fragment);
401
+ if (isActive.value && props.active) attrs.class = [attrs.class, props.active];
402
+ return /* @__PURE__ */ (0, _viewfly_core.jsx)(Tag, {
403
+ ...attrs,
404
+ children: props.children
405
+ });
406
+ };
407
+ }
408
+ //#endregion
409
+ //#region src/router-module.ts
410
+ var RouterModule = class {
411
+ subscription = new _tanbo_stream.Subscription();
412
+ navigator;
413
+ constructor(baseUrl = "", hooks = {}) {
414
+ this.baseUrl = baseUrl;
415
+ this.navigator = new BrowserNavigator(this.baseUrl, hooks);
416
+ }
417
+ setup(app) {
418
+ const navigator = this.navigator;
419
+ const router = new Router(navigator, null);
420
+ this.subscription.add(navigator.onUrlChanged.subscribe(() => {
421
+ router.refresh();
422
+ }));
423
+ app.provide([{
424
+ provide: Navigator,
425
+ useValue: navigator
426
+ }, {
427
+ provide: Router,
428
+ useValue: router
429
+ }]);
430
+ }
431
+ onDestroy() {
432
+ this.subscription.unsubscribe();
433
+ this.navigator.destroy();
434
+ }
435
+ };
436
+ //#endregion
437
+ //#region src/router-outlet.tsx
438
+ var routerErrorFn = (0, _viewfly_core.makeError)("RouterOutlet");
439
+ function RouterOutlet(props) {
440
+ const router = (0, _viewfly_core.inject)(Router, null);
441
+ if (router === null) throw routerErrorFn("cannot found parent Router.");
442
+ const childRouter = new Router((0, _viewfly_core.inject)(Navigator), router);
443
+ const Context = (0, _viewfly_core.createContext)([{
444
+ provide: Router,
445
+ useValue: childRouter
446
+ }]);
447
+ const children = (0, _viewfly_core.shallowReactive)({ value: null });
448
+ const subscription = router.onRefresh.subscribe(() => {
449
+ updateChildren();
450
+ });
451
+ (0, _viewfly_core.onUnmounted)(() => {
452
+ subscription.unsubscribe();
453
+ });
454
+ let currentComponent = null;
455
+ async function updateChildren() {
456
+ const routeConfig = router.consumeConfig(props.config);
457
+ if (!routeConfig) {
458
+ currentComponent = null;
459
+ children.value = props.children || null;
460
+ return;
461
+ }
462
+ if (typeof routeConfig.beforeEach === "function") {
463
+ if (!await routeConfig.beforeEach()) return;
464
+ }
465
+ if (routeConfig.component) _updateChildren(routeConfig.component);
466
+ else if (routeConfig.asyncComponent) _updateChildren(await routeConfig.asyncComponent());
467
+ if (typeof routeConfig.afterEach === "function") routeConfig.afterEach();
468
+ }
469
+ function _updateChildren(Component) {
470
+ childRouter.refresh();
471
+ if (Component !== currentComponent) children.value = /* @__PURE__ */ (0, _viewfly_core.jsx)(Component, {});
472
+ currentComponent = Component;
473
+ }
474
+ updateChildren();
475
+ return () => {
476
+ return /* @__PURE__ */ (0, _viewfly_core.jsx)(Context, { children: children.value });
477
+ };
478
+ }
479
+ //#endregion
480
+ Object.defineProperty(exports, "BrowserNavigator", {
481
+ enumerable: true,
482
+ get: function() {
483
+ return BrowserNavigator;
484
+ }
485
+ });
486
+ exports.Link = Link;
487
+ exports.Navigator = Navigator;
488
+ exports.Router = Router;
489
+ exports.RouterModule = RouterModule;
490
+ exports.RouterOutlet = RouterOutlet;
491
+ exports.UrlParser = UrlParser;
492
+ exports.formatQueryParams = formatQueryParams;
493
+ exports.formatUrl = formatUrl;
494
+ exports.useQueryParams = useQueryParams;
package/dist/link.d.ts ADDED
@@ -0,0 +1,12 @@
1
+ import { Props } from '@viewfly/core';
2
+ import { QueryParams } from './providers/_api';
3
+ export interface LinkProps extends Props {
4
+ to: string;
5
+ active?: string;
6
+ exact?: boolean;
7
+ queryParams?: QueryParams;
8
+ fragment?: string;
9
+ tag?: string;
10
+ [key: string]: any;
11
+ }
12
+ export declare function Link(props: LinkProps): () => import("@viewfly/core").JSX.Element;
@@ -0,0 +1,3 @@
1
+ export * from './navigator';
2
+ export * from './router';
3
+ export * from './url-parser';
@@ -0,0 +1,56 @@
1
+ import { Observable } from '@tanbo/stream';
2
+ import { Router } from './router';
3
+ import { UrlTree } from './url-parser';
4
+ export interface QueryParams {
5
+ [key: string]: string | string[];
6
+ }
7
+ export declare abstract class Navigator {
8
+ baseUrl: string;
9
+ abstract urlTree: UrlTree;
10
+ protected constructor(baseUrl: string);
11
+ abstract onUrlChanged: Observable<void>;
12
+ abstract get pathname(): string;
13
+ abstract to(pathName: string, relative: Router, queryParams?: QueryParams, fragment?: string): boolean;
14
+ abstract replace(pathName: string, relative: Router, queryParams?: QueryParams, fragment?: string): boolean;
15
+ abstract join(pathName: string, relative: Router, queryParams?: QueryParams, fragment?: string): string;
16
+ abstract back(): void;
17
+ abstract forward(): void;
18
+ abstract go(offset: number): void;
19
+ abstract destroy(): void;
20
+ }
21
+ export interface UrlFormatParams {
22
+ queryParams?: QueryParams;
23
+ fragment?: string;
24
+ }
25
+ export declare function formatUrl(pathname: string, urlFormatParams: UrlFormatParams): string;
26
+ export declare function formatQueryParams(queryParams: QueryParams): string;
27
+ export interface NavigatorParams {
28
+ pathname: string;
29
+ queryParams: QueryParams;
30
+ fragment: string | null;
31
+ }
32
+ export interface NavigatorHooks {
33
+ beforeEach?(currentParams: NavigatorParams, nextParams: NavigatorParams, next: () => void): void;
34
+ afterEach?(params: NavigatorParams): void;
35
+ }
36
+ export declare class BrowserNavigator extends Navigator {
37
+ private hooks;
38
+ onUrlChanged: Observable<void>;
39
+ /** 挂载在 location 上的路径前缀;'' 或 '/' 表示站点根,不做剥离 */
40
+ private get basePathPrefix();
41
+ get pathname(): string;
42
+ private urlParser;
43
+ urlTree: UrlTree;
44
+ private urlChangeEvent;
45
+ private subscription;
46
+ constructor(baseUrl: string, hooks?: NavigatorHooks);
47
+ to(pathName: string, relative: Router, queryParams?: QueryParams, fragment?: string): boolean;
48
+ replace(pathName: string, relative: Router, queryParams?: QueryParams, fragment?: string): boolean;
49
+ join(pathname: string, relative: Router, queryParams?: QueryParams, fragment?: string): string;
50
+ back(): void;
51
+ forward(): void;
52
+ go(offset: number): void;
53
+ destroy(): void;
54
+ private runHooks;
55
+ private getUrlTree;
56
+ }
@@ -0,0 +1,28 @@
1
+ import { Observable } from '@tanbo/stream';
2
+ import { ComponentSetup } from '@viewfly/core';
3
+ import { Navigator, NavigatorParams, QueryParams } from './navigator';
4
+ export interface RouteConfig {
5
+ path: string;
6
+ component?: ComponentSetup;
7
+ asyncComponent?: () => Promise<ComponentSetup>;
8
+ beforeEach?(): boolean | Promise<boolean>;
9
+ afterEach?(): void;
10
+ redirectTo?: string | ((path: string) => string | NavigatorParams);
11
+ }
12
+ export declare class Router {
13
+ private navigator;
14
+ parent: Router | null;
15
+ onRefresh: Observable<void>;
16
+ get deep(): number;
17
+ get path(): string;
18
+ private refreshEvent;
19
+ constructor(navigator: Navigator, parent: Router | null);
20
+ navigateTo(path: string, params?: QueryParams, fragment?: string | null): void;
21
+ replaceTo(path: string, params?: QueryParams): void;
22
+ refresh(): void;
23
+ consumeConfig(routes: RouteConfig[]): RouteConfig | null;
24
+ back(): void;
25
+ forward(): void;
26
+ go(offset: number): void;
27
+ private matchRoute;
28
+ }
@@ -0,0 +1,38 @@
1
+ export interface UrlRelativePath {
2
+ type: 'toParent';
3
+ }
4
+ export interface UrlChildPath {
5
+ type: 'toChild';
6
+ value: string;
7
+ }
8
+ export interface UrlQuery {
9
+ type: 'query';
10
+ params: UrlQueryParams;
11
+ }
12
+ export interface UrlQueryParams {
13
+ [key: string]: string | string[];
14
+ }
15
+ export interface UrlHash {
16
+ type: 'hash';
17
+ value: string;
18
+ }
19
+ export type UrlToken = UrlRelativePath | UrlChildPath | UrlQuery | UrlHash;
20
+ export interface UrlTree {
21
+ paths: string[];
22
+ queryParams: UrlQueryParams;
23
+ hash: string | null;
24
+ }
25
+ export declare class UrlParser {
26
+ private index;
27
+ private url;
28
+ private tokens;
29
+ parse(url: string): UrlTree;
30
+ private readHash;
31
+ private readQuery;
32
+ private readQueryValue;
33
+ private readQueryKey;
34
+ private readPath;
35
+ private not;
36
+ private peek;
37
+ private ignore;
38
+ }
@@ -0,0 +1,10 @@
1
+ import { Application, Module } from '@viewfly/core';
2
+ import { NavigatorHooks } from './providers/navigator';
3
+ export declare class RouterModule implements Module {
4
+ baseUrl: string;
5
+ private subscription;
6
+ private navigator;
7
+ constructor(baseUrl?: string, hooks?: NavigatorHooks);
8
+ setup(app: Application): void;
9
+ onDestroy(): void;
10
+ }
@@ -0,0 +1,6 @@
1
+ import { Props } from '@viewfly/core';
2
+ import { RouteConfig } from './providers/_api';
3
+ export interface RouterOutletProps extends Props {
4
+ config: RouteConfig[];
5
+ }
6
+ export declare function RouterOutlet(props: RouterOutletProps): () => import("@viewfly/core").JSX.Element;