@rxdi/router 0.7.220 → 0.7.221
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/README.md +101 -0
- package/dist/decorators.d.ts +1 -2
- package/dist/decorators.js +1 -1
- package/dist/helpers.d.ts +1 -1
- package/dist/helpers.js +11 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +2 -2
- package/dist/injection.tokens.d.ts +23 -16
- package/dist/injection.tokens.js +3 -1
- package/dist/lib/constants.d.ts +3 -0
- package/dist/lib/constants.js +6 -0
- package/dist/lib/index.d.ts +4 -0
- package/dist/{slot → lib}/index.js +6 -4
- package/dist/lib/path-to-regexp.d.ts +6 -0
- package/dist/lib/path-to-regexp.js +228 -0
- package/dist/lib/resolver.d.ts +70 -0
- package/dist/lib/resolver.js +426 -0
- package/dist/{vaadin/vaadin-router.d.ts → lib/router.d.ts} +98 -201
- package/dist/lib/router.js +833 -0
- package/dist/lib/triggers.d.ts +6 -0
- package/dist/lib/triggers.js +98 -0
- package/dist/lib/types.d.ts +134 -0
- package/dist/lib/types.js +6 -0
- package/dist/lib/utils.d.ts +20 -0
- package/dist/lib/utils.js +155 -0
- package/dist/not-found.component.js +3 -3
- package/dist/outlet.d.ts +7 -62
- package/dist/outlet.js +15 -84
- package/dist/router.component.d.ts +3 -3
- package/dist/router.component.js +4 -4
- package/package.json +3 -3
- package/dist/slot/index.d.ts +0 -8
- package/dist/slot/slot.d.ts +0 -11
- package/dist/slot/slot.js +0 -44
- package/dist/vaadin/vaadin-router.js +0 -2065
- package/slot/index.d.ts +0 -8
- package/slot/index.js +0 -8
- package/slot/slot.d.ts +0 -11
- package/slot/slot.js +0 -45
|
@@ -0,0 +1,833 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.Router = void 0;
|
|
4
|
+
const path_to_regexp_1 = require("./path-to-regexp");
|
|
5
|
+
const resolver_1 = require("./resolver");
|
|
6
|
+
const triggers_1 = require("./triggers");
|
|
7
|
+
const types_1 = require("./types");
|
|
8
|
+
const utils_1 = require("./utils");
|
|
9
|
+
const willAnimate = (elem) => {
|
|
10
|
+
const name = getComputedStyle(elem).getPropertyValue('animation-name');
|
|
11
|
+
return name && name !== 'none';
|
|
12
|
+
};
|
|
13
|
+
const waitForAnimation = (elem, cb) => {
|
|
14
|
+
const listener = () => {
|
|
15
|
+
elem.removeEventListener('animationend', listener);
|
|
16
|
+
cb();
|
|
17
|
+
};
|
|
18
|
+
elem.addEventListener('animationend', listener);
|
|
19
|
+
};
|
|
20
|
+
function animate(elem, className) {
|
|
21
|
+
elem.classList.add(className);
|
|
22
|
+
return new Promise((resolve) => {
|
|
23
|
+
if (willAnimate(elem)) {
|
|
24
|
+
const rect = elem.getBoundingClientRect();
|
|
25
|
+
const size = `height: ${rect.bottom - rect.top}px; width: ${rect.right - rect.left}px`;
|
|
26
|
+
elem.setAttribute('style', `position: absolute; ${size}`);
|
|
27
|
+
waitForAnimation(elem, () => {
|
|
28
|
+
elem.classList.remove(className);
|
|
29
|
+
elem.removeAttribute('style');
|
|
30
|
+
resolve();
|
|
31
|
+
});
|
|
32
|
+
}
|
|
33
|
+
else {
|
|
34
|
+
elem.classList.remove(className);
|
|
35
|
+
resolve();
|
|
36
|
+
}
|
|
37
|
+
});
|
|
38
|
+
}
|
|
39
|
+
const MAX_REDIRECT_COUNT = 256;
|
|
40
|
+
function isResultNotEmpty(result) {
|
|
41
|
+
return result !== null && result !== undefined;
|
|
42
|
+
}
|
|
43
|
+
function copyContextWithoutNext(context) {
|
|
44
|
+
const copy = Object.assign({}, context);
|
|
45
|
+
delete copy.next;
|
|
46
|
+
return copy;
|
|
47
|
+
}
|
|
48
|
+
function getPathnameForRouter(pathname, router) {
|
|
49
|
+
const base = router.__getEffectiveBaseUrl();
|
|
50
|
+
return base
|
|
51
|
+
? router.constructor.__createUrl(pathname.replace(/^\//, ''), base).pathname
|
|
52
|
+
: pathname;
|
|
53
|
+
}
|
|
54
|
+
function getMatchedPath(chain) {
|
|
55
|
+
return chain
|
|
56
|
+
.map((item) => {
|
|
57
|
+
const path = item.path || item.path || '';
|
|
58
|
+
return Array.isArray(path) ? path[0] : path;
|
|
59
|
+
})
|
|
60
|
+
.reduce((a, b) => {
|
|
61
|
+
if (b.length) {
|
|
62
|
+
return a.replace(/\/$/, '') + '/' + b.replace(/^\//, '');
|
|
63
|
+
}
|
|
64
|
+
return a;
|
|
65
|
+
}, '');
|
|
66
|
+
}
|
|
67
|
+
function createLocation({ pathname = '', search = '', hash = '', chain = [], params = {}, redirectFrom, resolver, }, route) {
|
|
68
|
+
const routes = chain.map((item) => item.route);
|
|
69
|
+
return {
|
|
70
|
+
baseUrl: (resolver && resolver.baseUrl) || '',
|
|
71
|
+
pathname,
|
|
72
|
+
search,
|
|
73
|
+
hash,
|
|
74
|
+
routes,
|
|
75
|
+
route: route || (routes.length && routes[routes.length - 1]) || null,
|
|
76
|
+
params,
|
|
77
|
+
redirectFrom,
|
|
78
|
+
getUrl: (userParams = {}) => getPathnameForRouter((0, path_to_regexp_1.compile)(getMatchedPath(routes))(Object.assign({}, params, userParams)), resolver),
|
|
79
|
+
};
|
|
80
|
+
}
|
|
81
|
+
function createRedirect(context, pathname) {
|
|
82
|
+
const params = Object.assign({}, context.params);
|
|
83
|
+
return {
|
|
84
|
+
redirect: {
|
|
85
|
+
pathname,
|
|
86
|
+
from: context.pathname,
|
|
87
|
+
params,
|
|
88
|
+
},
|
|
89
|
+
};
|
|
90
|
+
}
|
|
91
|
+
function renderElement(context, element) {
|
|
92
|
+
element.location = createLocation(context);
|
|
93
|
+
const index = context.chain.map((item) => item.route).indexOf(context.route);
|
|
94
|
+
context.chain[index].element = element;
|
|
95
|
+
return element;
|
|
96
|
+
}
|
|
97
|
+
function amend(amendmentFunction, args, element) {
|
|
98
|
+
return (amendmentResult) => {
|
|
99
|
+
if (amendmentResult &&
|
|
100
|
+
(amendmentResult.cancel || amendmentResult.redirect)) {
|
|
101
|
+
return amendmentResult;
|
|
102
|
+
}
|
|
103
|
+
if (element) {
|
|
104
|
+
return (0, utils_1.runCallbackIfPossible)(element[amendmentFunction], args, element);
|
|
105
|
+
}
|
|
106
|
+
return undefined;
|
|
107
|
+
};
|
|
108
|
+
}
|
|
109
|
+
function processNewChildren(newChildren, route) {
|
|
110
|
+
if (!Array.isArray(newChildren) && !(0, utils_1.isObject)(newChildren)) {
|
|
111
|
+
throw new Error((0, utils_1.log)(`Incorrect "children" value for the route ${route.path}: expected array or object, but got ${newChildren}`));
|
|
112
|
+
}
|
|
113
|
+
route.__children = [];
|
|
114
|
+
const childRoutes = (0, utils_1.toArray)(newChildren);
|
|
115
|
+
for (let i = 0; i < childRoutes.length; i++) {
|
|
116
|
+
(0, utils_1.ensureRoute)(childRoutes[i]);
|
|
117
|
+
route.__children.push(childRoutes[i]);
|
|
118
|
+
}
|
|
119
|
+
}
|
|
120
|
+
function removeDomNodes(nodes) {
|
|
121
|
+
if (nodes && nodes.length) {
|
|
122
|
+
const parent = nodes[0].parentNode;
|
|
123
|
+
for (let i = 0; i < nodes.length; i++) {
|
|
124
|
+
parent.removeChild(nodes[i]);
|
|
125
|
+
}
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
/**
|
|
129
|
+
* A simple client-side router for single-page applications. It uses
|
|
130
|
+
* express-style middleware and has a first-class support for Web Components and
|
|
131
|
+
* lazy-loading. Works great in Polymer and non-Polymer apps.
|
|
132
|
+
*
|
|
133
|
+
* Use `new Router(outlet, options)` to create a new Router instance.
|
|
134
|
+
*
|
|
135
|
+
* * The `outlet` parameter is a reference to the DOM node to render
|
|
136
|
+
* the content into.
|
|
137
|
+
*
|
|
138
|
+
* * The `options` parameter is an optional object with options. The following
|
|
139
|
+
* keys are supported:
|
|
140
|
+
* * `baseUrl` — the initial value for [
|
|
141
|
+
* the `baseUrl` property
|
|
142
|
+
* ](#/classes/Router#property-baseUrl)
|
|
143
|
+
*
|
|
144
|
+
* The Router instance is automatically subscribed to navigation events
|
|
145
|
+
* on `window`.
|
|
146
|
+
*
|
|
147
|
+
* See [Live Examples](#/classes/Router/demos/demo/index.html) for the detailed usage demo and code snippets.
|
|
148
|
+
*
|
|
149
|
+
* See also detailed API docs for the following methods, for the advanced usage:
|
|
150
|
+
*
|
|
151
|
+
* * [setOutlet](#/classes/Router#method-setOutlet) – should be used to configure the outlet.
|
|
152
|
+
* * [setTriggers](#/classes/Router#method-setTriggers) – should be used to configure the navigation events.
|
|
153
|
+
* * [setRoutes](#/classes/Router#method-setRoutes) – should be used to configure the routes.
|
|
154
|
+
*
|
|
155
|
+
* Only `setRoutes` has to be called manually, others are automatically invoked when creating a new instance.
|
|
156
|
+
*
|
|
157
|
+
* @extends Resolver
|
|
158
|
+
* @demo demo/index.html
|
|
159
|
+
* @summary JavaScript class that renders different DOM content depending on
|
|
160
|
+
* a given path. It can re-render when triggered or automatically on
|
|
161
|
+
* 'popstate' and / or 'click' events.
|
|
162
|
+
*/
|
|
163
|
+
class Router extends resolver_1.Resolver {
|
|
164
|
+
/**
|
|
165
|
+
* Creates a new Router instance with a given outlet, and
|
|
166
|
+
* automatically subscribes it to navigation events on the `window`.
|
|
167
|
+
* Using a constructor argument or a setter for outlet is equivalent:
|
|
168
|
+
*
|
|
169
|
+
* ```
|
|
170
|
+
* const router = new Router();
|
|
171
|
+
* router.setOutlet(outlet);
|
|
172
|
+
* ```
|
|
173
|
+
* @param outlet
|
|
174
|
+
* @param options
|
|
175
|
+
*/
|
|
176
|
+
constructor(outlet, options) {
|
|
177
|
+
const baseElement = document.head.querySelector('base');
|
|
178
|
+
const baseHref = baseElement && baseElement.getAttribute('href');
|
|
179
|
+
super([], Object.assign({
|
|
180
|
+
baseUrl: baseHref && resolver_1.Resolver.__createUrl(baseHref, document.URL).pathname.replace(/[^\/]*$/, ''),
|
|
181
|
+
}, options));
|
|
182
|
+
this.resolveRoute = (context) => this.__resolveRoute(context);
|
|
183
|
+
(0, triggers_1.setNavigationTriggers)([triggers_1.POPSTATE, triggers_1.CLICK]);
|
|
184
|
+
this.ready = Promise.resolve(outlet);
|
|
185
|
+
this.location = createLocation({ resolver: this });
|
|
186
|
+
this.__lastStartedRenderId = 0;
|
|
187
|
+
this.__navigationEventHandler = this.__onNavigationEvent.bind(this);
|
|
188
|
+
this.setOutlet(outlet);
|
|
189
|
+
this.subscribe();
|
|
190
|
+
this.__createdByRouter = new WeakMap();
|
|
191
|
+
this.__addedByRouter = new WeakMap();
|
|
192
|
+
}
|
|
193
|
+
__resolveRoute(context) {
|
|
194
|
+
const route = context.route;
|
|
195
|
+
let callbacks = Promise.resolve();
|
|
196
|
+
if ((0, utils_1.isFunction)(route.children)) {
|
|
197
|
+
callbacks = callbacks
|
|
198
|
+
.then(() => route.children(copyContextWithoutNext(context)))
|
|
199
|
+
.then((children) => {
|
|
200
|
+
if (!isResultNotEmpty(children) && !(0, utils_1.isFunction)(route.children)) {
|
|
201
|
+
children = route.children;
|
|
202
|
+
}
|
|
203
|
+
processNewChildren(children, route);
|
|
204
|
+
});
|
|
205
|
+
}
|
|
206
|
+
const commands = {
|
|
207
|
+
redirect: (path) => createRedirect(context, path),
|
|
208
|
+
component: (component) => {
|
|
209
|
+
const element = document.createElement(component);
|
|
210
|
+
this.__createdByRouter.set(element, true);
|
|
211
|
+
return element;
|
|
212
|
+
},
|
|
213
|
+
};
|
|
214
|
+
return callbacks
|
|
215
|
+
.then(() => {
|
|
216
|
+
if (this.__isLatestRender(context)) {
|
|
217
|
+
return (0, utils_1.runCallbackIfPossible)(route.action, [context, commands], route);
|
|
218
|
+
}
|
|
219
|
+
return undefined;
|
|
220
|
+
})
|
|
221
|
+
.then((result) => {
|
|
222
|
+
if (isResultNotEmpty(result)) {
|
|
223
|
+
if (result instanceof HTMLElement || result.redirect || result === types_1.notFoundResult) {
|
|
224
|
+
return result;
|
|
225
|
+
}
|
|
226
|
+
}
|
|
227
|
+
if ((0, utils_1.isString)(route.redirect)) {
|
|
228
|
+
return commands.redirect(route.redirect);
|
|
229
|
+
}
|
|
230
|
+
if (route.bundle) {
|
|
231
|
+
return (0, utils_1.loadBundle)(route.bundle).then(() => undefined, () => {
|
|
232
|
+
throw new Error((0, utils_1.log)(`Bundle not found: ${route.bundle}. Check if the file name is correct`));
|
|
233
|
+
});
|
|
234
|
+
}
|
|
235
|
+
return undefined;
|
|
236
|
+
})
|
|
237
|
+
.then((result) => {
|
|
238
|
+
if (isResultNotEmpty(result)) {
|
|
239
|
+
return result;
|
|
240
|
+
}
|
|
241
|
+
if ((0, utils_1.isString)(route.component)) {
|
|
242
|
+
return commands.component(route.component);
|
|
243
|
+
}
|
|
244
|
+
return undefined;
|
|
245
|
+
});
|
|
246
|
+
}
|
|
247
|
+
/**
|
|
248
|
+
* Takes current routes and set it
|
|
249
|
+
* @param routes: Route<C>[]
|
|
250
|
+
* @returns void
|
|
251
|
+
*/
|
|
252
|
+
/**
|
|
253
|
+
* Sets the router outlet (the DOM node where the content for the current
|
|
254
|
+
* route is inserted). Any content pre-existing in the router outlet is
|
|
255
|
+
* removed at the end of each render pass.
|
|
256
|
+
*
|
|
257
|
+
* NOTE: this method is automatically invoked first time when creating a new Router instance.
|
|
258
|
+
*
|
|
259
|
+
* @param outlet the DOM node where the content for the current route
|
|
260
|
+
* is inserted.
|
|
261
|
+
*/
|
|
262
|
+
setOutlet(outlet) {
|
|
263
|
+
if (outlet) {
|
|
264
|
+
this.__ensureOutlet(outlet);
|
|
265
|
+
}
|
|
266
|
+
this.__outlet = outlet;
|
|
267
|
+
}
|
|
268
|
+
/**
|
|
269
|
+
* Returns the current router outlet. The initial value is undefined.
|
|
270
|
+
*/
|
|
271
|
+
/**
|
|
272
|
+
* Returns the current router outlet. The initial value is undefined.
|
|
273
|
+
*
|
|
274
|
+
* @return the current router outlet (or `undefined`)
|
|
275
|
+
*/
|
|
276
|
+
getOutlet() {
|
|
277
|
+
return this.__outlet;
|
|
278
|
+
}
|
|
279
|
+
/**
|
|
280
|
+
* Takes current routes and set it
|
|
281
|
+
* @param routes: Route | Route[]
|
|
282
|
+
* @returns Route | Route[]
|
|
283
|
+
*/
|
|
284
|
+
/**
|
|
285
|
+
* Sets the routing config (replacing the existing one) and triggers a
|
|
286
|
+
* navigation event so that the router outlet is refreshed according to the
|
|
287
|
+
* current `window.location` and the new routing config.
|
|
288
|
+
*
|
|
289
|
+
* Each route object may have the following properties, listed here in the processing order:
|
|
290
|
+
* * `path` – the route path (relative to the parent route if any) in the
|
|
291
|
+
* [express.js syntax](https://expressjs.com/en/guide/routing.html#route-paths").
|
|
292
|
+
*
|
|
293
|
+
* * `children` – an array of nested routes or a function that provides this
|
|
294
|
+
* array at the render time. The function can be synchronous or asynchronous:
|
|
295
|
+
* in the latter case the render is delayed until the returned promise is
|
|
296
|
+
* resolved. The `children` function is executed every time when this route is
|
|
297
|
+
* being rendered. This allows for dynamic route structures (e.g. backend-defined),
|
|
298
|
+
* but it might have a performance impact as well. In order to avoid calling
|
|
299
|
+
* the function on subsequent renders, you can override the `children` property
|
|
300
|
+
* of the route object and save the calculated array there
|
|
301
|
+
* (via `context.route.children = [ route1, route2, ...];`).
|
|
302
|
+
* Parent routes are fully resolved before resolving the children. Children
|
|
303
|
+
* 'path' values are relative to the parent ones.
|
|
304
|
+
*
|
|
305
|
+
* * `action` – the action that is executed before the route is resolved.
|
|
306
|
+
* The value for this property should be a function, accepting `context`
|
|
307
|
+
* and `commands` parameters described below. If present, this function is
|
|
308
|
+
* always invoked first, disregarding of the other properties' presence.
|
|
309
|
+
* The action can return a result directly or within a `Promise`, which
|
|
310
|
+
* resolves to the result. If the action result is an `HTMLElement` instance,
|
|
311
|
+
* a `commands.component(name)` result, a `commands.redirect(path)` result,
|
|
312
|
+
* or a `context.next()` result, the current route resolution is finished,
|
|
313
|
+
* and other route config properties are ignored.
|
|
314
|
+
* See also **Route Actions** section in [Live Examples](#/classes/Router/demos/demo/index.html).
|
|
315
|
+
*
|
|
316
|
+
* * `redirect` – other route's path to redirect to. Passes all route parameters to the redirect target.
|
|
317
|
+
* The target route should also be defined.
|
|
318
|
+
* See also **Redirects** section in [Live Examples](#/classes/Router/demos/demo/index.html).
|
|
319
|
+
*
|
|
320
|
+
* * `bundle` – string containing the path to `.js` or `.mjs` bundle to load before resolving the route,
|
|
321
|
+
* or the object with "module" and "nomodule" keys referring to different bundles.
|
|
322
|
+
* Each bundle is only loaded once. If "module" and "nomodule" are set, only one bundle is loaded,
|
|
323
|
+
* depending on whether the browser supports ES modules or not.
|
|
324
|
+
* The property is ignored when either an `action` returns the result or `redirect` property is present.
|
|
325
|
+
* Any error, e.g. 404 while loading bundle will cause route resolution to throw.
|
|
326
|
+
* See also **Code Splitting** section in [Live Examples](#/classes/Router/demos/demo/index.html).
|
|
327
|
+
*
|
|
328
|
+
* * `component` – the tag name of the Web Component to resolve the route to.
|
|
329
|
+
* The property is ignored when either an `action` returns the result or `redirect` property is present.
|
|
330
|
+
* If route contains the `component` property (or an action that return a component)
|
|
331
|
+
* and its child route also contains the `component` property, child route's component
|
|
332
|
+
* will be rendered as a light dom child of a parent component.
|
|
333
|
+
*
|
|
334
|
+
* * `name` – the string name of the route to use in the
|
|
335
|
+
* [`router.urlForName(name, params)`](#/classes/Router#method-urlForName)
|
|
336
|
+
* navigation helper method.
|
|
337
|
+
*
|
|
338
|
+
* For any route function (`action`, `children`) defined, the corresponding `route` object is available inside the callback
|
|
339
|
+
* through the `this` reference. If you need to access it, make sure you define the callback as a non-arrow function
|
|
340
|
+
* because arrow functions do not have their own `this` reference.
|
|
341
|
+
*
|
|
342
|
+
* `context` object that is passed to `action` function holds the following properties:
|
|
343
|
+
* * `context.pathname` – string with the pathname being resolved
|
|
344
|
+
*
|
|
345
|
+
* * `context.search` – search query string
|
|
346
|
+
*
|
|
347
|
+
* * `context.hash` – hash string
|
|
348
|
+
*
|
|
349
|
+
* * `context.params` – object with route parameters
|
|
350
|
+
*
|
|
351
|
+
* * `context.route` – object that holds the route that is currently being rendered.
|
|
352
|
+
*
|
|
353
|
+
* * `context.next()` – function for asynchronously getting the next route
|
|
354
|
+
* contents from the resolution chain (if any)
|
|
355
|
+
*
|
|
356
|
+
* `commands` object that is passed to `action` function has
|
|
357
|
+
* the following methods:
|
|
358
|
+
*
|
|
359
|
+
* * `commands.redirect(path)` – function that creates a redirect data
|
|
360
|
+
* for the path specified.
|
|
361
|
+
*
|
|
362
|
+
* * `commands.component(component)` – function that creates a new HTMLElement
|
|
363
|
+
* with current context. Note: the component created by this function is reused if visiting the same path twice in row.
|
|
364
|
+
*
|
|
365
|
+
*
|
|
366
|
+
* @param routes a single route or an array of those
|
|
367
|
+
* @param skipRender configure the router but skip rendering the
|
|
368
|
+
* route corresponding to the current `window.location` values
|
|
369
|
+
*
|
|
370
|
+
* @return
|
|
371
|
+
*/
|
|
372
|
+
setRoutes(routes, skipRender = false) {
|
|
373
|
+
this.__previousContext = undefined;
|
|
374
|
+
this.__urlForName = undefined;
|
|
375
|
+
super.setRoutes(routes);
|
|
376
|
+
if (!skipRender) {
|
|
377
|
+
this.__onNavigationEvent();
|
|
378
|
+
}
|
|
379
|
+
return this.ready;
|
|
380
|
+
}
|
|
381
|
+
/**
|
|
382
|
+
* Asynchronously resolves the given pathname and renders the resolved route component into the router outlet. If no router outlet is set at the time of calling this method, or at the time when the route resolution is completed, a TypeError is thrown.
|
|
383
|
+
* Returns a promise that is fulfilled with the router outlet DOM Node after the route component is created and inserted into the router outlet, or rejected if no route matches the given path.
|
|
384
|
+
* If another render pass is started before the previous one is completed, the result of the previous render pass is ignored.
|
|
385
|
+
* @param pathnameOrContext — the pathname to render or a context object with a pathname property and other properties to pass to the resolver.
|
|
386
|
+
* @param shouldUpdateHistory
|
|
387
|
+
*/
|
|
388
|
+
/**
|
|
389
|
+
* Asynchronously resolves the given pathname and renders the resolved route
|
|
390
|
+
* component into the router outlet. If no router outlet is set at the time of
|
|
391
|
+
* calling this method, or at the time when the route resolution is completed,
|
|
392
|
+
* a `TypeError` is thrown.
|
|
393
|
+
*
|
|
394
|
+
* Returns a promise that is fulfilled with the router outlet DOM Node after
|
|
395
|
+
* the route component is created and inserted into the router outlet, or
|
|
396
|
+
* rejected if no route matches the given path.
|
|
397
|
+
*
|
|
398
|
+
* If another render pass is started before the previous one is completed, the
|
|
399
|
+
* result of the previous render pass is ignored.
|
|
400
|
+
*
|
|
401
|
+
* @param pathnameOrContext
|
|
402
|
+
* the pathname to render or a context object with a `pathname` property,
|
|
403
|
+
* optional `search` and `hash` properties, and other properties
|
|
404
|
+
* to pass to the resolver.
|
|
405
|
+
* @param shouldUpdateHistory
|
|
406
|
+
* update browser history with the rendered location
|
|
407
|
+
* @return
|
|
408
|
+
*/
|
|
409
|
+
render(pathnameOrContext, shouldUpdateHistory) {
|
|
410
|
+
const renderId = ++this.__lastStartedRenderId;
|
|
411
|
+
const context = Object.assign({
|
|
412
|
+
search: '',
|
|
413
|
+
hash: '',
|
|
414
|
+
}, (0, utils_1.isString)(pathnameOrContext) ? { pathname: pathnameOrContext } : pathnameOrContext, {
|
|
415
|
+
__renderId: renderId,
|
|
416
|
+
});
|
|
417
|
+
this.ready = this.resolve(context)
|
|
418
|
+
.then((context) => this.__fullyResolveChain(context))
|
|
419
|
+
.then((context) => {
|
|
420
|
+
if (this.__isLatestRender(context)) {
|
|
421
|
+
const previousContext = this.__previousContext;
|
|
422
|
+
if (context === previousContext) {
|
|
423
|
+
this.__updateBrowserHistory(previousContext, true);
|
|
424
|
+
return this.location;
|
|
425
|
+
}
|
|
426
|
+
this.location = createLocation(context);
|
|
427
|
+
if (shouldUpdateHistory) {
|
|
428
|
+
this.__updateBrowserHistory(context, renderId === 1);
|
|
429
|
+
}
|
|
430
|
+
(0, utils_1.fireRouterEvent)('location-changed', { location: this.location });
|
|
431
|
+
if (context.__skipAttach) {
|
|
432
|
+
this.__copyUnchangedElements(context, previousContext);
|
|
433
|
+
this.__previousContext = context;
|
|
434
|
+
return this.location;
|
|
435
|
+
}
|
|
436
|
+
this.__addAppearingContent(context, previousContext);
|
|
437
|
+
const animationDone = this.__animateIfNeeded(context);
|
|
438
|
+
this.__runOnAfterEnterCallbacks(context);
|
|
439
|
+
this.__runOnAfterLeaveCallbacks(context, previousContext);
|
|
440
|
+
return animationDone.then(() => {
|
|
441
|
+
if (this.__isLatestRender(context)) {
|
|
442
|
+
this.__removeDisappearingContent();
|
|
443
|
+
this.__previousContext = context;
|
|
444
|
+
return this.location;
|
|
445
|
+
}
|
|
446
|
+
return undefined;
|
|
447
|
+
});
|
|
448
|
+
}
|
|
449
|
+
return undefined;
|
|
450
|
+
})
|
|
451
|
+
.catch((error) => {
|
|
452
|
+
if (renderId === this.__lastStartedRenderId) {
|
|
453
|
+
if (shouldUpdateHistory) {
|
|
454
|
+
this.__updateBrowserHistory(context);
|
|
455
|
+
}
|
|
456
|
+
removeDomNodes(this.__outlet && this.__outlet.children);
|
|
457
|
+
this.location = createLocation(Object.assign(context, { resolver: this }));
|
|
458
|
+
(0, utils_1.fireRouterEvent)('error', Object.assign({ router: this, error }, context));
|
|
459
|
+
throw error;
|
|
460
|
+
}
|
|
461
|
+
return undefined;
|
|
462
|
+
});
|
|
463
|
+
return this.ready;
|
|
464
|
+
}
|
|
465
|
+
__fullyResolveChain(topOfTheChainContextBeforeRedirects, contextBeforeRedirects = topOfTheChainContextBeforeRedirects) {
|
|
466
|
+
return this.__findComponentContextAfterAllRedirects(contextBeforeRedirects).then((contextAfterRedirects) => {
|
|
467
|
+
const redirectsHappened = contextAfterRedirects !== contextBeforeRedirects;
|
|
468
|
+
const topOfTheChainContextAfterRedirects = redirectsHappened
|
|
469
|
+
? contextAfterRedirects
|
|
470
|
+
: topOfTheChainContextBeforeRedirects;
|
|
471
|
+
const matchedPath = getPathnameForRouter(getMatchedPath(contextAfterRedirects.chain), contextAfterRedirects.resolver);
|
|
472
|
+
const isFound = matchedPath === contextAfterRedirects.pathname;
|
|
473
|
+
const findNextContextIfAny = (context, parent = context.route, prevResult) => {
|
|
474
|
+
return context
|
|
475
|
+
.next(undefined, parent, prevResult)
|
|
476
|
+
.then((nextContext) => {
|
|
477
|
+
if (nextContext === null || nextContext === types_1.notFoundResult) {
|
|
478
|
+
if (isFound) {
|
|
479
|
+
return context;
|
|
480
|
+
}
|
|
481
|
+
else if (parent.parent !== null) {
|
|
482
|
+
return findNextContextIfAny(context, parent.parent, nextContext);
|
|
483
|
+
}
|
|
484
|
+
else {
|
|
485
|
+
return nextContext;
|
|
486
|
+
}
|
|
487
|
+
}
|
|
488
|
+
return nextContext;
|
|
489
|
+
});
|
|
490
|
+
};
|
|
491
|
+
return findNextContextIfAny(contextAfterRedirects).then((nextContext) => {
|
|
492
|
+
if (nextContext === null || nextContext === types_1.notFoundResult) {
|
|
493
|
+
throw (0, utils_1.getNotFoundError)(topOfTheChainContextAfterRedirects);
|
|
494
|
+
}
|
|
495
|
+
return nextContext && nextContext !== types_1.notFoundResult && nextContext !== contextAfterRedirects
|
|
496
|
+
? this.__fullyResolveChain(topOfTheChainContextAfterRedirects, nextContext)
|
|
497
|
+
: this.__amendWithOnBeforeCallbacks(contextAfterRedirects);
|
|
498
|
+
});
|
|
499
|
+
});
|
|
500
|
+
}
|
|
501
|
+
__findComponentContextAfterAllRedirects(context) {
|
|
502
|
+
const result = context.result;
|
|
503
|
+
if (result instanceof HTMLElement) {
|
|
504
|
+
renderElement(context, result);
|
|
505
|
+
return Promise.resolve(context);
|
|
506
|
+
}
|
|
507
|
+
else if (result && result.redirect) {
|
|
508
|
+
return this.__redirect(result.redirect, context.__redirectCount, context.__renderId).then((context) => this.__findComponentContextAfterAllRedirects(context));
|
|
509
|
+
}
|
|
510
|
+
else if (result instanceof Error) {
|
|
511
|
+
return Promise.reject(result);
|
|
512
|
+
}
|
|
513
|
+
else {
|
|
514
|
+
return Promise.reject(new Error((0, utils_1.log)(`Invalid route resolution result for path "${context.pathname}". ` +
|
|
515
|
+
`Expected redirect object or HTML element, but got: "${(0, utils_1.logValue)(result)}". ` +
|
|
516
|
+
`Double check the action return value for the route.`)));
|
|
517
|
+
}
|
|
518
|
+
}
|
|
519
|
+
__amendWithOnBeforeCallbacks(contextWithFullChain) {
|
|
520
|
+
return this.__runOnBeforeCallbacks(contextWithFullChain).then((amendedContext) => {
|
|
521
|
+
if (amendedContext === this.__previousContext || amendedContext === contextWithFullChain) {
|
|
522
|
+
return amendedContext;
|
|
523
|
+
}
|
|
524
|
+
return this.__fullyResolveChain(amendedContext);
|
|
525
|
+
});
|
|
526
|
+
}
|
|
527
|
+
__runOnBeforeCallbacks(newContext) {
|
|
528
|
+
const previousContext = this.__previousContext || {};
|
|
529
|
+
const previousChain = previousContext.chain || [];
|
|
530
|
+
const newChain = newContext.chain;
|
|
531
|
+
let callbacks = Promise.resolve();
|
|
532
|
+
const prevent = () => ({ cancel: true });
|
|
533
|
+
const redirect = (pathname) => createRedirect(newContext, pathname);
|
|
534
|
+
newContext.__divergedChainIndex = 0;
|
|
535
|
+
newContext.__skipAttach = false;
|
|
536
|
+
if (previousChain.length) {
|
|
537
|
+
for (let i = 0; i < Math.min(previousChain.length, newChain.length); i = ++newContext.__divergedChainIndex) {
|
|
538
|
+
if (previousChain[i].route !== newChain[i].route ||
|
|
539
|
+
(previousChain[i].path !== newChain[i].path && previousChain[i].element !== newChain[i].element) ||
|
|
540
|
+
!this.__isReusableElement(previousChain[i].element, newChain[i].element)) {
|
|
541
|
+
break;
|
|
542
|
+
}
|
|
543
|
+
}
|
|
544
|
+
newContext.__skipAttach =
|
|
545
|
+
newChain.length === previousChain.length &&
|
|
546
|
+
newContext.__divergedChainIndex == newChain.length &&
|
|
547
|
+
this.__isReusableElement(newContext.result, previousContext.result);
|
|
548
|
+
if (newContext.__skipAttach) {
|
|
549
|
+
for (let i = newChain.length - 1; i >= 0; i--) {
|
|
550
|
+
callbacks = this.__runOnBeforeLeaveCallbacks(callbacks, newContext, { prevent }, previousChain[i]);
|
|
551
|
+
}
|
|
552
|
+
for (let i = 0; i < newChain.length; i++) {
|
|
553
|
+
callbacks = this.__runOnBeforeEnterCallbacks(callbacks, newContext, { prevent, redirect }, newChain[i]);
|
|
554
|
+
previousChain[i].element.location = createLocation(newContext, previousChain[i].route);
|
|
555
|
+
}
|
|
556
|
+
}
|
|
557
|
+
else {
|
|
558
|
+
for (let i = previousChain.length - 1; i >= newContext.__divergedChainIndex; i--) {
|
|
559
|
+
callbacks = this.__runOnBeforeLeaveCallbacks(callbacks, newContext, { prevent }, previousChain[i]);
|
|
560
|
+
}
|
|
561
|
+
}
|
|
562
|
+
}
|
|
563
|
+
if (!newContext.__skipAttach) {
|
|
564
|
+
for (let i = 0; i < newChain.length; i++) {
|
|
565
|
+
if (i < newContext.__divergedChainIndex) {
|
|
566
|
+
if (i < previousChain.length && previousChain[i].element) {
|
|
567
|
+
previousChain[i].element.location = createLocation(newContext, previousChain[i].route);
|
|
568
|
+
}
|
|
569
|
+
}
|
|
570
|
+
else {
|
|
571
|
+
callbacks = this.__runOnBeforeEnterCallbacks(callbacks, newContext, { prevent, redirect }, newChain[i]);
|
|
572
|
+
if (newChain[i].element) {
|
|
573
|
+
newChain[i].element.location = createLocation(newContext, newChain[i].route);
|
|
574
|
+
}
|
|
575
|
+
}
|
|
576
|
+
}
|
|
577
|
+
}
|
|
578
|
+
return callbacks.then((amendmentResult) => {
|
|
579
|
+
if (amendmentResult) {
|
|
580
|
+
if (amendmentResult.cancel) {
|
|
581
|
+
this.__previousContext.__renderId = newContext.__renderId;
|
|
582
|
+
return this.__previousContext;
|
|
583
|
+
}
|
|
584
|
+
if (amendmentResult.redirect) {
|
|
585
|
+
return this.__redirect(amendmentResult.redirect, newContext.__redirectCount, newContext.__renderId);
|
|
586
|
+
}
|
|
587
|
+
}
|
|
588
|
+
return newContext;
|
|
589
|
+
});
|
|
590
|
+
}
|
|
591
|
+
__runOnBeforeLeaveCallbacks(callbacks, newContext, commands, chainElement) {
|
|
592
|
+
const location = createLocation(newContext);
|
|
593
|
+
return callbacks
|
|
594
|
+
.then((result) => {
|
|
595
|
+
if (this.__isLatestRender(newContext)) {
|
|
596
|
+
const afterLeaveFunction = amend('onBeforeLeave', [location, commands, this], chainElement.element);
|
|
597
|
+
return afterLeaveFunction(result);
|
|
598
|
+
}
|
|
599
|
+
return undefined;
|
|
600
|
+
})
|
|
601
|
+
.then((result) => {
|
|
602
|
+
if (!(result || {}).redirect) {
|
|
603
|
+
return result;
|
|
604
|
+
}
|
|
605
|
+
return undefined;
|
|
606
|
+
});
|
|
607
|
+
}
|
|
608
|
+
__runOnBeforeEnterCallbacks(callbacks, newContext, commands, chainElement) {
|
|
609
|
+
const location = createLocation(newContext, chainElement.route);
|
|
610
|
+
return callbacks.then((result) => {
|
|
611
|
+
if (this.__isLatestRender(newContext)) {
|
|
612
|
+
const beforeEnterFunction = amend('onBeforeEnter', [location, commands, this], chainElement.element);
|
|
613
|
+
return beforeEnterFunction(result);
|
|
614
|
+
}
|
|
615
|
+
return undefined;
|
|
616
|
+
});
|
|
617
|
+
}
|
|
618
|
+
__isReusableElement(element, otherElement) {
|
|
619
|
+
if (element && otherElement) {
|
|
620
|
+
return this.__createdByRouter.get(element) && this.__createdByRouter.get(otherElement)
|
|
621
|
+
? element.localName === otherElement.localName
|
|
622
|
+
: element === otherElement;
|
|
623
|
+
}
|
|
624
|
+
return false;
|
|
625
|
+
}
|
|
626
|
+
__isLatestRender(context) {
|
|
627
|
+
return context.__renderId === this.__lastStartedRenderId;
|
|
628
|
+
}
|
|
629
|
+
__redirect(redirectData, counter, renderId) {
|
|
630
|
+
if ((counter || 0) > MAX_REDIRECT_COUNT) {
|
|
631
|
+
throw new Error((0, utils_1.log)(`Too many redirects when rendering ${redirectData.from}`));
|
|
632
|
+
}
|
|
633
|
+
return this.resolve({
|
|
634
|
+
pathname: this.urlForPath(redirectData.pathname, redirectData.params),
|
|
635
|
+
redirectFrom: redirectData.from,
|
|
636
|
+
__redirectCount: (counter || 0) + 1,
|
|
637
|
+
__renderId: renderId,
|
|
638
|
+
});
|
|
639
|
+
}
|
|
640
|
+
__ensureOutlet(outlet = this.__outlet) {
|
|
641
|
+
if (!(outlet instanceof Node)) {
|
|
642
|
+
throw new TypeError((0, utils_1.log)(`Expected router outlet to be a valid DOM Node (but got ${outlet})`));
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
__updateBrowserHistory({ pathname, search = '', hash = '' }, replace) {
|
|
646
|
+
if (window.location.pathname !== pathname || window.location.search !== search || window.location.hash !== hash) {
|
|
647
|
+
const changeState = replace ? 'replaceState' : 'pushState';
|
|
648
|
+
window.history[changeState](null, document.title, pathname + search + hash);
|
|
649
|
+
window.dispatchEvent(new PopStateEvent('popstate', { state: 'router-ignore' }));
|
|
650
|
+
}
|
|
651
|
+
}
|
|
652
|
+
__copyUnchangedElements(context, previousContext) {
|
|
653
|
+
let deepestCommonParent = this.__outlet;
|
|
654
|
+
for (let i = 0; i < context.__divergedChainIndex; i++) {
|
|
655
|
+
const unchangedElement = previousContext && previousContext.chain[i].element;
|
|
656
|
+
if (unchangedElement) {
|
|
657
|
+
if (unchangedElement.parentNode === deepestCommonParent) {
|
|
658
|
+
context.chain[i].element = unchangedElement;
|
|
659
|
+
deepestCommonParent = unchangedElement;
|
|
660
|
+
}
|
|
661
|
+
else {
|
|
662
|
+
break;
|
|
663
|
+
}
|
|
664
|
+
}
|
|
665
|
+
}
|
|
666
|
+
return deepestCommonParent;
|
|
667
|
+
}
|
|
668
|
+
__addAppearingContent(context, previousContext) {
|
|
669
|
+
this.__ensureOutlet();
|
|
670
|
+
this.__removeAppearingContent();
|
|
671
|
+
const deepestCommonParent = this.__copyUnchangedElements(context, previousContext);
|
|
672
|
+
this.__appearingContent = [];
|
|
673
|
+
this.__disappearingContent = Array.from(deepestCommonParent.children).filter((e) => this.__addedByRouter.get(e) && e !== context.result);
|
|
674
|
+
let parentElement = deepestCommonParent;
|
|
675
|
+
for (let i = context.__divergedChainIndex; i < context.chain.length; i++) {
|
|
676
|
+
const elementToAdd = context.chain[i].element;
|
|
677
|
+
if (elementToAdd) {
|
|
678
|
+
parentElement.appendChild(elementToAdd);
|
|
679
|
+
this.__addedByRouter.set(elementToAdd, true);
|
|
680
|
+
if (parentElement === deepestCommonParent) {
|
|
681
|
+
this.__appearingContent.push(elementToAdd);
|
|
682
|
+
}
|
|
683
|
+
parentElement = elementToAdd;
|
|
684
|
+
}
|
|
685
|
+
}
|
|
686
|
+
}
|
|
687
|
+
__removeDisappearingContent() {
|
|
688
|
+
if (this.__disappearingContent) {
|
|
689
|
+
removeDomNodes(this.__disappearingContent);
|
|
690
|
+
}
|
|
691
|
+
this.__disappearingContent = null;
|
|
692
|
+
this.__appearingContent = null;
|
|
693
|
+
}
|
|
694
|
+
__removeAppearingContent() {
|
|
695
|
+
if (this.__disappearingContent && this.__appearingContent) {
|
|
696
|
+
removeDomNodes(this.__appearingContent);
|
|
697
|
+
this.__disappearingContent = null;
|
|
698
|
+
this.__appearingContent = null;
|
|
699
|
+
}
|
|
700
|
+
}
|
|
701
|
+
__runOnAfterLeaveCallbacks(currentContext, targetContext) {
|
|
702
|
+
if (!targetContext) {
|
|
703
|
+
return;
|
|
704
|
+
}
|
|
705
|
+
for (let i = targetContext.chain.length - 1; i >= currentContext.__divergedChainIndex; i--) {
|
|
706
|
+
if (!this.__isLatestRender(currentContext)) {
|
|
707
|
+
break;
|
|
708
|
+
}
|
|
709
|
+
const currentComponent = targetContext.chain[i].element;
|
|
710
|
+
if (!currentComponent) {
|
|
711
|
+
continue;
|
|
712
|
+
}
|
|
713
|
+
try {
|
|
714
|
+
const location = createLocation(currentContext);
|
|
715
|
+
(0, utils_1.runCallbackIfPossible)(currentComponent.onAfterLeave, [location, {}, targetContext.resolver], currentComponent);
|
|
716
|
+
}
|
|
717
|
+
finally {
|
|
718
|
+
if (this.__disappearingContent.indexOf(currentComponent) > -1) {
|
|
719
|
+
removeDomNodes(currentComponent.children);
|
|
720
|
+
}
|
|
721
|
+
}
|
|
722
|
+
}
|
|
723
|
+
}
|
|
724
|
+
__runOnAfterEnterCallbacks(currentContext) {
|
|
725
|
+
for (let i = currentContext.__divergedChainIndex; i < currentContext.chain.length; i++) {
|
|
726
|
+
if (!this.__isLatestRender(currentContext)) {
|
|
727
|
+
break;
|
|
728
|
+
}
|
|
729
|
+
const currentComponent = currentContext.chain[i].element || {};
|
|
730
|
+
const location = createLocation(currentContext, currentContext.chain[i].route);
|
|
731
|
+
(0, utils_1.runCallbackIfPossible)(currentComponent.onAfterEnter, [location, {}, currentContext.resolver], currentComponent);
|
|
732
|
+
}
|
|
733
|
+
}
|
|
734
|
+
__animateIfNeeded(context) {
|
|
735
|
+
const from = (this.__disappearingContent || [])[0];
|
|
736
|
+
const to = (this.__appearingContent || [])[0];
|
|
737
|
+
const promises = [];
|
|
738
|
+
const chain = context.chain;
|
|
739
|
+
let config;
|
|
740
|
+
for (let i = chain.length; i > 0; i--) {
|
|
741
|
+
if (chain[i - 1].route.animate) {
|
|
742
|
+
config = chain[i - 1].route.animate;
|
|
743
|
+
break;
|
|
744
|
+
}
|
|
745
|
+
}
|
|
746
|
+
if (from && to && config) {
|
|
747
|
+
const leave = ((0, utils_1.isObject)(config) && config.leave) || 'leaving';
|
|
748
|
+
const enter = ((0, utils_1.isObject)(config) && config.enter) || 'entering';
|
|
749
|
+
promises.push(animate(from, leave));
|
|
750
|
+
promises.push(animate(to, enter));
|
|
751
|
+
}
|
|
752
|
+
return Promise.all(promises).then(() => context);
|
|
753
|
+
}
|
|
754
|
+
/**
|
|
755
|
+
* Subscribes this instance to navigation events on the `window`.
|
|
756
|
+
*
|
|
757
|
+
* NOTE: beware of resource leaks. For as long as a router instance is
|
|
758
|
+
* subscribed to navigation events, it won't be garbage collected.
|
|
759
|
+
*/
|
|
760
|
+
subscribe() {
|
|
761
|
+
window.addEventListener('router-go', this.__navigationEventHandler);
|
|
762
|
+
}
|
|
763
|
+
/**
|
|
764
|
+
* Removes the subscription to navigation events created in the `subscribe()`
|
|
765
|
+
* method.
|
|
766
|
+
*/
|
|
767
|
+
unsubscribe() {
|
|
768
|
+
window.removeEventListener('router-go', this.__navigationEventHandler);
|
|
769
|
+
}
|
|
770
|
+
__onNavigationEvent(event) {
|
|
771
|
+
const { pathname, search, hash } = event ? event.detail : window.location;
|
|
772
|
+
if ((0, utils_1.isString)(this.__normalizePathname(pathname))) {
|
|
773
|
+
if (event && event.preventDefault) {
|
|
774
|
+
event.preventDefault();
|
|
775
|
+
}
|
|
776
|
+
this.render({ pathname, search, hash }, true);
|
|
777
|
+
}
|
|
778
|
+
}
|
|
779
|
+
/**
|
|
780
|
+
* Generates a URL for the route with the given name, optionally performing
|
|
781
|
+
* substitution of parameters.
|
|
782
|
+
*
|
|
783
|
+
* The route is searched in all the Router instances subscribed to
|
|
784
|
+
* navigation events.
|
|
785
|
+
*
|
|
786
|
+
* **Note:** For child route names, only array children are considered.
|
|
787
|
+
* It is not possible to generate URLs using a name for routes set with
|
|
788
|
+
* a children function.
|
|
789
|
+
*
|
|
790
|
+
* @param name the route name or the route’s `component` name.
|
|
791
|
+
* @param params Optional object with route path parameters.
|
|
792
|
+
* Named parameters are passed by name (`params[name] = value`), unnamed
|
|
793
|
+
* parameters are passed by index (`params[index] = value`).
|
|
794
|
+
*
|
|
795
|
+
* @return
|
|
796
|
+
*/
|
|
797
|
+
urlForName(name, params) {
|
|
798
|
+
if (!this.__urlForName) {
|
|
799
|
+
this.__urlForName = (0, resolver_1.generateUrls)(this);
|
|
800
|
+
}
|
|
801
|
+
return getPathnameForRouter(this.__urlForName(name, params), this);
|
|
802
|
+
}
|
|
803
|
+
/**
|
|
804
|
+
* Generates a URL for the given route path, optionally performing
|
|
805
|
+
* substitution of parameters.
|
|
806
|
+
*
|
|
807
|
+
* @param path string route path declared in [express.js syntax](https://expressjs.com/en/guide/routing.html#route-paths").
|
|
808
|
+
* @param params Optional object with route path parameters.
|
|
809
|
+
* Named parameters are passed by name (`params[name] = value`), unnamed
|
|
810
|
+
* parameters are passed by index (`params[index] = value`).
|
|
811
|
+
*
|
|
812
|
+
* @return
|
|
813
|
+
*/
|
|
814
|
+
urlForPath(path, params) {
|
|
815
|
+
return getPathnameForRouter((0, path_to_regexp_1.compile)(path)(params), this);
|
|
816
|
+
}
|
|
817
|
+
/**
|
|
818
|
+
* Triggers navigation to a new path. Returns a boolean without waiting until
|
|
819
|
+
* the navigation is complete. Returns `true` if at least one `Router`
|
|
820
|
+
* has handled the navigation (was subscribed and had `baseUrl` matching
|
|
821
|
+
* the `path` argument), otherwise returns `false`.
|
|
822
|
+
*
|
|
823
|
+
* @param path
|
|
824
|
+
* a new in-app path string, or an URL-like object with `pathname`
|
|
825
|
+
* string property, and optional `search` and `hash` string properties.
|
|
826
|
+
* @return
|
|
827
|
+
*/
|
|
828
|
+
static go(path) {
|
|
829
|
+
const { pathname, search, hash } = (0, utils_1.isString)(path) ? this.__createUrl(path, 'http://a') : path;
|
|
830
|
+
return (0, utils_1.fireRouterEvent)('go', { pathname, search: search || '', hash: hash || '' });
|
|
831
|
+
}
|
|
832
|
+
}
|
|
833
|
+
exports.Router = Router;
|