Huge News!Announcing our $40M Series B led by Abstract Ventures.Learn More
Socket
Sign inDemoInstall
Socket

@vaadin/router

Package Overview
Dependencies
Maintainers
9
Versions
36
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@vaadin/router - npm Package Compare versions

Comparing version 0.4.0 to 1.0.0-rc.0

src/documentation/location.js

482

dist/vaadin-router.js

@@ -10,2 +10,14 @@ function toArray(objectOrArray) {

const MODULE = 'module';
const NOMODULE = 'nomodule';
const bundleKeys = [MODULE, NOMODULE];
function ensureBundle(src) {
if (!src.match(/.+\.[m]?js$/)) {
throw new Error(
log(`Unsupported type for bundle "${src}": .js or .mjs expected.`)
);
}
}
function ensureRoute(route) {

@@ -18,2 +30,4 @@ if (!route || !isString(route.path)) {

const bundle = route.bundle;
const stringKeys = ['component', 'redirect', 'bundle'];

@@ -24,3 +38,3 @@ if (

!isFunction(route.children) &&
!isObject(route.bundle) &&
!isObject(bundle) &&
!stringKeys.some(key => isString(route[key]))

@@ -36,8 +50,11 @@ ) {

if (route.bundle) {
const src = isString(route.bundle) ? route.bundle : route.bundle.src;
if (!src.match(/.+\.[m]?js$/)) {
if (bundle) {
if (isString(bundle)) {
ensureBundle(bundle);
} else if (!bundleKeys.some(key => key in bundle)) {
throw new Error(
log(`Unsupported type for bundle "${src}": .js or .mjs expected.`)
log('Expected route bundle to include either "' + NOMODULE + '" or "' + MODULE + '" keys, or both')
);
} else {
bundleKeys.forEach(key => key in bundle && ensureBundle(bundle[key]));
}

@@ -64,31 +81,15 @@ }

function loadBundle(bundle) {
const path = isString(bundle) ? bundle : bundle.src;
let script = document.head.querySelector('script[src="' + path + '"][async]');
if (script && script.parentNode === document.head) {
if (script.__dynamicImportLoaded) {
return Promise.resolve();
} else {
return new Promise((resolve, reject) => {
const originalOnLoad = script.onload;
script.onreadystatechange = script.onload = e => {
originalOnLoad();
resolve(e);
};
const originalOnError = script.onerror;
script.onerror = e => {
originalOnError();
reject(e);
};
});
function loadScript(src, key) {
let script = document.head.querySelector('script[src="' + src + '"][async]');
if (!script) {
script = document.createElement('script');
script.setAttribute('src', src);
if (key === MODULE) {
script.setAttribute('type', MODULE);
} else if (key === NOMODULE) {
script.setAttribute(NOMODULE, '');
}
script.async = true;
}
return new Promise((resolve, reject) => {
script = document.createElement('script');
script.setAttribute('src', path);
if (isObject(bundle) && bundle.type === 'module') {
script.setAttribute('type', 'module');
}
script.async = true;
script.onreadystatechange = script.onload = e => {

@@ -104,6 +105,22 @@ script.__dynamicImportLoaded = true;

};
document.head.appendChild(script);
if (script.parentNode === null) {
document.head.appendChild(script);
} else if (script.__dynamicImportLoaded) {
resolve();
}
});
}
function loadBundle(bundle) {
if (isString(bundle)) {
return loadScript(bundle);
} else {
return Promise.race(
bundleKeys
.filter(key => key in bundle)
.map(key => loadScript(bundle[key], key))
);
}
}
function fireRouterEvent(type, detail) {

@@ -116,3 +133,4 @@ window.dispatchEvent(

function isObject(o) {
return typeof o === 'object';
// guard against null passing the typeof check
return typeof o === 'object' && !!o;
}

@@ -128,2 +146,9 @@

function getNotFoundError(context) {
const error = new Error(log(`Page not found (${context.pathname})`));
error.context = context;
error.code = 404;
return error;
}
/* istanbul ignore next: coverage is calculated in Chrome, this code is for IE */

@@ -802,2 +827,3 @@ function getAnchorOrigin(anchor) {

params: match.params,
path: match.path
},

@@ -891,12 +917,14 @@ };

function addRouteToChain(context, newRoute) {
function shouldDiscardOldChain(oldChain, newRoute) {
return !newRoute.parent || !oldChain || !oldChain.length || oldChain[oldChain.length - 1] !== newRoute.parent;
function addRouteToChain(context, match) {
const {route, path} = match;
function shouldDiscardOldChain(oldChain, route) {
return !route.parent || !oldChain || !oldChain.length || oldChain[oldChain.length - 1].route !== route.parent;
}
if (newRoute && !newRoute.__synthetic) {
if (shouldDiscardOldChain(context.chain, newRoute)) {
context.chain = [newRoute];
if (route && !route.__synthetic) {
const item = {path, route};
if (shouldDiscardOldChain(context.chain, route)) {
context.chain = [item];
} else {
context.chain.push(newRoute);
context.chain.push(item);
}

@@ -1013,9 +1041,6 @@ }

if (matches.done) {
const error = new Error(`Page not found (${context.pathname})`);
error.context = context;
error.code = 404;
return Promise.reject(error);
return Promise.reject(getNotFoundError(context));
}
addRouteToChain(context, matches.value.route);
addRouteToChain(context, matches.value);
currentContext = Object.assign({}, context, matches.value);

@@ -1116,3 +1141,19 @@

function redirect(context, pathname) {
function copyContextWithoutNext(context) {
const copy = Object.assign({}, context);
delete copy.next;
return copy;
}
function createLocation({pathname = '', chain = [], params = {}, redirectFrom}, route) {
return {
pathname,
routes: chain.map(item => item.route),
route: (!route && chain.length && chain[chain.length - 1].route) || route,
params,
redirectFrom,
};
}
function createRedirect(context, pathname) {
const params = Object.assign({}, context.params);

@@ -1129,19 +1170,16 @@ return {

function renderComponent(context, component) {
const element = context.route.__component || document.createElement(component);
const params = Object.assign({}, context.params);
element.route = {params, pathname: context.pathname};
if (context.from) {
element.route.redirectFrom = context.from;
}
context.route.__component = element;
const element = document.createElement(component);
element.location = createLocation(context);
const index = context.chain.map(item => item.route).indexOf(context.route);
context.chain[index].element = element;
return element;
}
function runCallbackIfPossible(callback, context, thisObject) {
function runCallbackIfPossible(callback, args, thisArg) {
if (isFunction(callback)) {
return callback.call(thisObject, context);
return callback.apply(thisArg, args);
}
}
function amend(amendmentFunction, context, route) {
function amend(amendmentFunction, args, element) {
return amendmentResult => {

@@ -1152,6 +1190,4 @@ if (amendmentResult && (amendmentResult.cancel || amendmentResult.redirect)) {

const component = route.__component;
if (component) {
return runCallbackIfPossible(component[amendmentFunction],
Object.assign({cancel: () => ({cancel: true})}, context, {next: undefined}), component);
if (element) {
return runCallbackIfPossible(element[amendmentFunction], args, element);
}

@@ -1161,6 +1197,9 @@ };

function processNewChildren(newChildren, route, context) {
if (isResultNotEmpty(newChildren) && !isObject(newChildren)) {
throw new Error(log(`Expected 'children' method of the route with path '${route.path}' `
+ `to return an object, but got: '${newChildren}'`));
function processNewChildren(newChildren, route) {
if (!Array.isArray(newChildren) && !isObject(newChildren)) {
throw new Error(
log(
`Incorrect "children" value for the route ${route.path}: expected array or object, but got ${newChildren}`
)
);
}

@@ -1176,8 +1215,20 @@

function processComponent(route, context) {
if (isString(route.component)) {
return renderComponent(context, route.component);
function removeDomNodes(nodes) {
if (nodes && nodes.length) {
const parent = nodes[0].parentNode;
for (let i = 0; i < nodes.length; i++) {
parent.removeChild(nodes[i]);
}
}
}
function getMatchedPath(chain) {
return chain.map(item => item.path).reduce((prev, path) => {
if (path.length) {
return prev === '/' ? prev + path : prev + '/' + path;
}
return prev;
});
}
/**

@@ -1235,3 +1286,3 @@ * A simple client-side router for single-page applications. It uses

* @public
* @type {!Promise<?Node>}
* @type {!Promise<!Vaadin.Router.Location>}
*/

@@ -1242,12 +1293,12 @@ this.ready;

/**
* A read-only list of the currently active routes (starting from the root
* down to a leaf of the routes config tree). The list is initially empty
* and gets updated after each _completed_ render call. When a render fails
* the `activeRoutes` is set to an empty list.
* Contains read-only information about the current router location:
* pathname, active routes, parameters. See the
* [Location type declaration](#/classes/Vaadin.Router.Location)
* for more details.
*
* @public
* @type {!Array<Route>}
* @type {!Vaadin.Router.Location}
*/
this.activeRoutes;
this.activeRoutes = [];
this.location;
this.location = createLocation({});

@@ -1263,7 +1314,7 @@ this.__lastStartedRenderId = 0;

const updatedContext = Object.assign({
redirect: path => redirect(context, path),
const commands = {
redirect: path => createRedirect(context, path),
component: component => renderComponent(context, component)
}, context);
const actionResult = runCallbackIfPossible(resolveRoute, updatedContext, route);
};
const actionResult = runCallbackIfPossible(route.action, [context, commands], route);
if (isResultNotEmpty(actionResult)) {

@@ -1274,3 +1325,3 @@ return actionResult;

if (isString(route.redirect)) {
return redirect(context, route.redirect);
return commands.redirect(route.redirect);
}

@@ -1289,3 +1340,3 @@

callbacks = callbacks
.then(() => route.children(Object.assign({}, context, {next: undefined})))
.then(() => route.children(copyContextWithoutNext(context)))
.then(children => {

@@ -1297,7 +1348,11 @@ // The route.children() callback might have re-written the

}
processNewChildren(children, route, context);
processNewChildren(children, route);
});
}
return callbacks.then(() => processComponent(route, context));
return callbacks.then(() => {
if (isString(route.component)) {
return commands.component(route.component);
}
});
}

@@ -1350,3 +1405,6 @@

*
* * `bundle` – `.js` or `.mjs` bundle to load before resolving the route. Each bundle is only loaded once.
* * `bundle` – string containing the path to `.js` or `.mjs` bundle to load before resolving the route,
* or the object with "module" and "nomodule" keys referring to different bundles.
* Each bundle is only loaded once. If "module" and "nomodule" are set, only one bundle is loaded,
* depending on whether the browser supports ES modules or not.
* The property is ignored when either an `action` returns the result or `redirect` property is present.

@@ -1418,41 +1476,55 @@ * Any error, e.g. 404 while loading bundle will cause route resolution to throw.

const renderId = ++this.__lastStartedRenderId;
const pathname = pathnameOrContext.pathname || pathnameOrContext;
// Find the first route that resolves to a non-empty result
this.ready = this.resolve(pathnameOrContext)
.then(originalContext => this.__fullyResolveChain(originalContext, originalContext))
// Process the result of this.resolve() and handle all special commands:
// (redirect / prevent / component). If the result is a 'component',
// then go deeper and build the entire chain of nested components matching
// the pathname. Also call all 'on before' callbacks along the way.
.then(context => this.__fullyResolveChain(context))
.then(context => {
if (renderId === this.__lastStartedRenderId) {
const previousContext = this.__previousContext;
// Check if the render was prevented and make an early return in that case
if (context === previousContext) {
return this.location;
}
if (shouldUpdateHistory) {
this.__updateBrowserHistory(context.result.route.pathname, context.from);
this.__updateBrowserHistory(context.pathname, context.redirectFrom);
}
if (context !== this.__previousContext) {
return this.__runOnAfterCallbacks(context, this.__previousContext, 'onAfterLeave')
.then(() => this.__setOutletContent(context))
.then(() => this.__runOnAfterCallbacks(context, context, 'onAfterEnter'))
.then(() => context);
}
return Promise.resolve(context);
this.__addAppearingContent(context, previousContext);
const animationDone = this.__animateIfNeeded(context);
this.__runOnAfterEnterCallbacks(context);
this.__runOnAfterLeaveCallbacks(context, previousContext);
return animationDone.then(() => {
if (renderId === this.__lastStartedRenderId) {
// If there is another render pass started after this one,
// the 'disappearing content' would be removed when the other
// render pass calls `this.__addAppearingContent()`
this.__removeDisappearingContent();
this.__previousContext = context;
this.location = createLocation(context);
fireRouterEvent('location-changed', {router: this, location: this.location});
return this.location;
}
});
}
})
.then(context => {
if (renderId === this.__lastStartedRenderId) {
return this.__animateIfNeeded(context);
}
})
.then(context => {
if (renderId === this.__lastStartedRenderId) {
this.__removeOldOutletContent();
}
this.__previousContext = context;
this.activeRoutes = [...context.chain];
fireRouterEvent('route-changed', {router: this, params: context.params, pathname: context.pathname});
return this.__outlet;
})
.catch(error => {
if (renderId === this.__lastStartedRenderId) {
if (shouldUpdateHistory) {
this.__updateBrowserHistory(pathnameOrContext);
this.__updateBrowserHistory(pathname);
}
this.__removeOutletContent();
this.activeRoutes = [];
fireRouterEvent('error', {router: this, error});
removeDomNodes(this.__outlet && this.__outlet.children);
this.location = createLocation({pathname});
fireRouterEvent('error', {router: this, error, pathname});
throw error;

@@ -1464,3 +1536,3 @@ }

__fullyResolveChain(originalContext, currentContext) {
__fullyResolveChain(originalContext, currentContext = originalContext) {
return this.__amendWithResolutionResult(currentContext)

@@ -1471,5 +1543,10 @@ .then(amendedContext => {

.then(nextContext => {
if (nextContext === null) {
if (amendedContext.pathname !== getMatchedPath(amendedContext.chain)) {
throw getNotFoundError(initialContext);
}
}
return nextContext
? this.__fullyResolveChain(initialContext, nextContext)
: this.__amendWithLifecycleCallbacks(initialContext);
: this.__amendWithOnBeforeCallbacks(initialContext);
});

@@ -1500,21 +1577,24 @@ });

__amendWithLifecycleCallbacks(contextWithFullChain) {
return this.__runLifecycleCallbacks(contextWithFullChain).then(amendedContext => {
__amendWithOnBeforeCallbacks(contextWithFullChain) {
return this.__runOnBeforeCallbacks(contextWithFullChain).then(amendedContext => {
if (amendedContext === this.__previousContext || amendedContext === contextWithFullChain) {
return amendedContext;
}
return this.__fullyResolveChain(amendedContext, amendedContext);
return this.__fullyResolveChain(amendedContext);
});
}
__runLifecycleCallbacks(newContext) {
const previousChain = (this.__previousContext || {}).chain;
__runOnBeforeCallbacks(newContext) {
const previousContext = this.__previousContext || {};
const previousChain = previousContext.chain || [];
const newChain = newContext.chain;
let callbacks = Promise.resolve();
const prevent = () => ({cancel: true});
const redirect = (pathname) => createRedirect(newContext, pathname);
newContext.__divergedChainIndex = 0;
if (previousChain && previousChain.length) {
for (; newContext.__divergedChainIndex < Math.min(previousChain.length, newChain.length); newContext.__divergedChainIndex++) {
if (previousChain[newContext.__divergedChainIndex] !== newChain[newContext.__divergedChainIndex]) {
if (previousChain.length) {
for (let i = 0; i < Math.min(previousChain.length, newChain.length); i = ++newContext.__divergedChainIndex) {
if (previousChain[i].route !== newChain[i].route || previousChain[i].path !== newChain[i].path) {
break;

@@ -1525,4 +1605,5 @@ }

for (let i = previousChain.length - 1; i >= newContext.__divergedChainIndex; i--) {
const location = createLocation(newContext);
callbacks = callbacks
.then(amend('onBeforeLeave', newContext, previousChain[i]))
.then(amend('onBeforeLeave', [location, {prevent}, this], previousChain[i].element))
.then(result => {

@@ -1536,5 +1617,5 @@ if (!(result || {}).redirect) {

const onBeforeEnterContext = Object.assign({redirect: path => redirect(newContext, path)}, newContext);
for (let i = newContext.__divergedChainIndex; i < newChain.length; i++) {
callbacks = callbacks.then(amend('onBeforeEnter', onBeforeEnterContext, newChain[i]));
const location = createLocation(newContext, newChain[i].route);
callbacks = callbacks.then(amend('onBeforeEnter', [location, {prevent, redirect}, this], newChain[i].element));
}

@@ -1562,3 +1643,3 @@

pathname: Router.pathToRegexp.compile(redirectData.pathname)(redirectData.params),
from: redirectData.from,
redirectFrom: redirectData.from,
__redirectCount: (counter || 0) + 1

@@ -1574,4 +1655,3 @@ });

__updateBrowserHistory(pathnameOrContext, replace) {
const pathname = pathnameOrContext.pathname || pathnameOrContext;
__updateBrowserHistory(pathname, replace) {
if (window.location.pathname !== pathname) {

@@ -1584,27 +1664,20 @@ const changeState = replace ? 'replaceState' : 'pushState';

__setOutletContent(context) {
this.__removePendingContent();
function containsElement(htmlElements, elementToSearch) {
for (let i = 0; i < htmlElements.length; i++) {
if (htmlElements[i] === elementToSearch) {
return true;
}
}
return false;
}
__addAppearingContent(context, previousContext) {
this.__ensureOutlet();
let lastUnchangedComponent = this.__outlet;
// If the previous 'entering' animation has not completed yet,
// stop it and remove that content from the DOM before adding new one.
this.__removeAppearingContent();
if (context) {
for (let i = 0; i < context.__divergedChainIndex; i++) {
const unchangedComponent = context.chain[i].__component;
if (unchangedComponent) {
if (containsElement(lastUnchangedComponent.children || [], unchangedComponent)) {
lastUnchangedComponent = unchangedComponent;
} else {
break;
}
// Find the deepest common parent between the last and the new component
// chains. Update references for the unchanged elements in the new chain
let deepestCommonParent = this.__outlet;
for (let i = 0; i < context.__divergedChainIndex; i++) {
const unchangedElement = previousContext && previousContext.chain[i].element;
if (unchangedElement) {
if (unchangedElement.parentNode === deepestCommonParent) {
context.chain[i].element = unchangedElement;
deepestCommonParent = unchangedElement;
} else {
break;
}

@@ -1614,14 +1687,21 @@ }

this.__oldContent = Array.from(lastUnchangedComponent.childNodes);
this.__newContent = [];
// Keep two lists of DOM elements:
// - those that should be removed once the transition animation is over
// - and those that should remain
this.__disappearingContent = Array.from(deepestCommonParent.children);
this.__appearingContent = [];
if (context) {
let parentElement = lastUnchangedComponent;
for (let i = context.__divergedChainIndex; i < context.chain.length; i++) {
const componentToAdd = context.chain[i].__component;
if (componentToAdd) {
parentElement.appendChild(componentToAdd);
parentElement = componentToAdd;
this.__newContent.push(componentToAdd);
// Add new elements (starting after the deepest common parent) to the DOM.
// That way only the components that are actually different between the two
// locations are added to the DOM (and those that are common remain in the
// DOM without first removing and then adding them again).
let parentElement = deepestCommonParent;
for (let i = context.__divergedChainIndex; i < context.chain.length; i++) {
const elementToAdd = context.chain[i].element;
if (elementToAdd) {
parentElement.appendChild(elementToAdd);
if (parentElement === deepestCommonParent) {
this.__appearingContent.push(elementToAdd);
}
parentElement = elementToAdd;
}

@@ -1631,43 +1711,56 @@ }

__removeOldOutletContent() {
if (this.__oldContent && this.__oldContent.length) {
this.__removeOutletContent(this.__oldContent);
__removeDisappearingContent() {
if (this.__disappearingContent) {
removeDomNodes(this.__disappearingContent);
}
this.__oldContent = null;
this.__newContent = null;
this.__disappearingContent = null;
this.__appearingContent = null;
}
__removePendingContent() {
if (this.__oldContent && this.__newContent) {
this.__oldContent = this.__newContent;
this.__removeOldOutletContent();
__removeAppearingContent() {
if (this.__disappearingContent && this.__appearingContent) {
removeDomNodes(this.__appearingContent);
this.__disappearingContent = null;
this.__appearingContent = null;
}
}
__removeOutletContent(content) {
content = content || (this.__outlet && this.__outlet.children);
if (content && content.length) {
const parent = content[0].parentNode;
for (let i = 0; i < content.length; i += 1) {
parent.removeChild(content[i]);
__runOnAfterLeaveCallbacks(currentContext, targetContext) {
if (!targetContext) {
return;
}
// REVERSE iteration: from Z to A
for (let i = targetContext.chain.length - 1; i >= currentContext.__divergedChainIndex; i--) {
const currentComponent = targetContext.chain[i].element;
if (!currentComponent) {
continue;
}
try {
const location = createLocation(currentContext);
runCallbackIfPossible(
currentComponent.onAfterLeave,
[location, {}, targetContext.resolver],
currentComponent);
} finally {
removeDomNodes(currentComponent.children);
}
}
}
__runOnAfterCallbacks(currentContext, targetContext, callbackName) {
let promises = Promise.resolve();
if (targetContext) {
const callbackContext = Object.assign({}, currentContext, {next: undefined});
for (let i = currentContext.__divergedChainIndex; i < targetContext.chain.length; i++) {
const currentComponent = targetContext.chain[i].__component || {};
promises = promises.then(() => runCallbackIfPossible(currentComponent[callbackName], callbackContext, currentComponent));
}
__runOnAfterEnterCallbacks(currentContext) {
// forward iteration: from A to Z
for (let i = currentContext.__divergedChainIndex; i < currentContext.chain.length; i++) {
const currentComponent = currentContext.chain[i].element || {};
const location = createLocation(currentContext, currentContext.chain[i].route);
runCallbackIfPossible(
currentComponent.onAfterEnter,
[location, {}, currentContext.resolver],
currentComponent);
}
return promises;
}
__animateIfNeeded(context) {
const from = this.__oldContent && this.__oldContent[0];
const to = this.__newContent && this.__newContent[0];
const from = (this.__disappearingContent || [])[0];
const to = (this.__appearingContent || [])[0];
const promises = [];

@@ -1678,4 +1771,4 @@

for (let i = chain.length; i > 0; i--) {
if (chain[i - 1].animate) {
config = chain[i - 1].animate;
if (chain[i - 1].route.animate) {
config = chain[i - 1].route.animate;
break;

@@ -1686,5 +1779,4 @@ }

if (from && to && config) {
const isObj = isObject(config);
const leave = isObj && config.leave || 'leaving';
const enter = isObj && config.enter || 'entering';
const leave = isObject(config) && config.leave || 'leaving';
const enter = isObject(config) && config.enter || 'entering';
promises.push(animate(from, leave));

@@ -1694,9 +1786,3 @@ promises.push(animate(to, enter));

if (promises.length) {
return new Promise(resolve => {
Promise.all(promises).then(() => resolve(context));
});
}
return context;
return Promise.all(promises).then(() => context);
}

@@ -1703,0 +1789,0 @@

@@ -1,1 +0,1 @@

function t(t){return t=t||[],Array.isArray(t)?t:[t]}function e(t){return`[Vaadin.Router] ${t}`}function n(t){if(!t||!u(t.path))throw new Error(e('Expected route config to be an object with a "path" string property, or an array of such objects'));const n=["component","redirect","bundle"];if(!(s(t.action)||Array.isArray(t.children)||s(t.children)||i(t.bundle)||n.some(e=>u(t[e]))))throw new Error(e(`Expected route config "${t.path}" to include either "${n.join('", "')}" `+'or "action" function but none found.'));if(t.bundle){const n=u(t.bundle)?t.bundle:t.bundle.src;if(!n.match(/.+\.[m]?js$/))throw new Error(e(`Unsupported type for bundle "${n}": .js or .mjs expected.`))}t.redirect&&["bundle","component"].forEach(n=>{n in t&&console.warn(e(`Route config "${t.path}" has both "redirect" and "${n}" properties, `+`and "redirect" will always override the latter. Did you mean to only use "${n}"?`))})}function r(e){t(e).forEach(t=>n(t))}function o(t,e){window.dispatchEvent(new CustomEvent(`vaadin-router-${t}`,{detail:e}))}function i(t){return"object"==typeof t}function s(t){return"function"==typeof t}function u(t){return"string"==typeof t}function c(t){if(t.defaultPrevented)return;if(0!==t.button)return;if(t.shiftKey||t.ctrlKey||t.altKey||t.metaKey)return;let e=t.target;const n=t.composedPath?t.composedPath():t.path||[];for(let t=0;t<n.length;t++){const r=n[t];if(r.nodeName&&"a"===r.nodeName.toLowerCase()){e=r;break}}for(;e&&"a"!==e.nodeName.toLowerCase();)e=e.parentNode;e&&"a"===e.nodeName.toLowerCase()&&(e.target&&"_self"!==e.target.toLowerCase()||e.hasAttribute("download")||e.pathname===window.location.pathname&&""!==e.hash||(e.origin||function(t){const e=t.port,n=t.protocol;return`${n}//${"http:"===n&&"80"===e||"https:"===n&&"443"===e?t.hostname:t.host}`}(e))===window.location.origin&&(t.preventDefault(),o("go",{pathname:e.pathname})))}const a={activate(){window.document.addEventListener("click",c)},inactivate(){window.document.removeEventListener("click",c)}};function f(t){"vaadin-router-ignore"!==t.state&&o("go",{pathname:window.location.pathname})}/Trident/.test(navigator.userAgent)&&!s(window.PopStateEvent)&&(window.PopStateEvent=function(t,e){e=e||{};var n=document.createEvent("Event");return n.initEvent(t,Boolean(e.bubbles),Boolean(e.cancelable)),n.state=e.state||null,n},window.PopStateEvent.prototype=window.Event.prototype);const h={activate(){window.addEventListener("popstate",f)},inactivate(){window.removeEventListener("popstate",f)}};var l=P,d=g,p=function(t,e){return E(g(t,e))},w=E,m=O,v="/",y="./",b=new RegExp(["(\\\\.)","(?:\\:(\\w+)(?:\\(((?:\\\\.|[^\\\\()])+)\\))?|\\(((?:\\\\.|[^\\\\()])+)\\))([+*?])?"].join("|"),"g");function g(t,e){for(var n,r=[],o=0,i=0,s="",u=e&&e.delimiter||v,c=e&&e.delimiters||y,a=!1;null!==(n=b.exec(t));){var f=n[0],h=n[1],l=n.index;if(s+=t.slice(i,l),i=l+f.length,h)s+=h[1],a=!0;else{var d="",p=t[i],w=n[2],m=n[3],g=n[4],E=n[5];if(!a&&s.length){var x=s.length-1;c.indexOf(s[x])>-1&&(d=s[x],s=s.slice(0,x))}s&&(r.push(s),s="",a=!1);var O=""!==d&&void 0!==p&&p!==d,P="+"===E||"*"===E,j="?"===E||"*"===E,R=d||u,C=m||g;r.push({name:w||o++,prefix:d,delimiter:R,optional:j,repeat:P,partial:O,pattern:C?$(C):"[^"+_(R)+"]+?"})}}return(s||i<t.length)&&r.push(s+t.substr(i)),r}function E(t){for(var e=new Array(t.length),n=0;n<t.length;n++)"object"==typeof t[n]&&(e[n]=new RegExp("^(?:"+t[n].pattern+")$"));return function(n,r){for(var o="",i=r&&r.encode||encodeURIComponent,s=0;s<t.length;s++){var u=t[s];if("string"!=typeof u){var c,a=n?n[u.name]:void 0;if(Array.isArray(a)){if(!u.repeat)throw new TypeError('Expected "'+u.name+'" to not repeat, but got array');if(0===a.length){if(u.optional)continue;throw new TypeError('Expected "'+u.name+'" to not be empty')}for(var f=0;f<a.length;f++){if(c=i(a[f],u),!e[s].test(c))throw new TypeError('Expected all "'+u.name+'" to match "'+u.pattern+'"');o+=(0===f?u.prefix:u.delimiter)+c}}else if("string"!=typeof a&&"number"!=typeof a&&"boolean"!=typeof a){if(!u.optional)throw new TypeError('Expected "'+u.name+'" to be '+(u.repeat?"an array":"a string"));u.partial&&(o+=u.prefix)}else{if(c=i(String(a),u),!e[s].test(c))throw new TypeError('Expected "'+u.name+'" to match "'+u.pattern+'", but got "'+c+'"');o+=u.prefix+c}}else o+=u}return o}}function _(t){return t.replace(/([.+*?=^!:${}()[\]|/\\])/g,"\\$1")}function $(t){return t.replace(/([=!:$/()])/g,"\\$1")}function x(t){return t&&t.sensitive?"":"i"}function O(t,e,n){for(var r=(n=n||{}).strict,o=!1!==n.end,i=_(n.delimiter||v),s=n.delimiters||y,u=[].concat(n.endsWith||[]).map(_).concat("$").join("|"),c="",a=!1,f=0;f<t.length;f++){var h=t[f];if("string"==typeof h)c+=_(h),a=f===t.length-1&&s.indexOf(h[h.length-1])>-1;else{var l=_(h.prefix),d=h.repeat?"(?:"+h.pattern+")(?:"+l+"(?:"+h.pattern+"))*":h.pattern;e&&e.push(h),h.optional?h.partial?c+=l+"("+d+")?":c+="(?:"+l+"("+d+"))?":c+=l+"("+d+")"}}return o?(r||(c+="(?:"+i+")?"),c+="$"===u?"$":"(?="+u+")"):(r||(c+="(?:"+i+"(?="+u+"))?"),a||(c+="(?="+i+"|"+u+")")),new RegExp("^"+c,x(n))}function P(t,e,n){return t instanceof RegExp?function(t,e){if(!e)return t;var n=t.source.match(/\((?!\?)/g);if(n)for(var r=0;r<n.length;r++)e.push({name:r,prefix:null,delimiter:null,optional:!1,repeat:!1,partial:!1,pattern:null});return t}(t,e):Array.isArray(t)?function(t,e,n){for(var r=[],o=0;o<t.length;o++)r.push(P(t[o],e,n).source);return new RegExp("(?:"+r.join("|")+")",x(n))}(t,e,n):function(t,e,n){return O(g(t,n),e,n)}(t,e,n)}l.parse=d,l.compile=p,l.tokensToFunction=w,l.tokensToRegExp=m;const{hasOwnProperty:j}=Object.prototype,R=new Map;function C(t){try{return decodeURIComponent(t)}catch(e){return t}}function T(t,e,n,r,o){let i,s,u=0,c=t.path||"";return"/"===c.charAt(0)&&(n&&(c=c.substr(1)),n=!0),{next(a){if(t===a)return{done:!0};const f=t.t=t.t||t.children;if(!i&&(i=function(t,e,n,r,o){const i=`${t}|${n=!!n}`;let s=R.get(i);if(!s){const e=[];s={keys:e,pattern:l(t,e,{end:n,strict:""===t})},R.set(i,s)}const u=s.pattern.exec(e);if(!u)return null;const c=Object.assign({},o);for(let t=1;t<u.length;t++){const e=s.keys[t-1],n=e.name,r=u[t];void 0===r&&j.call(c,n)||(e.repeat?c[n]=r?r.split(e.delimiter).map(C):[]:c[n]=r?C(r):r)}return{path:u[0],keys:(r||[]).concat(s.keys),params:c}}(c,e,!f,r,o)))return{done:!1,value:{route:t,keys:i.keys,params:i.params}};if(i&&f)for(;u<f.length;){if(!s){const r=f[u];r.parent=t;let o=i.path.length;o>0&&"/"===e.charAt(o)&&(o+=1),s=T(r,e.substr(o),n,i.keys,i.params)}const r=s.next(a);if(!r.done)return{done:!1,value:r.value};s=null,u++}return{done:!0}}}}function k(t){if(s(t.route.action))return t.route.action(t)}R.set("|false",{keys:[],pattern:/(?:)/});class A{constructor(t,e={}){if(Object(t)!==t)throw new TypeError("Invalid routes");this.baseUrl=e.baseUrl||"",this.errorHandler=e.errorHandler,this.resolveRoute=e.resolveRoute||k,this.context=Object.assign({resolver:this},e.context),this.root=Array.isArray(t)?{path:"",t:t,parent:null,o:!0}:t,this.root.parent=null}getRoutes(){return[...this.root.t]}setRoutes(e){r(e);const n=[...t(e)];this.root.t=n}addRoutes(e){return r(e),this.root.t.push(...t(e)),this.getRoutes()}removeRoutes(){this.setRoutes([])}resolve(t){const e=Object.assign({},this.context,u(t)?{pathname:t}:t),n=T(this.root,e.pathname.substr(this.baseUrl.length)),r=this.resolveRoute;let o=null,i=null,s=e;function c(t,u=o.value.route,a){const f=null===a&&o.value.route;if(o=i||n.next(f),i=null,!t&&(o.done||!function(t,e){let n=e;for(;n;)if((n=n.parent)===t)return!0;return!1}(u,o.value.route)))return i=o,Promise.resolve(null);if(o.done){const t=new Error(`Page not found (${e.pathname})`);return t.context=e,t.code=404,Promise.reject(t)}return function(t,e){e&&!e.o&&(function(t,e){return!e.parent||!t||!t.length||t[t.length-1]!==e.parent}(t.chain,e)?t.chain=[e]:t.chain.push(e))}(e,o.value.route),s=Object.assign({},e,o.value),Promise.resolve(r(s)).then(e=>null!==e&&void 0!==e?(s.result=e.result||e,s):c(t,u,e))}return e.next=c,Promise.resolve().then(()=>c(!0,this.root)).catch(t=>{const e=function(t){let e=`Path '${t.pathname}' is not properly resolved due to an error.`;const n=(t.route||{}).path;return n&&(e+=` Resolution had failed on route: '${n}'`),e}(s);if(t?console.warn(e):t=new Error(e),t.context=t.context||s,t instanceof DOMException||(t.code=t.code||500),this.errorHandler)return s.result=this.errorHandler(t),s;throw t})}}A.pathToRegexp=l;let L=[];function M(t){L.forEach(t=>t.inactivate()),t.forEach(t=>t.activate()),L=t}const B=t=>{const e=getComputedStyle(t).getPropertyValue("animation-name");return e&&"none"!==e},I=(t,e)=>{const n=()=>{t.removeEventListener("animationend",n),e()};t.addEventListener("animationend",n)};function S(t,e){return t.classList.add(e),new Promise(n=>{if(B(t)){const r=t.getBoundingClientRect(),o=`height: ${r.bottom-r.top}px; width: ${r.right-r.left}px`;t.setAttribute("style",`position: absolute; ${o}`),I(t,()=>{t.classList.remove(e),t.removeAttribute("style"),n()})}else t.classList.remove(e),n()})}const D=256;function H(t){return null!==t&&void 0!==t}function N(t,e){const n=Object.assign({},t.params);return{redirect:{pathname:e,from:t.pathname,params:n}}}function U(t,e){const n=t.route.i||document.createElement(e),r=Object.assign({},t.params);return n.route={params:r,pathname:t.pathname},t.from&&(n.route.redirectFrom=t.from),t.route.i=n,n}function W(t,e,n){if(s(t))return t.call(n,e)}function K(t,e,n){return r=>{if(r&&(r.cancel||r.redirect))return r;const o=n.i;return o?W(o[t],Object.assign({cancel:()=>({cancel:!0})},e,{next:void 0}),o):void 0}}class V extends A{constructor(t,e){super([],Object.assign({},e)),this.resolveRoute=(t=>this.s(t));const n=V.NavigationTrigger;V.setTriggers.apply(V,Object.keys(n).map(t=>n[t])),this.ready,this.ready=Promise.resolve(t),this.activeRoutes,this.activeRoutes=[],this.u=0,this.h=this.l.bind(this),this.setOutlet(t),this.subscribe()}s(r){const o=r.route,c=W(k,Object.assign({redirect:t=>N(r,t),component:t=>U(r,t)},r),o);if(H(c))return c;if(u(o.redirect))return N(r,o.redirect);let a=Promise.resolve();return o.bundle&&(a=a.then(()=>(function(t){const e=u(t)?t:t.src;let n=document.head.querySelector('script[src="'+e+'"][async]');return n&&n.parentNode===document.head?n.p?Promise.resolve():new Promise((t,e)=>{const r=n.onload;n.onreadystatechange=n.onload=(e=>{r(),t(e)});const o=n.onerror;n.onerror=(t=>{o(),e(t)})}):new Promise((r,o)=>{(n=document.createElement("script")).setAttribute("src",e),i(t)&&"module"===t.type&&n.setAttribute("type","module"),n.async=!0,n.onreadystatechange=n.onload=(t=>{n.p=!0,r(t)}),n.onerror=(t=>{n.parentNode&&n.parentNode.removeChild(n),o(t)}),document.head.appendChild(n)})})(o.bundle)).catch(()=>{throw new Error(e(`Bundle not found: ${o.bundle}. Check if the file name is correct`))})),s(o.children)&&(a=a.then(()=>o.children(Object.assign({},r,{next:void 0}))).then(r=>{H(r)||s(o.children)||(r=o.children),function(r,o,s){if(H(r)&&!i(r))throw new Error(e(`Expected 'children' method of the route with path '${o.path}' `+`to return an object, but got: '${r}'`));o.t=[];const u=t(r);for(let t=0;t<u.length;t++)n(u[t]),o.t.push(u[t])}(r,o)})),a.then(()=>(function(t,e){if(u(t.component))return U(e,t.component)})(o,r))}setOutlet(t){t&&this.m(t),this.v=t}getOutlet(){return this.v}setRoutes(t){super.setRoutes(t),this.l()}render(t,e){const n=++this.u;return this.ready=this.resolve(t).then(t=>this.g(t,t)).then(t=>{if(n===this.u)return e&&this._(t.result.route.pathname,t.from),t!==this.$?this.O(t,this.$,"onAfterLeave").then(()=>this.P(t)).then(()=>this.O(t,t,"onAfterEnter")).then(()=>t):Promise.resolve(t)}).then(t=>{if(n===this.u)return this.j(t)}).then(t=>(n===this.u&&this.R(),this.$=t,this.activeRoutes=[...t.chain],o("route-changed",{router:this,params:t.params,pathname:t.pathname}),this.v)).catch(r=>{if(n===this.u)throw e&&this._(t),this.C(),this.activeRoutes=[],o("error",{router:this,error:r}),r}),this.ready}g(t,e){return this.T(e).then(n=>{const r=n!==e?n:t;return n.next().then(t=>t?this.g(r,t):this.k(r))})}T(t){const n=t.result;return n instanceof HTMLElement?Promise.resolve(t):n.redirect?this.A(n.redirect,t.L).then(t=>this.T(t)):n instanceof Error?Promise.reject(n):Promise.reject(new Error(e(`Invalid route resolution result for path "${t.pathname}". `+`Expected redirect object or HTML element, but got: "${n}". `+"Double check the action return value for the route.")))}k(t){return this.M(t).then(e=>e===this.$||e===t?e:this.g(e,e))}M(t){const e=(this.$||{}).chain,n=t.chain;let r=Promise.resolve();if(t.B=0,e&&e.length){for(;t.B<Math.min(e.length,n.length)&&e[t.B]===n[t.B];t.B++);for(let n=e.length-1;n>=t.B;n--)r=r.then(K("onBeforeLeave",t,e[n])).then(t=>{if(!(t||{}).redirect)return t})}const o=Object.assign({redirect:e=>N(t,e)},t);for(let e=t.B;e<n.length;e++)r=r.then(K("onBeforeEnter",o,n[e]));return r.then(e=>{if(e){if(e.cancel)return this.$;if(e.redirect)return this.A(e.redirect,t.L)}return t})}A(t,n){if(n>D)throw new Error(e(`Too many redirects when rendering ${t.from}`));return this.resolve({pathname:V.pathToRegexp.compile(t.pathname)(t.params),from:t.from,L:(n||0)+1})}m(t=this.v){if(!(t instanceof Node))throw new TypeError(e(`Expected router outlet to be a valid DOM Node (but got ${t})`))}_(t,e){const n=t.pathname||t;if(window.location.pathname!==n){const t=e?"replaceState":"pushState";window.history[t](null,document.title,n),window.dispatchEvent(new PopStateEvent("popstate",{state:"vaadin-router-ignore"}))}}P(t){function e(t,e){for(let n=0;n<t.length;n++)if(t[n]===e)return!0;return!1}this.I(),this.m();let n=this.v;if(t)for(let r=0;r<t.B;r++){const o=t.chain[r].i;if(o){if(!e(n.children||[],o))break;n=o}}if(this.S=Array.from(n.childNodes),this.D=[],t){let e=n;for(let n=t.B;n<t.chain.length;n++){const r=t.chain[n].i;r&&(e.appendChild(r),e=r,this.D.push(r))}}}R(){this.S&&this.S.length&&this.C(this.S),this.S=null,this.D=null}I(){this.S&&this.D&&(this.S=this.D,this.R())}C(t){if((t=t||this.v&&this.v.children)&&t.length){const e=t[0].parentNode;for(let n=0;n<t.length;n+=1)e.removeChild(t[n])}}O(t,e,n){let r=Promise.resolve();if(e){const o=Object.assign({},t,{next:void 0});for(let i=t.B;i<e.chain.length;i++){const t=e.chain[i].i||{};r=r.then(()=>W(t[n],o,t))}}return r}j(t){const e=this.S&&this.S[0],n=this.D&&this.D[0],r=[],o=t.chain;let s;for(let t=o.length;t>0;t--)if(o[t-1].animate){s=o[t-1].animate;break}if(e&&n&&s){const t=i(s),o=t&&s.leave||"leaving",u=t&&s.enter||"entering";r.push(S(e,o)),r.push(S(n,u))}return r.length?new Promise(e=>{Promise.all(r).then(()=>e(t))}):t}subscribe(){window.addEventListener("vaadin-router-go",this.h)}unsubscribe(){window.removeEventListener("vaadin-router-go",this.h)}l(t){const e=t?t.detail.pathname:window.location.pathname;this.render(e,!0)}static setTriggers(...t){M(t)}static go(t){o("go",{pathname:t})}}const q=(()=>(class extends HTMLElement{static get is(){return"vaadin-router-meta"}static get version(){return"0.3.0"}}))();customElements.define(q.is,q),V.NavigationTrigger={POPSTATE:h,CLICK:a};export{V as Router,A as Resolver};
function t(t){return t=t||[],Array.isArray(t)?t:[t]}function e(t){return`[Vaadin.Router] ${t}`}const n="module",r="nomodule",o=[n,r];function i(t){if(!t.match(/.+\.[m]?js$/))throw new Error(e(`Unsupported type for bundle "${t}": .js or .mjs expected.`))}function s(t){if(!t||!h(t.path))throw new Error(e('Expected route config to be an object with a "path" string property, or an array of such objects'));const s=t.bundle,u=["component","redirect","bundle"];if(!(l(t.action)||Array.isArray(t.children)||l(t.children)||f(s)||u.some(e=>h(t[e]))))throw new Error(e(`Expected route config "${t.path}" to include either "${u.join('", "')}" `+'or "action" function but none found.'));if(s)if(h(s))i(s);else{if(!o.some(t=>t in s))throw new Error(e('Expected route bundle to include either "'+r+'" or "'+n+'" keys, or both'));o.forEach(t=>t in s&&i(s[t]))}t.redirect&&["bundle","component"].forEach(n=>{n in t&&console.warn(e(`Route config "${t.path}" has both "redirect" and "${n}" properties, `+`and "redirect" will always override the latter. Did you mean to only use "${n}"?`))})}function u(e){t(e).forEach(t=>s(t))}function c(t,e){let o=document.head.querySelector('script[src="'+t+'"][async]');return o||((o=document.createElement("script")).setAttribute("src",t),e===n?o.setAttribute("type",n):e===r&&o.setAttribute(r,""),o.async=!0),new Promise((t,e)=>{o.onreadystatechange=o.onload=(e=>{o.t=!0,t(e)}),o.onerror=(t=>{o.parentNode&&o.parentNode.removeChild(o),e(t)}),null===o.parentNode?document.head.appendChild(o):o.t&&t()})}function a(t,e){window.dispatchEvent(new CustomEvent(`vaadin-router-${t}`,{detail:e}))}function f(t){return"object"==typeof t&&!!t}function l(t){return"function"==typeof t}function h(t){return"string"==typeof t}function d(t){const n=new Error(e(`Page not found (${t.pathname})`));return n.context=t,n.code=404,n}function p(t){if(t.defaultPrevented)return;if(0!==t.button)return;if(t.shiftKey||t.ctrlKey||t.altKey||t.metaKey)return;let e=t.target;const n=t.composedPath?t.composedPath():t.path||[];for(let t=0;t<n.length;t++){const r=n[t];if(r.nodeName&&"a"===r.nodeName.toLowerCase()){e=r;break}}for(;e&&"a"!==e.nodeName.toLowerCase();)e=e.parentNode;e&&"a"===e.nodeName.toLowerCase()&&(e.target&&"_self"!==e.target.toLowerCase()||e.hasAttribute("download")||e.pathname===window.location.pathname&&""!==e.hash||(e.origin||function(t){const e=t.port,n=t.protocol;return`${n}//${"http:"===n&&"80"===e||"https:"===n&&"443"===e?t.hostname:t.host}`}(e))===window.location.origin&&(t.preventDefault(),a("go",{pathname:e.pathname})))}const w={activate(){window.document.addEventListener("click",p)},inactivate(){window.document.removeEventListener("click",p)}};function m(t){"vaadin-router-ignore"!==t.state&&a("go",{pathname:window.location.pathname})}/Trident/.test(navigator.userAgent)&&!l(window.PopStateEvent)&&(window.PopStateEvent=function(t,e){e=e||{};var n=document.createEvent("Event");return n.initEvent(t,Boolean(e.bubbles),Boolean(e.cancelable)),n.state=e.state||null,n},window.PopStateEvent.prototype=window.Event.prototype);const v={activate(){window.addEventListener("popstate",m)},inactivate(){window.removeEventListener("popstate",m)}};var y=A,g=P,b=function(t,e){return j(P(t,e))},E=j,_=T,$="/",x="./",O=new RegExp(["(\\\\.)","(?:\\:(\\w+)(?:\\(((?:\\\\.|[^\\\\()])+)\\))?|\\(((?:\\\\.|[^\\\\()])+)\\))([+*?])?"].join("|"),"g");function P(t,e){for(var n,r=[],o=0,i=0,s="",u=e&&e.delimiter||$,c=e&&e.delimiters||x,a=!1;null!==(n=O.exec(t));){var f=n[0],l=n[1],h=n.index;if(s+=t.slice(i,h),i=h+f.length,l)s+=l[1],a=!0;else{var d="",p=t[i],w=n[2],m=n[3],v=n[4],y=n[5];if(!a&&s.length){var g=s.length-1;c.indexOf(s[g])>-1&&(d=s[g],s=s.slice(0,g))}s&&(r.push(s),s="",a=!1);var b=""!==d&&void 0!==p&&p!==d,E="+"===y||"*"===y,_="?"===y||"*"===y,P=d||u,j=m||v;r.push({name:w||o++,prefix:d,delimiter:P,optional:_,repeat:E,partial:b,pattern:j?k(j):"[^"+R(P)+"]+?"})}}return(s||i<t.length)&&r.push(s+t.substr(i)),r}function j(t){for(var e=new Array(t.length),n=0;n<t.length;n++)"object"==typeof t[n]&&(e[n]=new RegExp("^(?:"+t[n].pattern+")$"));return function(n,r){for(var o="",i=r&&r.encode||encodeURIComponent,s=0;s<t.length;s++){var u=t[s];if("string"!=typeof u){var c,a=n?n[u.name]:void 0;if(Array.isArray(a)){if(!u.repeat)throw new TypeError('Expected "'+u.name+'" to not repeat, but got array');if(0===a.length){if(u.optional)continue;throw new TypeError('Expected "'+u.name+'" to not be empty')}for(var f=0;f<a.length;f++){if(c=i(a[f],u),!e[s].test(c))throw new TypeError('Expected all "'+u.name+'" to match "'+u.pattern+'"');o+=(0===f?u.prefix:u.delimiter)+c}}else if("string"!=typeof a&&"number"!=typeof a&&"boolean"!=typeof a){if(!u.optional)throw new TypeError('Expected "'+u.name+'" to be '+(u.repeat?"an array":"a string"));u.partial&&(o+=u.prefix)}else{if(c=i(String(a),u),!e[s].test(c))throw new TypeError('Expected "'+u.name+'" to match "'+u.pattern+'", but got "'+c+'"');o+=u.prefix+c}}else o+=u}return o}}function R(t){return t.replace(/([.+*?=^!:${}()[\]|/\\])/g,"\\$1")}function k(t){return t.replace(/([=!:$/()])/g,"\\$1")}function C(t){return t&&t.sensitive?"":"i"}function T(t,e,n){for(var r=(n=n||{}).strict,o=!1!==n.end,i=R(n.delimiter||$),s=n.delimiters||x,u=[].concat(n.endsWith||[]).map(R).concat("$").join("|"),c="",a=!1,f=0;f<t.length;f++){var l=t[f];if("string"==typeof l)c+=R(l),a=f===t.length-1&&s.indexOf(l[l.length-1])>-1;else{var h=R(l.prefix),d=l.repeat?"(?:"+l.pattern+")(?:"+h+"(?:"+l.pattern+"))*":l.pattern;e&&e.push(l),l.optional?l.partial?c+=h+"("+d+")?":c+="(?:"+h+"("+d+"))?":c+=h+"("+d+")"}}return o?(r||(c+="(?:"+i+")?"),c+="$"===u?"$":"(?="+u+")"):(r||(c+="(?:"+i+"(?="+u+"))?"),a||(c+="(?="+i+"|"+u+")")),new RegExp("^"+c,C(n))}function A(t,e,n){return t instanceof RegExp?function(t,e){if(!e)return t;var n=t.source.match(/\((?!\?)/g);if(n)for(var r=0;r<n.length;r++)e.push({name:r,prefix:null,delimiter:null,optional:!1,repeat:!1,partial:!1,pattern:null});return t}(t,e):Array.isArray(t)?function(t,e,n){for(var r=[],o=0;o<t.length;o++)r.push(A(t[o],e,n).source);return new RegExp("(?:"+r.join("|")+")",C(n))}(t,e,n):function(t,e,n){return T(P(t,n),e,n)}(t,e,n)}y.parse=g,y.compile=b,y.tokensToFunction=E,y.tokensToRegExp=_;const{hasOwnProperty:B}=Object.prototype,I=new Map;function M(t){try{return decodeURIComponent(t)}catch(e){return t}}function L(t,e,n,r,o){let i,s,u=0,c=t.path||"";return"/"===c.charAt(0)&&(n&&(c=c.substr(1)),n=!0),{next(a){if(t===a)return{done:!0};const f=t.o=t.o||t.children;if(!i&&(i=function(t,e,n,r,o){const i=`${t}|${n=!!n}`;let s=I.get(i);if(!s){const e=[];s={keys:e,pattern:y(t,e,{end:n,strict:""===t})},I.set(i,s)}const u=s.pattern.exec(e);if(!u)return null;const c=Object.assign({},o);for(let t=1;t<u.length;t++){const e=s.keys[t-1],n=e.name,r=u[t];void 0===r&&B.call(c,n)||(e.repeat?c[n]=r?r.split(e.delimiter).map(M):[]:c[n]=r?M(r):r)}return{path:u[0],keys:(r||[]).concat(s.keys),params:c}}(c,e,!f,r,o)))return{done:!1,value:{route:t,keys:i.keys,params:i.params,path:i.path}};if(i&&f)for(;u<f.length;){if(!s){const r=f[u];r.parent=t;let o=i.path.length;o>0&&"/"===e.charAt(o)&&(o+=1),s=L(r,e.substr(o),n,i.keys,i.params)}const r=s.next(a);if(!r.done)return{done:!1,value:r.value};s=null,u++}return{done:!0}}}}function S(t){if(l(t.route.action))return t.route.action(t)}I.set("|false",{keys:[],pattern:/(?:)/});class D{constructor(t,e={}){if(Object(t)!==t)throw new TypeError("Invalid routes");this.baseUrl=e.baseUrl||"",this.errorHandler=e.errorHandler,this.resolveRoute=e.resolveRoute||S,this.context=Object.assign({resolver:this},e.context),this.root=Array.isArray(t)?{path:"",o:t,parent:null,i:!0}:t,this.root.parent=null}getRoutes(){return[...this.root.o]}setRoutes(e){u(e);const n=[...t(e)];this.root.o=n}addRoutes(e){return u(e),this.root.o.push(...t(e)),this.getRoutes()}removeRoutes(){this.setRoutes([])}resolve(t){const e=Object.assign({},this.context,h(t)?{pathname:t}:t),n=L(this.root,e.pathname.substr(this.baseUrl.length)),r=this.resolveRoute;let o=null,i=null,s=e;function u(t,c=o.value.route,a){const f=null===a&&o.value.route;return o=i||n.next(f),i=null,t||!o.done&&function(t,e){let n=e;for(;n;)if((n=n.parent)===t)return!0;return!1}(c,o.value.route)?o.done?Promise.reject(d(e)):(function(t,e){const{route:n,path:r}=e;if(n&&!n.i){const e={path:r,route:n};!function(t,e){return!e.parent||!t||!t.length||t[t.length-1].route!==e.parent}(t.chain,n)?t.chain.push(e):t.chain=[e]}}(e,o.value),s=Object.assign({},e,o.value),Promise.resolve(r(s)).then(e=>null!==e&&void 0!==e?(s.result=e.result||e,s):u(t,c,e))):(i=o,Promise.resolve(null))}return e.next=u,Promise.resolve().then(()=>u(!0,this.root)).catch(t=>{const e=function(t){let e=`Path '${t.pathname}' is not properly resolved due to an error.`;const n=(t.route||{}).path;return n&&(e+=` Resolution had failed on route: '${n}'`),e}(s);if(t?console.warn(e):t=new Error(e),t.context=t.context||s,t instanceof DOMException||(t.code=t.code||500),this.errorHandler)return s.result=this.errorHandler(t),s;throw t})}}D.pathToRegexp=y;let H=[];function N(t){H.forEach(t=>t.inactivate()),t.forEach(t=>t.activate()),H=t}const F=t=>{const e=getComputedStyle(t).getPropertyValue("animation-name");return e&&"none"!==e},U=(t,e)=>{const n=()=>{t.removeEventListener("animationend",n),e()};t.addEventListener("animationend",n)};function W(t,e){return t.classList.add(e),new Promise(n=>{if(F(t)){const r=t.getBoundingClientRect(),o=`height: ${r.bottom-r.top}px; width: ${r.right-r.left}px`;t.setAttribute("style",`position: absolute; ${o}`),U(t,()=>{t.classList.remove(e),t.removeAttribute("style"),n()})}else t.classList.remove(e),n()})}const K=256;function V(t){return null!==t&&void 0!==t}function q({pathname:t="",chain:e=[],params:n={},redirectFrom:r},o){return{pathname:t,routes:e.map(t=>t.route),route:!o&&e.length&&e[e.length-1].route||o,params:n,redirectFrom:r}}function z(t,e){const n=Object.assign({},t.params);return{redirect:{pathname:e,from:t.pathname,params:n}}}function G(t,e,n){if(l(t))return t.apply(n,e)}function J(t,e,n){return r=>r&&(r.cancel||r.redirect)?r:n?G(n[t],e,n):void 0}function Q(t){if(t&&t.length){const e=t[0].parentNode;for(let n=0;n<t.length;n++)e.removeChild(t[n])}}class X extends D{constructor(t,e){super([],Object.assign({},e)),this.resolveRoute=(t=>this.s(t));const n=X.NavigationTrigger;X.setTriggers.apply(X,Object.keys(n).map(t=>n[t])),this.ready,this.ready=Promise.resolve(t),this.location,this.location=q({}),this.u=0,this.l=this.h.bind(this),this.setOutlet(t),this.subscribe()}s(n){const r=n.route,i={redirect:t=>z(n,t),component:t=>(function(t,e){const n=document.createElement(e);n.location=q(t);const r=t.chain.map(t=>t.route).indexOf(t.route);return t.chain[r].element=n,n})(n,t)},u=G(r.action,[n,i],r);if(V(u))return u;if(h(r.redirect))return i.redirect(r.redirect);let a=Promise.resolve();var d;return r.bundle&&(a=a.then(()=>(d=r.bundle,h(d)?c(d):Promise.race(o.filter(t=>t in d).map(t=>c(d[t],t))))).catch(()=>{throw new Error(e(`Bundle not found: ${r.bundle}. Check if the file name is correct`))})),l(r.children)&&(a=a.then(()=>r.children(function(t){const e=Object.assign({},t);return delete e.next,e}(n))).then(n=>{V(n)||l(r.children)||(n=r.children),function(n,r){if(!Array.isArray(n)&&!f(n))throw new Error(e(`Incorrect "children" value for the route ${r.path}: expected array or object, but got ${n}`));r.o=[];const o=t(n);for(let t=0;t<o.length;t++)s(o[t]),r.o.push(o[t])}(n,r)})),a.then(()=>{if(h(r.component))return i.component(r.component)})}setOutlet(t){t&&this.p(t),this.m=t}getOutlet(){return this.m}setRoutes(t){super.setRoutes(t),this.h()}render(t,e){const n=++this.u,r=t.pathname||t;return this.ready=this.resolve(t).then(t=>this.v(t)).then(t=>{if(n===this.u){const r=this.g;if(t===r)return this.location;e&&this._(t.pathname,t.redirectFrom),this.$(t,r);const o=this.O(t);return this.P(t),this.j(t,r),o.then(()=>{if(n===this.u)return this.R(),this.g=t,this.location=q(t),a("location-changed",{router:this,location:this.location}),this.location})}}).catch(t=>{if(n===this.u)throw e&&this._(r),Q(this.m&&this.m.children),this.location=q({pathname:r}),a("error",{router:this,error:t,pathname:r}),t}),this.ready}v(t,e=t){return this.k(e).then(n=>{const r=n!==e?n:t;return n.next().then(t=>{if(null===t&&n.pathname!==n.chain.map(t=>t.path).reduce((t,e)=>e.length?"/"===t?t+e:t+"/"+e:t))throw d(r);return t?this.v(r,t):this.C(r)})})}k(t){const n=t.result;return n instanceof HTMLElement?Promise.resolve(t):n.redirect?this.T(n.redirect,t.A).then(t=>this.k(t)):n instanceof Error?Promise.reject(n):Promise.reject(new Error(e(`Invalid route resolution result for path "${t.pathname}". `+`Expected redirect object or HTML element, but got: "${n}". `+"Double check the action return value for the route.")))}C(t){return this.B(t).then(e=>e===this.g||e===t?e:this.v(e))}B(t){const e=(this.g||{}).chain||[],n=t.chain;let r=Promise.resolve();const o=()=>({cancel:!0}),i=e=>z(t,e);if(t.I=0,e.length){for(let r=0;r<Math.min(e.length,n.length)&&(e[r].route===n[r].route&&e[r].path===n[r].path);r=++t.I);for(let n=e.length-1;n>=t.I;n--){const i=q(t);r=r.then(J("onBeforeLeave",[i,{prevent:o},this],e[n].element)).then(t=>{if(!(t||{}).redirect)return t})}}for(let e=t.I;e<n.length;e++){const s=q(t,n[e].route);r=r.then(J("onBeforeEnter",[s,{prevent:o,redirect:i},this],n[e].element))}return r.then(e=>{if(e){if(e.cancel)return this.g;if(e.redirect)return this.T(e.redirect,t.A)}return t})}T(t,n){if(n>K)throw new Error(e(`Too many redirects when rendering ${t.from}`));return this.resolve({pathname:X.pathToRegexp.compile(t.pathname)(t.params),redirectFrom:t.from,A:(n||0)+1})}p(t=this.m){if(!(t instanceof Node))throw new TypeError(e(`Expected router outlet to be a valid DOM Node (but got ${t})`))}_(t,e){if(window.location.pathname!==t){const n=e?"replaceState":"pushState";window.history[n](null,document.title,t),window.dispatchEvent(new PopStateEvent("popstate",{state:"vaadin-router-ignore"}))}}$(t,e){this.p(),this.M();let n=this.m;for(let r=0;r<t.I;r++){const o=e&&e.chain[r].element;if(o){if(o.parentNode!==n)break;t.chain[r].element=o,n=o}}this.L=Array.from(n.children),this.S=[];let r=n;for(let e=t.I;e<t.chain.length;e++){const o=t.chain[e].element;o&&(r.appendChild(o),r===n&&this.S.push(o),r=o)}}R(){this.L&&Q(this.L),this.L=null,this.S=null}M(){this.L&&this.S&&(Q(this.S),this.L=null,this.S=null)}j(t,e){if(e)for(let n=e.chain.length-1;n>=t.I;n--){const r=e.chain[n].element;if(r)try{const n=q(t);G(r.onAfterLeave,[n,{},e.resolver],r)}finally{Q(r.children)}}}P(t){for(let e=t.I;e<t.chain.length;e++){const n=t.chain[e].element||{},r=q(t,t.chain[e].route);G(n.onAfterEnter,[r,{},t.resolver],n)}}O(t){const e=(this.L||[])[0],n=(this.S||[])[0],r=[],o=t.chain;let i;for(let t=o.length;t>0;t--)if(o[t-1].route.animate){i=o[t-1].route.animate;break}if(e&&n&&i){const t=f(i)&&i.leave||"leaving",o=f(i)&&i.enter||"entering";r.push(W(e,t)),r.push(W(n,o))}return Promise.all(r).then(()=>t)}subscribe(){window.addEventListener("vaadin-router-go",this.l)}unsubscribe(){window.removeEventListener("vaadin-router-go",this.l)}h(t){const e=t?t.detail.pathname:window.location.pathname;this.render(e,!0)}static setTriggers(...t){N(t)}static go(t){a("go",{pathname:t})}}const Y=(()=>(class extends HTMLElement{static get is(){return"vaadin-router-meta"}static get version(){return"0.3.0"}}))();customElements.define(Y.is,Y),X.NavigationTrigger={POPSTATE:v,CLICK:w};export{X as Router,D as Resolver};

@@ -1,2 +0,2 @@

!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t(e.Vaadin=e.Vaadin||{})}(this,function(e){"use strict";var t="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},n=function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")},r=function(){function e(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}return function(t,n,r){return n&&e(t.prototype,n),r&&e(t,r),t}}(),o=function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)},i=function(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t},a=function(e){if(Array.isArray(e)){for(var t=0,n=Array(e.length);t<e.length;t++)n[t]=e[t];return n}return Array.from(e)};function u(e){return e=e||[],Array.isArray(e)?e:[e]}function c(e){return"[Vaadin.Router] "+e}function l(e){if(!e||!p(e.path))throw new Error(c('Expected route config to be an object with a "path" string property, or an array of such objects'));var t=["component","redirect","bundle"];if(!(h(e.action)||Array.isArray(e.children)||h(e.children)||d(e.bundle)||t.some(function(t){return p(e[t])})))throw new Error(c('Expected route config "'+e.path+'" to include either "'+t.join('", "')+'" or "action" function but none found.'));if(e.bundle){var n=p(e.bundle)?e.bundle:e.bundle.src;if(!n.match(/.+\.[m]?js$/))throw new Error(c('Unsupported type for bundle "'+n+'": .js or .mjs expected.'))}e.redirect&&["bundle","component"].forEach(function(t){t in e&&console.warn(c('Route config "'+e.path+'" has both "redirect" and "'+t+'" properties, and "redirect" will always override the latter. Did you mean to only use "'+t+'"?'))})}function s(e){u(e).forEach(function(e){return l(e)})}function f(e,t){window.dispatchEvent(new CustomEvent("vaadin-router-"+e,{detail:t}))}function d(e){return"object"===(void 0===e?"undefined":t(e))}function h(e){return"function"==typeof e}function p(e){return"string"==typeof e}function v(e){if(!e.defaultPrevented&&0===e.button&&!(e.shiftKey||e.ctrlKey||e.altKey||e.metaKey)){for(var t=e.target,n=e.composedPath?e.composedPath():e.path||[],r=0;r<n.length;r++){var o=n[r];if(o.nodeName&&"a"===o.nodeName.toLowerCase()){t=o;break}}for(;t&&"a"!==t.nodeName.toLowerCase();)t=t.parentNode;if(t&&"a"===t.nodeName.toLowerCase())if(!t.target||"_self"===t.target.toLowerCase())if(!t.hasAttribute("download"))if(t.pathname!==window.location.pathname||""===t.hash)(t.origin||function(e){var t=e.port,n=e.protocol;return n+"//"+("http:"===n&&"80"===t||"https:"===n&&"443"===t?e.hostname:e.host)}(t))===window.location.origin&&(e.preventDefault(),f("go",{pathname:t.pathname}))}}var _={activate:function(){window.document.addEventListener("click",v)},inactivate:function(){window.document.removeEventListener("click",v)}};function m(e){"vaadin-router-ignore"!==e.state&&f("go",{pathname:window.location.pathname})}/Trident/.test(navigator.userAgent)&&!h(window.PopStateEvent)&&(window.PopStateEvent=function(e,t){t=t||{};var n=document.createEvent("Event");return n.initEvent(e,Boolean(t.bubbles),Boolean(t.cancelable)),n.state=t.state||null,n},window.PopStateEvent.prototype=window.Event.prototype);var y={activate:function(){window.addEventListener("popstate",m)},inactivate:function(){window.removeEventListener("popstate",m)}},g=T,w=R,b=function(e,t){return j(R(e,t))},E=j,C=I,x="/",O="./",k=new RegExp(["(\\\\.)","(?:\\:(\\w+)(?:\\(((?:\\\\.|[^\\\\()])+)\\))?|\\(((?:\\\\.|[^\\\\()])+)\\))([+*?])?"].join("|"),"g");function R(e,t){for(var n,r=[],o=0,i=0,a="",u=t&&t.delimiter||x,c=t&&t.delimiters||O,l=!1;null!==(n=k.exec(e));){var s=n[0],f=n[1],d=n.index;if(a+=e.slice(i,d),i=d+s.length,f)a+=f[1],l=!0;else{var h="",p=e[i],v=n[2],_=n[3],m=n[4],y=n[5];if(!l&&a.length){var g=a.length-1;c.indexOf(a[g])>-1&&(h=a[g],a=a.slice(0,g))}a&&(r.push(a),a="",l=!1);var w=""!==h&&void 0!==p&&p!==h,b="+"===y||"*"===y,E="?"===y||"*"===y,C=h||u,R=_||m;r.push({name:v||o++,prefix:h,delimiter:C,optional:E,repeat:b,partial:w,pattern:R?A(R):"[^"+P(C)+"]+?"})}}return(a||i<e.length)&&r.push(a+e.substr(i)),r}function j(e){for(var n=new Array(e.length),r=0;r<e.length;r++)"object"===t(e[r])&&(n[r]=new RegExp("^(?:"+e[r].pattern+")$"));return function(t,r){for(var o="",i=r&&r.encode||encodeURIComponent,a=0;a<e.length;a++){var u=e[a];if("string"!=typeof u){var c,l=t?t[u.name]:void 0;if(Array.isArray(l)){if(!u.repeat)throw new TypeError('Expected "'+u.name+'" to not repeat, but got array');if(0===l.length){if(u.optional)continue;throw new TypeError('Expected "'+u.name+'" to not be empty')}for(var s=0;s<l.length;s++){if(c=i(l[s],u),!n[a].test(c))throw new TypeError('Expected all "'+u.name+'" to match "'+u.pattern+'"');o+=(0===s?u.prefix:u.delimiter)+c}}else if("string"!=typeof l&&"number"!=typeof l&&"boolean"!=typeof l){if(!u.optional)throw new TypeError('Expected "'+u.name+'" to be '+(u.repeat?"an array":"a string"));u.partial&&(o+=u.prefix)}else{if(c=i(String(l),u),!n[a].test(c))throw new TypeError('Expected "'+u.name+'" to match "'+u.pattern+'", but got "'+c+'"');o+=u.prefix+c}}else o+=u}return o}}function P(e){return e.replace(/([.+*?=^!:${}()[\]|/\\])/g,"\\$1")}function A(e){return e.replace(/([=!:$/()])/g,"\\$1")}function L(e){return e&&e.sensitive?"":"i"}function I(e,t,n){for(var r=(n=n||{}).strict,o=!1!==n.end,i=P(n.delimiter||x),a=n.delimiters||O,u=[].concat(n.endsWith||[]).map(P).concat("$").join("|"),c="",l=!1,s=0;s<e.length;s++){var f=e[s];if("string"==typeof f)c+=P(f),l=s===e.length-1&&a.indexOf(f[f.length-1])>-1;else{var d=P(f.prefix),h=f.repeat?"(?:"+f.pattern+")(?:"+d+"(?:"+f.pattern+"))*":f.pattern;t&&t.push(f),f.optional?f.partial?c+=d+"("+h+")?":c+="(?:"+d+"("+h+"))?":c+=d+"("+h+")"}}return o?(r||(c+="(?:"+i+")?"),c+="$"===u?"$":"(?="+u+")"):(r||(c+="(?:"+i+"(?="+u+"))?"),l||(c+="(?="+i+"|"+u+")")),new RegExp("^"+c,L(n))}function T(e,t,n){return e instanceof RegExp?function(e,t){if(!t)return e;var n=e.source.match(/\((?!\?)/g);if(n)for(var r=0;r<n.length;r++)t.push({name:r,prefix:null,delimiter:null,optional:!1,repeat:!1,partial:!1,pattern:null});return e}(e,t):Array.isArray(e)?function(e,t,n){for(var r=[],o=0;o<e.length;o++)r.push(T(e[o],t,n).source);return new RegExp("(?:"+r.join("|")+")",L(n))}(e,t,n):function(e,t,n){return I(R(e,n),t,n)}(e,t,n)}g.parse=w,g.compile=b,g.tokensToFunction=E,g.tokensToRegExp=C;var S=Object.prototype.hasOwnProperty,N=new Map;function H(e){try{return decodeURIComponent(e)}catch(t){return e}}function B(e,t,n,r,o){var i=void 0,a=void 0,u=0,c=e.path||"";return"/"===c.charAt(0)&&(n&&(c=c.substr(1)),n=!0),{next:function(l){if(e===l)return{done:!0};var s=e.__children=e.__children||e.children;if(!i&&(i=function(e,t,n,r,o){var i=e+"|"+(n=!!n),a=N.get(i);if(!a){var u=[];a={keys:u,pattern:g(e,u,{end:n,strict:""===e})},N.set(i,a)}var c=a.pattern.exec(t);if(!c)return null;for(var l=Object.assign({},o),s=1;s<c.length;s++){var f=a.keys[s-1],d=f.name,h=c[s];void 0===h&&S.call(l,d)||(f.repeat?l[d]=h?h.split(f.delimiter).map(H):[]:l[d]=h?H(h):h)}return{path:c[0],keys:(r||[]).concat(a.keys),params:l}}(c,t,!s,r,o)))return{done:!1,value:{route:e,keys:i.keys,params:i.params}};if(i&&s)for(;u<s.length;){if(!a){var f=s[u];f.parent=e;var d=i.path.length;d>0&&"/"===t.charAt(d)&&(d+=1),a=B(f,t.substr(d),n,i.keys,i.params)}var h=a.next(l);if(!h.done)return{done:!1,value:h.value};a=null,u++}return{done:!0}}}}function $(e){if(h(e.route.action))return e.route.action(e)}N.set("|false",{keys:[],pattern:/(?:)/});var M=function(){function e(t){var r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};if(n(this,e),Object(t)!==t)throw new TypeError("Invalid routes");this.baseUrl=r.baseUrl||"",this.errorHandler=r.errorHandler,this.resolveRoute=r.resolveRoute||$,this.context=Object.assign({resolver:this},r.context),this.root=Array.isArray(t)?{path:"",__children:t,parent:null,__synthetic:!0}:t,this.root.parent=null}return r(e,[{key:"getRoutes",value:function(){return[].concat(a(this.root.__children))}},{key:"setRoutes",value:function(e){s(e);var t=[].concat(a(u(e)));this.root.__children=t}},{key:"addRoutes",value:function(e){var t;return s(e),(t=this.root.__children).push.apply(t,a(u(e))),this.getRoutes()}},{key:"removeRoutes",value:function(){this.setRoutes([])}},{key:"resolve",value:function(e){var t=this,n=Object.assign({},this.context,p(e)?{pathname:e}:e),r=B(this.root,n.pathname.substr(this.baseUrl.length)),o=this.resolveRoute,i=null,a=null,u=n;function c(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:i.value.route,l=null===arguments[2]&&i.value.route;if(i=a||r.next(l),a=null,!e&&(i.done||!function(e,t){for(var n=t;n;)if((n=n.parent)===e)return!0;return!1}(t,i.value.route)))return a=i,Promise.resolve(null);if(i.done){var s=new Error("Page not found ("+n.pathname+")");return s.context=n,s.code=404,Promise.reject(s)}return function(e,t){t&&!t.__synthetic&&(function(e,t){return!t.parent||!e||!e.length||e[e.length-1]!==t.parent}(e.chain,t)?e.chain=[t]:e.chain.push(t))}(n,i.value.route),u=Object.assign({},n,i.value),Promise.resolve(o(u)).then(function(n){return null!==n&&void 0!==n?(u.result=n.result||n,u):c(e,t,n)})}return n.next=c,Promise.resolve().then(function(){return c(!0,t.root)}).catch(function(e){var n=function(e){var t="Path '"+e.pathname+"' is not properly resolved due to an error.",n=(e.route||{}).path;return n&&(t+=" Resolution had failed on route: '"+n+"'"),t}(u);if(e?console.warn(n):e=new Error(n),e.context=e.context||u,e instanceof DOMException||(e.code=e.code||500),t.errorHandler)return u.result=t.errorHandler(e),u;throw e})}}]),e}();M.pathToRegexp=g;var D=[];function U(e){D.forEach(function(e){return e.inactivate()}),e.forEach(function(e){return e.activate()}),D=e}var W=function(e){var t=getComputedStyle(e).getPropertyValue("animation-name");return t&&"none"!==t},K=function(e,t){e.addEventListener("animationend",function n(){e.removeEventListener("animationend",n),t()})};function V(e,t){return e.classList.add(t),new Promise(function(n){if(W(e)){var r=e.getBoundingClientRect(),o="height: "+(r.bottom-r.top)+"px; width: "+(r.right-r.left)+"px";e.setAttribute("style","position: absolute; "+o),K(e,function(){e.classList.remove(t),e.removeAttribute("style"),n()})}else e.classList.remove(t),n()})}function F(e){return null!==e&&void 0!==e}function q(e,t){var n=Object.assign({},e.params);return{redirect:{pathname:t,from:e.pathname,params:n}}}function z(e,t){var n=e.route.__component||document.createElement(t),r=Object.assign({},e.params);return n.route={params:r,pathname:e.pathname},e.from&&(n.route.redirectFrom=e.from),e.route.__component=n,n}function G(e,t,n){if(h(e))return e.call(n,t)}function J(e,t,n){return function(r){if(r&&(r.cancel||r.redirect))return r;var o=n.__component;return o?G(o[e],Object.assign({cancel:function(){return{cancel:!0}}},t,{next:void 0}),o):void 0}}var Q=function(e){function t(e,r){n(this,t);var o=i(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,[],Object.assign({},r)));o.resolveRoute=function(e){return o.__resolveRoute(e)};var a=t.NavigationTrigger;return t.setTriggers.apply(t,Object.keys(a).map(function(e){return a[e]})),o.ready,o.ready=Promise.resolve(e),o.activeRoutes,o.activeRoutes=[],o.__lastStartedRenderId=0,o.__navigationEventHandler=o.__onNavigationEvent.bind(o),o.setOutlet(e),o.subscribe(),o}return o(t,M),r(t,[{key:"__resolveRoute",value:function(e){var t=e.route,n=G($,Object.assign({redirect:function(t){return q(e,t)},component:function(t){return z(e,t)}},e),t);if(F(n))return n;if(p(t.redirect))return q(e,t.redirect);var r=Promise.resolve();return t.bundle&&(r=r.then(function(){return e=t.bundle,n=p(e)?e:e.src,(r=document.head.querySelector('script[src="'+n+'"][async]'))&&r.parentNode===document.head?r.__dynamicImportLoaded?Promise.resolve():new Promise(function(e,t){var n=r.onload;r.onreadystatechange=r.onload=function(t){n(),e(t)};var o=r.onerror;r.onerror=function(e){o(),t(e)}}):new Promise(function(t,o){(r=document.createElement("script")).setAttribute("src",n),d(e)&&"module"===e.type&&r.setAttribute("type","module"),r.async=!0,r.onreadystatechange=r.onload=function(e){r.__dynamicImportLoaded=!0,t(e)},r.onerror=function(e){r.parentNode&&r.parentNode.removeChild(r),o(e)},document.head.appendChild(r)});var e,n,r}).catch(function(){throw new Error(c("Bundle not found: "+t.bundle+". Check if the file name is correct"))})),h(t.children)&&(r=r.then(function(){return t.children(Object.assign({},e,{next:void 0}))}).then(function(e){F(e)||h(t.children)||(e=t.children),function(e,t,n){if(F(e)&&!d(e))throw new Error(c("Expected 'children' method of the route with path '"+t.path+"' to return an object, but got: '"+e+"'"));t.__children=[];for(var r=u(e),o=0;o<r.length;o++)l(r[o]),t.__children.push(r[o])}(e,t)})),r.then(function(){return function(e,t){if(p(e.component))return z(t,e.component)}(t,e)})}},{key:"setOutlet",value:function(e){e&&this.__ensureOutlet(e),this.__outlet=e}},{key:"getOutlet",value:function(){return this.__outlet}},{key:"setRoutes",value:function(e){(function e(t,n,r){null===t&&(t=Function.prototype);var o=Object.getOwnPropertyDescriptor(t,n);if(void 0===o){var i=Object.getPrototypeOf(t);return null===i?void 0:e(i,n,r)}if("value"in o)return o.value;var a=o.get;return void 0!==a?a.call(r):void 0})(t.prototype.__proto__||Object.getPrototypeOf(t.prototype),"setRoutes",this).call(this,e),this.__onNavigationEvent()}},{key:"render",value:function(e,t){var n=this,r=++this.__lastStartedRenderId;return this.ready=this.resolve(e).then(function(e){return n.__fullyResolveChain(e,e)}).then(function(e){if(r===n.__lastStartedRenderId)return t&&n.__updateBrowserHistory(e.result.route.pathname,e.from),e!==n.__previousContext?n.__runOnAfterCallbacks(e,n.__previousContext,"onAfterLeave").then(function(){return n.__setOutletContent(e)}).then(function(){return n.__runOnAfterCallbacks(e,e,"onAfterEnter")}).then(function(){return e}):Promise.resolve(e)}).then(function(e){if(r===n.__lastStartedRenderId)return n.__animateIfNeeded(e)}).then(function(e){return r===n.__lastStartedRenderId&&n.__removeOldOutletContent(),n.__previousContext=e,n.activeRoutes=[].concat(a(e.chain)),f("route-changed",{router:n,params:e.params,pathname:e.pathname}),n.__outlet}).catch(function(o){if(r===n.__lastStartedRenderId)throw t&&n.__updateBrowserHistory(e),n.__removeOutletContent(),n.activeRoutes=[],f("error",{router:n,error:o}),o}),this.ready}},{key:"__fullyResolveChain",value:function(e,t){var n=this;return this.__amendWithResolutionResult(t).then(function(r){var o=r!==t?r:e;return r.next().then(function(e){return e?n.__fullyResolveChain(o,e):n.__amendWithLifecycleCallbacks(o)})})}},{key:"__amendWithResolutionResult",value:function(e){var t=this,n=e.result;return n instanceof HTMLElement?Promise.resolve(e):n.redirect?this.__redirect(n.redirect,e.__redirectCount).then(function(e){return t.__amendWithResolutionResult(e)}):n instanceof Error?Promise.reject(n):Promise.reject(new Error(c('Invalid route resolution result for path "'+e.pathname+'". Expected redirect object or HTML element, but got: "'+n+'". Double check the action return value for the route.')))}},{key:"__amendWithLifecycleCallbacks",value:function(e){var t=this;return this.__runLifecycleCallbacks(e).then(function(n){return n===t.__previousContext||n===e?n:t.__fullyResolveChain(n,n)})}},{key:"__runLifecycleCallbacks",value:function(e){var t=this,n=(this.__previousContext||{}).chain,r=e.chain,o=Promise.resolve();if(e.__divergedChainIndex=0,n&&n.length){for(;e.__divergedChainIndex<Math.min(n.length,r.length)&&n[e.__divergedChainIndex]===r[e.__divergedChainIndex];e.__divergedChainIndex++);for(var i=n.length-1;i>=e.__divergedChainIndex;i--)o=o.then(J("onBeforeLeave",e,n[i])).then(function(e){if(!(e||{}).redirect)return e})}for(var a=Object.assign({redirect:function(t){return q(e,t)}},e),u=e.__divergedChainIndex;u<r.length;u++)o=o.then(J("onBeforeEnter",a,r[u]));return o.then(function(n){if(n){if(n.cancel)return t.__previousContext;if(n.redirect)return t.__redirect(n.redirect,e.__redirectCount)}return e})}},{key:"__redirect",value:function(e,n){if(n>256)throw new Error(c("Too many redirects when rendering "+e.from));return this.resolve({pathname:t.pathToRegexp.compile(e.pathname)(e.params),from:e.from,__redirectCount:(n||0)+1})}},{key:"__ensureOutlet",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.__outlet;if(!(e instanceof Node))throw new TypeError(c("Expected router outlet to be a valid DOM Node (but got "+e+")"))}},{key:"__updateBrowserHistory",value:function(e,t){var n=e.pathname||e;if(window.location.pathname!==n){var r=t?"replaceState":"pushState";window.history[r](null,document.title,n),window.dispatchEvent(new PopStateEvent("popstate",{state:"vaadin-router-ignore"}))}}},{key:"__setOutletContent",value:function(e){function t(e,t){for(var n=0;n<e.length;n++)if(e[n]===t)return!0;return!1}this.__removePendingContent(),this.__ensureOutlet();var n=this.__outlet;if(e)for(var r=0;r<e.__divergedChainIndex;r++){var o=e.chain[r].__component;if(o){if(!t(n.children||[],o))break;n=o}}if(this.__oldContent=Array.from(n.childNodes),this.__newContent=[],e)for(var i=n,a=e.__divergedChainIndex;a<e.chain.length;a++){var u=e.chain[a].__component;u&&(i.appendChild(u),i=u,this.__newContent.push(u))}}},{key:"__removeOldOutletContent",value:function(){this.__oldContent&&this.__oldContent.length&&this.__removeOutletContent(this.__oldContent),this.__oldContent=null,this.__newContent=null}},{key:"__removePendingContent",value:function(){this.__oldContent&&this.__newContent&&(this.__oldContent=this.__newContent,this.__removeOldOutletContent())}},{key:"__removeOutletContent",value:function(e){if((e=e||this.__outlet&&this.__outlet.children)&&e.length)for(var t=e[0].parentNode,n=0;n<e.length;n+=1)t.removeChild(e[n])}},{key:"__runOnAfterCallbacks",value:function(e,t,n){var r=Promise.resolve();return t&&function(){for(var o=Object.assign({},e,{next:void 0}),i=function(e){var i=t.chain[e].__component||{};r=r.then(function(){return G(i[n],o,i)})},a=e.__divergedChainIndex;a<t.chain.length;a++)i(a)}(),r}},{key:"__animateIfNeeded",value:function(e){for(var t=this.__oldContent&&this.__oldContent[0],n=this.__newContent&&this.__newContent[0],r=[],o=e.chain,i=void 0,a=o.length;a>0;a--)if(o[a-1].animate){i=o[a-1].animate;break}if(t&&n&&i){var u=d(i),c=u&&i.leave||"leaving",l=u&&i.enter||"entering";r.push(V(t,c)),r.push(V(n,l))}return r.length?new Promise(function(t){Promise.all(r).then(function(){return t(e)})}):e}},{key:"subscribe",value:function(){window.addEventListener("vaadin-router-go",this.__navigationEventHandler)}},{key:"unsubscribe",value:function(){window.removeEventListener("vaadin-router-go",this.__navigationEventHandler)}},{key:"__onNavigationEvent",value:function(e){var t=e?e.detail.pathname:window.location.pathname;this.render(t,!0)}}],[{key:"setTriggers",value:function(){for(var e=arguments.length,t=Array(e),n=0;n<e;n++)t[n]=arguments[n];U(t)}},{key:"go",value:function(e){f("go",{pathname:e})}}]),t}(),X=function(e){function t(){return n(this,t),i(this,(t.__proto__||Object.getPrototypeOf(t)).apply(this,arguments))}return o(t,e),r(t,null,[{key:"is",get:function(){return"vaadin-router-meta"}},{key:"version",get:function(){return"0.3.0"}}]),t}(HTMLElement);customElements.define(X.is,X),Q.NavigationTrigger={POPSTATE:y,CLICK:_},e.Router=Q,e.Resolver=M,Object.defineProperty(e,"__esModule",{value:!0})});
!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?t(exports):"function"==typeof define&&define.amd?define(["exports"],t):t(e.Vaadin=e.Vaadin||{})}(this,function(e){"use strict";var t="function"==typeof Symbol&&"symbol"==typeof Symbol.iterator?function(e){return typeof e}:function(e){return e&&"function"==typeof Symbol&&e.constructor===Symbol&&e!==Symbol.prototype?"symbol":typeof e},n=function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")},r=function(){function e(e,t){for(var n=0;n<t.length;n++){var r=t[n];r.enumerable=r.enumerable||!1,r.configurable=!0,"value"in r&&(r.writable=!0),Object.defineProperty(e,r.key,r)}}return function(t,n,r){return n&&e(t.prototype,n),r&&e(t,r),t}}(),o=function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(Object.setPrototypeOf?Object.setPrototypeOf(e,t):e.__proto__=t)},i=function(e,t){if(!e)throw new ReferenceError("this hasn't been initialised - super() hasn't been called");return!t||"object"!=typeof t&&"function"!=typeof t?e:t},a=function(e){if(Array.isArray(e)){for(var t=0,n=Array(e.length);t<e.length;t++)n[t]=e[t];return n}return Array.from(e)};function u(e){return e=e||[],Array.isArray(e)?e:[e]}function c(e){return"[Vaadin.Router] "+e}var l="module",s="nomodule",f=[l,s];function h(e){if(!e.match(/.+\.[m]?js$/))throw new Error(c('Unsupported type for bundle "'+e+'": .js or .mjs expected.'))}function p(e){if(!e||!y(e.path))throw new Error(c('Expected route config to be an object with a "path" string property, or an array of such objects'));var t=e.bundle,n=["component","redirect","bundle"];if(!(g(e.action)||Array.isArray(e.children)||g(e.children)||m(t)||n.some(function(t){return y(e[t])})))throw new Error(c('Expected route config "'+e.path+'" to include either "'+n.join('", "')+'" or "action" function but none found.'));if(t)if(y(t))h(t);else{if(!f.some(function(e){return e in t}))throw new Error(c('Expected route bundle to include either "'+s+'" or "'+l+'" keys, or both'));f.forEach(function(e){return e in t&&h(t[e])})}e.redirect&&["bundle","component"].forEach(function(t){t in e&&console.warn(c('Route config "'+e.path+'" has both "redirect" and "'+t+'" properties, and "redirect" will always override the latter. Did you mean to only use "'+t+'"?'))})}function d(e){u(e).forEach(function(e){return p(e)})}function v(e,t){var n=document.head.querySelector('script[src="'+e+'"][async]');return n||((n=document.createElement("script")).setAttribute("src",e),t===l?n.setAttribute("type",l):t===s&&n.setAttribute(s,""),n.async=!0),new Promise(function(e,t){n.onreadystatechange=n.onload=function(t){n.__dynamicImportLoaded=!0,e(t)},n.onerror=function(e){n.parentNode&&n.parentNode.removeChild(n),t(e)},null===n.parentNode?document.head.appendChild(n):n.__dynamicImportLoaded&&e()})}function _(e,t){window.dispatchEvent(new CustomEvent("vaadin-router-"+e,{detail:t}))}function m(e){return"object"===(void 0===e?"undefined":t(e))&&!!e}function g(e){return"function"==typeof e}function y(e){return"string"==typeof e}function b(e){var t=new Error(c("Page not found ("+e.pathname+")"));return t.context=e,t.code=404,t}function w(e){if(!e.defaultPrevented&&0===e.button&&!(e.shiftKey||e.ctrlKey||e.altKey||e.metaKey)){for(var t=e.target,n=e.composedPath?e.composedPath():e.path||[],r=0;r<n.length;r++){var o=n[r];if(o.nodeName&&"a"===o.nodeName.toLowerCase()){t=o;break}}for(;t&&"a"!==t.nodeName.toLowerCase();)t=t.parentNode;if(t&&"a"===t.nodeName.toLowerCase())if(!t.target||"_self"===t.target.toLowerCase())if(!t.hasAttribute("download"))if(t.pathname!==window.location.pathname||""===t.hash)(t.origin||function(e){var t=e.port,n=e.protocol;return n+"//"+("http:"===n&&"80"===t||"https:"===n&&"443"===t?e.hostname:e.host)}(t))===window.location.origin&&(e.preventDefault(),_("go",{pathname:t.pathname}))}}var E={activate:function(){window.document.addEventListener("click",w)},inactivate:function(){window.document.removeEventListener("click",w)}};function C(e){"vaadin-router-ignore"!==e.state&&_("go",{pathname:window.location.pathname})}/Trident/.test(navigator.userAgent)&&!g(window.PopStateEvent)&&(window.PopStateEvent=function(e,t){t=t||{};var n=document.createEvent("Event");return n.initEvent(e,Boolean(t.bubbles),Boolean(t.cancelable)),n.state=t.state||null,n},window.PopStateEvent.prototype=window.Event.prototype);var x={activate:function(){window.addEventListener("popstate",C)},inactivate:function(){window.removeEventListener("popstate",C)}},k=D,O=I,R=function(e,t){return S(I(e,t))},A=S,j=$,P="/",L="./",T=new RegExp(["(\\\\.)","(?:\\:(\\w+)(?:\\(((?:\\\\.|[^\\\\()])+)\\))?|\\(((?:\\\\.|[^\\\\()])+)\\))([+*?])?"].join("|"),"g");function I(e,t){for(var n,r=[],o=0,i=0,a="",u=t&&t.delimiter||P,c=t&&t.delimiters||L,l=!1;null!==(n=T.exec(e));){var s=n[0],f=n[1],h=n.index;if(a+=e.slice(i,h),i=h+s.length,f)a+=f[1],l=!0;else{var p="",d=e[i],v=n[2],_=n[3],m=n[4],g=n[5];if(!l&&a.length){var y=a.length-1;c.indexOf(a[y])>-1&&(p=a[y],a=a.slice(0,y))}a&&(r.push(a),a="",l=!1);var b=""!==p&&void 0!==d&&d!==p,w="+"===g||"*"===g,E="?"===g||"*"===g,C=p||u,x=_||m;r.push({name:v||o++,prefix:p,delimiter:C,optional:E,repeat:w,partial:b,pattern:x?B(x):"[^"+N(C)+"]+?"})}}return(a||i<e.length)&&r.push(a+e.substr(i)),r}function S(e){for(var n=new Array(e.length),r=0;r<e.length;r++)"object"===t(e[r])&&(n[r]=new RegExp("^(?:"+e[r].pattern+")$"));return function(t,r){for(var o="",i=r&&r.encode||encodeURIComponent,a=0;a<e.length;a++){var u=e[a];if("string"!=typeof u){var c,l=t?t[u.name]:void 0;if(Array.isArray(l)){if(!u.repeat)throw new TypeError('Expected "'+u.name+'" to not repeat, but got array');if(0===l.length){if(u.optional)continue;throw new TypeError('Expected "'+u.name+'" to not be empty')}for(var s=0;s<l.length;s++){if(c=i(l[s],u),!n[a].test(c))throw new TypeError('Expected all "'+u.name+'" to match "'+u.pattern+'"');o+=(0===s?u.prefix:u.delimiter)+c}}else if("string"!=typeof l&&"number"!=typeof l&&"boolean"!=typeof l){if(!u.optional)throw new TypeError('Expected "'+u.name+'" to be '+(u.repeat?"an array":"a string"));u.partial&&(o+=u.prefix)}else{if(c=i(String(l),u),!n[a].test(c))throw new TypeError('Expected "'+u.name+'" to match "'+u.pattern+'", but got "'+c+'"');o+=u.prefix+c}}else o+=u}return o}}function N(e){return e.replace(/([.+*?=^!:${}()[\]|/\\])/g,"\\$1")}function B(e){return e.replace(/([=!:$/()])/g,"\\$1")}function H(e){return e&&e.sensitive?"":"i"}function $(e,t,n){for(var r=(n=n||{}).strict,o=!1!==n.end,i=N(n.delimiter||P),a=n.delimiters||L,u=[].concat(n.endsWith||[]).map(N).concat("$").join("|"),c="",l=!1,s=0;s<e.length;s++){var f=e[s];if("string"==typeof f)c+=N(f),l=s===e.length-1&&a.indexOf(f[f.length-1])>-1;else{var h=N(f.prefix),p=f.repeat?"(?:"+f.pattern+")(?:"+h+"(?:"+f.pattern+"))*":f.pattern;t&&t.push(f),f.optional?f.partial?c+=h+"("+p+")?":c+="(?:"+h+"("+p+"))?":c+=h+"("+p+")"}}return o?(r||(c+="(?:"+i+")?"),c+="$"===u?"$":"(?="+u+")"):(r||(c+="(?:"+i+"(?="+u+"))?"),l||(c+="(?="+i+"|"+u+")")),new RegExp("^"+c,H(n))}function D(e,t,n){return e instanceof RegExp?function(e,t){if(!t)return e;var n=e.source.match(/\((?!\?)/g);if(n)for(var r=0;r<n.length;r++)t.push({name:r,prefix:null,delimiter:null,optional:!1,repeat:!1,partial:!1,pattern:null});return e}(e,t):Array.isArray(e)?function(e,t,n){for(var r=[],o=0;o<e.length;o++)r.push(D(e[o],t,n).source);return new RegExp("(?:"+r.join("|")+")",H(n))}(e,t,n):function(e,t,n){return $(I(e,n),t,n)}(e,t,n)}k.parse=O,k.compile=R,k.tokensToFunction=A,k.tokensToRegExp=j;var M=Object.prototype.hasOwnProperty,F=new Map;function U(e){try{return decodeURIComponent(e)}catch(t){return e}}function W(e,t,n,r,o){var i=void 0,a=void 0,u=0,c=e.path||"";return"/"===c.charAt(0)&&(n&&(c=c.substr(1)),n=!0),{next:function(l){if(e===l)return{done:!0};var s=e.__children=e.__children||e.children;if(!i&&(i=function(e,t,n,r,o){var i=e+"|"+(n=!!n),a=F.get(i);if(!a){var u=[];a={keys:u,pattern:k(e,u,{end:n,strict:""===e})},F.set(i,a)}var c=a.pattern.exec(t);if(!c)return null;for(var l=Object.assign({},o),s=1;s<c.length;s++){var f=a.keys[s-1],h=f.name,p=c[s];void 0===p&&M.call(l,h)||(f.repeat?l[h]=p?p.split(f.delimiter).map(U):[]:l[h]=p?U(p):p)}return{path:c[0],keys:(r||[]).concat(a.keys),params:l}}(c,t,!s,r,o)))return{done:!1,value:{route:e,keys:i.keys,params:i.params,path:i.path}};if(i&&s)for(;u<s.length;){if(!a){var f=s[u];f.parent=e;var h=i.path.length;h>0&&"/"===t.charAt(h)&&(h+=1),a=W(f,t.substr(h),n,i.keys,i.params)}var p=a.next(l);if(!p.done)return{done:!1,value:p.value};a=null,u++}return{done:!0}}}}function K(e){if(g(e.route.action))return e.route.action(e)}F.set("|false",{keys:[],pattern:/(?:)/});var V=function(){function e(t){var r=arguments.length>1&&void 0!==arguments[1]?arguments[1]:{};if(n(this,e),Object(t)!==t)throw new TypeError("Invalid routes");this.baseUrl=r.baseUrl||"",this.errorHandler=r.errorHandler,this.resolveRoute=r.resolveRoute||K,this.context=Object.assign({resolver:this},r.context),this.root=Array.isArray(t)?{path:"",__children:t,parent:null,__synthetic:!0}:t,this.root.parent=null}return r(e,[{key:"getRoutes",value:function(){return[].concat(a(this.root.__children))}},{key:"setRoutes",value:function(e){d(e);var t=[].concat(a(u(e)));this.root.__children=t}},{key:"addRoutes",value:function(e){var t;return d(e),(t=this.root.__children).push.apply(t,a(u(e))),this.getRoutes()}},{key:"removeRoutes",value:function(){this.setRoutes([])}},{key:"resolve",value:function(e){var t=this,n=Object.assign({},this.context,y(e)?{pathname:e}:e),r=W(this.root,n.pathname.substr(this.baseUrl.length)),o=this.resolveRoute,i=null,a=null,u=n;function c(e){var t=arguments.length>1&&void 0!==arguments[1]?arguments[1]:i.value.route,l=null===arguments[2]&&i.value.route;return i=a||r.next(l),a=null,e||!i.done&&function(e,t){for(var n=t;n;)if((n=n.parent)===e)return!0;return!1}(t,i.value.route)?i.done?Promise.reject(b(n)):(function(e,t){var n=t.route,r=t.path;if(n&&!n.__synthetic){var o={path:r,route:n};!function(e,t){return!t.parent||!e||!e.length||e[e.length-1].route!==t.parent}(e.chain,n)?e.chain.push(o):e.chain=[o]}}(n,i.value),u=Object.assign({},n,i.value),Promise.resolve(o(u)).then(function(n){return null!==n&&void 0!==n?(u.result=n.result||n,u):c(e,t,n)})):(a=i,Promise.resolve(null))}return n.next=c,Promise.resolve().then(function(){return c(!0,t.root)}).catch(function(e){var n=function(e){var t="Path '"+e.pathname+"' is not properly resolved due to an error.",n=(e.route||{}).path;return n&&(t+=" Resolution had failed on route: '"+n+"'"),t}(u);if(e?console.warn(n):e=new Error(n),e.context=e.context||u,e instanceof DOMException||(e.code=e.code||500),t.errorHandler)return u.result=t.errorHandler(e),u;throw e})}}]),e}();V.pathToRegexp=k;var q=[];function z(e){q.forEach(function(e){return e.inactivate()}),e.forEach(function(e){return e.activate()}),q=e}var G=function(e){var t=getComputedStyle(e).getPropertyValue("animation-name");return t&&"none"!==t},J=function(e,t){e.addEventListener("animationend",function n(){e.removeEventListener("animationend",n),t()})};function Q(e,t){return e.classList.add(t),new Promise(function(n){if(G(e)){var r=e.getBoundingClientRect(),o="height: "+(r.bottom-r.top)+"px; width: "+(r.right-r.left)+"px";e.setAttribute("style","position: absolute; "+o),J(e,function(){e.classList.remove(t),e.removeAttribute("style"),n()})}else e.classList.remove(t),n()})}function X(e){return null!==e&&void 0!==e}function Y(e,t){var n=e.pathname,r=void 0===n?"":n,o=e.chain,i=void 0===o?[]:o,a=e.params,u=void 0===a?{}:a,c=e.redirectFrom;return{pathname:r,routes:i.map(function(e){return e.route}),route:!t&&i.length&&i[i.length-1].route||t,params:u,redirectFrom:c}}function Z(e,t){var n=Object.assign({},e.params);return{redirect:{pathname:t,from:e.pathname,params:n}}}function ee(e,t,n){if(g(e))return e.apply(n,t)}function te(e,t,n){return function(r){return r&&(r.cancel||r.redirect)?r:n?ee(n[e],t,n):void 0}}function ne(e){if(e&&e.length)for(var t=e[0].parentNode,n=0;n<e.length;n++)t.removeChild(e[n])}var re=function(e){function t(e,r){n(this,t);var o=i(this,(t.__proto__||Object.getPrototypeOf(t)).call(this,[],Object.assign({},r)));o.resolveRoute=function(e){return o.__resolveRoute(e)};var a=t.NavigationTrigger;return t.setTriggers.apply(t,Object.keys(a).map(function(e){return a[e]})),o.ready,o.ready=Promise.resolve(e),o.location,o.location=Y({}),o.__lastStartedRenderId=0,o.__navigationEventHandler=o.__onNavigationEvent.bind(o),o.setOutlet(e),o.subscribe(),o}return o(t,V),r(t,[{key:"__resolveRoute",value:function(e){var t=e.route,n={redirect:function(t){return Z(e,t)},component:function(t){return function(e,t){var n=document.createElement(t);n.location=Y(e);var r=e.chain.map(function(e){return e.route}).indexOf(e.route);return e.chain[r].element=n,n}(e,t)}},r=ee(t.action,[e,n],t);if(X(r))return r;if(y(t.redirect))return n.redirect(t.redirect);var o=Promise.resolve();return t.bundle&&(o=o.then(function(){return y(e=t.bundle)?v(e):Promise.race(f.filter(function(t){return t in e}).map(function(t){return v(e[t],t)}));var e}).catch(function(){throw new Error(c("Bundle not found: "+t.bundle+". Check if the file name is correct"))})),g(t.children)&&(o=o.then(function(){return t.children(function(e){var t=Object.assign({},e);return delete t.next,t}(e))}).then(function(e){X(e)||g(t.children)||(e=t.children),function(e,t){if(!Array.isArray(e)&&!m(e))throw new Error(c('Incorrect "children" value for the route '+t.path+": expected array or object, but got "+e));t.__children=[];for(var n=u(e),r=0;r<n.length;r++)p(n[r]),t.__children.push(n[r])}(e,t)})),o.then(function(){if(y(t.component))return n.component(t.component)})}},{key:"setOutlet",value:function(e){e&&this.__ensureOutlet(e),this.__outlet=e}},{key:"getOutlet",value:function(){return this.__outlet}},{key:"setRoutes",value:function(e){(function e(t,n,r){null===t&&(t=Function.prototype);var o=Object.getOwnPropertyDescriptor(t,n);if(void 0===o){var i=Object.getPrototypeOf(t);return null===i?void 0:e(i,n,r)}if("value"in o)return o.value;var a=o.get;return void 0!==a?a.call(r):void 0})(t.prototype.__proto__||Object.getPrototypeOf(t.prototype),"setRoutes",this).call(this,e),this.__onNavigationEvent()}},{key:"render",value:function(e,t){var n=this,r=++this.__lastStartedRenderId,o=e.pathname||e;return this.ready=this.resolve(e).then(function(e){return n.__fullyResolveChain(e)}).then(function(e){if(r===n.__lastStartedRenderId){var o=n.__previousContext;if(e===o)return n.location;t&&n.__updateBrowserHistory(e.pathname,e.redirectFrom),n.__addAppearingContent(e,o);var i=n.__animateIfNeeded(e);return n.__runOnAfterEnterCallbacks(e),n.__runOnAfterLeaveCallbacks(e,o),i.then(function(){if(r===n.__lastStartedRenderId)return n.__removeDisappearingContent(),n.__previousContext=e,n.location=Y(e),_("location-changed",{router:n,location:n.location}),n.location})}}).catch(function(e){if(r===n.__lastStartedRenderId)throw t&&n.__updateBrowserHistory(o),ne(n.__outlet&&n.__outlet.children),n.location=Y({pathname:o}),_("error",{router:n,error:e,pathname:o}),e}),this.ready}},{key:"__fullyResolveChain",value:function(e){var t=this,n=arguments.length>1&&void 0!==arguments[1]?arguments[1]:e;return this.__amendWithResolutionResult(n).then(function(r){var o=r!==n?r:e;return r.next().then(function(e){if(null===e&&r.pathname!==r.chain.map(function(e){return e.path}).reduce(function(e,t){return t.length?"/"===e?e+t:e+"/"+t:e}))throw b(o);return e?t.__fullyResolveChain(o,e):t.__amendWithOnBeforeCallbacks(o)})})}},{key:"__amendWithResolutionResult",value:function(e){var t=this,n=e.result;return n instanceof HTMLElement?Promise.resolve(e):n.redirect?this.__redirect(n.redirect,e.__redirectCount).then(function(e){return t.__amendWithResolutionResult(e)}):n instanceof Error?Promise.reject(n):Promise.reject(new Error(c('Invalid route resolution result for path "'+e.pathname+'". Expected redirect object or HTML element, but got: "'+n+'". Double check the action return value for the route.')))}},{key:"__amendWithOnBeforeCallbacks",value:function(e){var t=this;return this.__runOnBeforeCallbacks(e).then(function(n){return n===t.__previousContext||n===e?n:t.__fullyResolveChain(n)})}},{key:"__runOnBeforeCallbacks",value:function(e){var t=this,n=(this.__previousContext||{}).chain||[],r=e.chain,o=Promise.resolve(),i=function(){return{cancel:!0}},a=function(t){return Z(e,t)};if(e.__divergedChainIndex=0,n.length){for(var u=0;u<Math.min(n.length,r.length)&&(n[u].route===r[u].route&&n[u].path===r[u].path);u=++e.__divergedChainIndex);for(var c=n.length-1;c>=e.__divergedChainIndex;c--){var l=Y(e);o=o.then(te("onBeforeLeave",[l,{prevent:i},this],n[c].element)).then(function(e){if(!(e||{}).redirect)return e})}}for(var s=e.__divergedChainIndex;s<r.length;s++){var f=Y(e,r[s].route);o=o.then(te("onBeforeEnter",[f,{prevent:i,redirect:a},this],r[s].element))}return o.then(function(n){if(n){if(n.cancel)return t.__previousContext;if(n.redirect)return t.__redirect(n.redirect,e.__redirectCount)}return e})}},{key:"__redirect",value:function(e,n){if(n>256)throw new Error(c("Too many redirects when rendering "+e.from));return this.resolve({pathname:t.pathToRegexp.compile(e.pathname)(e.params),redirectFrom:e.from,__redirectCount:(n||0)+1})}},{key:"__ensureOutlet",value:function(){var e=arguments.length>0&&void 0!==arguments[0]?arguments[0]:this.__outlet;if(!(e instanceof Node))throw new TypeError(c("Expected router outlet to be a valid DOM Node (but got "+e+")"))}},{key:"__updateBrowserHistory",value:function(e,t){if(window.location.pathname!==e){var n=t?"replaceState":"pushState";window.history[n](null,document.title,e),window.dispatchEvent(new PopStateEvent("popstate",{state:"vaadin-router-ignore"}))}}},{key:"__addAppearingContent",value:function(e,t){this.__ensureOutlet(),this.__removeAppearingContent();for(var n=this.__outlet,r=0;r<e.__divergedChainIndex;r++){var o=t&&t.chain[r].element;if(o){if(o.parentNode!==n)break;e.chain[r].element=o,n=o}}this.__disappearingContent=Array.from(n.children),this.__appearingContent=[];for(var i=n,a=e.__divergedChainIndex;a<e.chain.length;a++){var u=e.chain[a].element;u&&(i.appendChild(u),i===n&&this.__appearingContent.push(u),i=u)}}},{key:"__removeDisappearingContent",value:function(){this.__disappearingContent&&ne(this.__disappearingContent),this.__disappearingContent=null,this.__appearingContent=null}},{key:"__removeAppearingContent",value:function(){this.__disappearingContent&&this.__appearingContent&&(ne(this.__appearingContent),this.__disappearingContent=null,this.__appearingContent=null)}},{key:"__runOnAfterLeaveCallbacks",value:function(e,t){if(t)for(var n=t.chain.length-1;n>=e.__divergedChainIndex;n--){var r=t.chain[n].element;if(r)try{var o=Y(e);ee(r.onAfterLeave,[o,{},t.resolver],r)}finally{ne(r.children)}}}},{key:"__runOnAfterEnterCallbacks",value:function(e){for(var t=e.__divergedChainIndex;t<e.chain.length;t++){var n=e.chain[t].element||{},r=Y(e,e.chain[t].route);ee(n.onAfterEnter,[r,{},e.resolver],n)}}},{key:"__animateIfNeeded",value:function(e){for(var t=(this.__disappearingContent||[])[0],n=(this.__appearingContent||[])[0],r=[],o=e.chain,i=void 0,a=o.length;a>0;a--)if(o[a-1].route.animate){i=o[a-1].route.animate;break}if(t&&n&&i){var u=m(i)&&i.leave||"leaving",c=m(i)&&i.enter||"entering";r.push(Q(t,u)),r.push(Q(n,c))}return Promise.all(r).then(function(){return e})}},{key:"subscribe",value:function(){window.addEventListener("vaadin-router-go",this.__navigationEventHandler)}},{key:"unsubscribe",value:function(){window.removeEventListener("vaadin-router-go",this.__navigationEventHandler)}},{key:"__onNavigationEvent",value:function(e){var t=e?e.detail.pathname:window.location.pathname;this.render(t,!0)}}],[{key:"setTriggers",value:function(){for(var e=arguments.length,t=Array(e),n=0;n<e;n++)t[n]=arguments[n];z(t)}},{key:"go",value:function(e){_("go",{pathname:e})}}]),t}(),oe=function(e){function t(){return n(this,t),i(this,(t.__proto__||Object.getPrototypeOf(t)).apply(this,arguments))}return o(t,e),r(t,null,[{key:"is",get:function(){return"vaadin-router-meta"}},{key:"version",get:function(){return"0.3.0"}}]),t}(HTMLElement);customElements.define(oe.is,oe),re.NavigationTrigger={POPSTATE:x,CLICK:E},e.Router=re,e.Resolver=V,Object.defineProperty(e,"__esModule",{value:!0})});
//# sourceMappingURL=vaadin-router.umd.min.js.map
{
"name": "@vaadin/router",
"version": "0.4.0",
"version": "1.0.0-rc.0",
"description": "Small and powerful client-side router for Web Components. Framework-agnostic.",
"main": "dist/vaadin-router.umd.js",
"browser": "dist/vaadin-router.js",
"main": "dist/vaadin-router.js",
"repository": "vaadin/vaadin-router",

@@ -48,3 +47,3 @@ "keywords": [

"path": "dist/vaadin-router.min.js",
"maxSize": "6 kB"
"maxSize": "6.5 kB"
}

@@ -51,0 +50,0 @@ ],

@@ -143,2 +143,6 @@ /**

*
* This callback is called asynchronously after the native
* [`connectedCallback()`](https://html.spec.whatwg.org/multipage/custom-elements.html#custom-element-reactions)
* defined by the Custom Elements spec.
*
* @param context the context object with the following properties:

@@ -156,7 +160,4 @@ *

// user implementation example:
return new Promise(resolve => {
sendVisitStatistics();
resolve();
});
sendVisitStatistics();
}
}

@@ -87,2 +87,3 @@ /**

params: match.params,
path: match.path
},

@@ -89,0 +90,0 @@ };

@@ -13,3 +13,3 @@ /**

import resolveRoute from './resolveRoute.js';
import {toArray, ensureRoutes, isString} from '../utils.js';
import {toArray, ensureRoutes, isString, getNotFoundError} from '../utils.js';

@@ -36,12 +36,14 @@ function isChildRoute(parentRoute, childRoute) {

function addRouteToChain(context, newRoute) {
function shouldDiscardOldChain(oldChain, newRoute) {
return !newRoute.parent || !oldChain || !oldChain.length || oldChain[oldChain.length - 1] !== newRoute.parent;
function addRouteToChain(context, match) {
const {route, path} = match;
function shouldDiscardOldChain(oldChain, route) {
return !route.parent || !oldChain || !oldChain.length || oldChain[oldChain.length - 1].route !== route.parent;
}
if (newRoute && !newRoute.__synthetic) {
if (shouldDiscardOldChain(context.chain, newRoute)) {
context.chain = [newRoute];
if (route && !route.__synthetic) {
const item = {path, route};
if (shouldDiscardOldChain(context.chain, route)) {
context.chain = [item];
} else {
context.chain.push(newRoute);
context.chain.push(item);
}

@@ -158,9 +160,6 @@ }

if (matches.done) {
const error = new Error(`Page not found (${context.pathname})`);
error.context = context;
error.code = 404;
return Promise.reject(error);
return Promise.reject(getNotFoundError(context));
}
addRouteToChain(context, matches.value.route);
addRouteToChain(context, matches.value);
currentContext = Object.assign({}, context, matches.value);

@@ -167,0 +166,0 @@

import Resolver from './resolver/resolver.js';
import {default as processAction} from './resolver/resolveRoute.js';
import setNavigationTriggers from './triggers/setNavigationTriggers.js';

@@ -14,2 +13,3 @@ import animate from './transitions/animate.js';

isObject,
getNotFoundError,
} from './utils.js';

@@ -23,3 +23,19 @@

function redirect(context, pathname) {
function copyContextWithoutNext(context) {
const copy = Object.assign({}, context);
delete copy.next;
return copy;
}
function createLocation({pathname = '', chain = [], params = {}, redirectFrom}, route) {
return {
pathname,
routes: chain.map(item => item.route),
route: (!route && chain.length && chain[chain.length - 1].route) || route,
params,
redirectFrom,
};
}
function createRedirect(context, pathname) {
const params = Object.assign({}, context.params);

@@ -36,19 +52,16 @@ return {

function renderComponent(context, component) {
const element = context.route.__component || document.createElement(component);
const params = Object.assign({}, context.params);
element.route = {params, pathname: context.pathname};
if (context.from) {
element.route.redirectFrom = context.from;
}
context.route.__component = element;
const element = document.createElement(component);
element.location = createLocation(context);
const index = context.chain.map(item => item.route).indexOf(context.route);
context.chain[index].element = element;
return element;
}
function runCallbackIfPossible(callback, context, thisObject) {
function runCallbackIfPossible(callback, args, thisArg) {
if (isFunction(callback)) {
return callback.call(thisObject, context);
return callback.apply(thisArg, args);
}
}
function amend(amendmentFunction, context, route) {
function amend(amendmentFunction, args, element) {
return amendmentResult => {

@@ -59,6 +72,4 @@ if (amendmentResult && (amendmentResult.cancel || amendmentResult.redirect)) {

const component = route.__component;
if (component) {
return runCallbackIfPossible(component[amendmentFunction],
Object.assign({cancel: () => ({cancel: true})}, context, {next: undefined}), component);
if (element) {
return runCallbackIfPossible(element[amendmentFunction], args, element);
}

@@ -68,6 +79,9 @@ };

function processNewChildren(newChildren, route, context) {
if (isResultNotEmpty(newChildren) && !isObject(newChildren)) {
throw new Error(log(`Expected 'children' method of the route with path '${route.path}' `
+ `to return an object, but got: '${newChildren}'`));
function processNewChildren(newChildren, route) {
if (!Array.isArray(newChildren) && !isObject(newChildren)) {
throw new Error(
log(
`Incorrect "children" value for the route ${route.path}: expected array or object, but got ${newChildren}`
)
);
}

@@ -83,8 +97,20 @@

function processComponent(route, context) {
if (isString(route.component)) {
return renderComponent(context, route.component);
function removeDomNodes(nodes) {
if (nodes && nodes.length) {
const parent = nodes[0].parentNode;
for (let i = 0; i < nodes.length; i++) {
parent.removeChild(nodes[i]);
}
}
}
function getMatchedPath(chain) {
return chain.map(item => item.path).reduce((prev, path) => {
if (path.length) {
return prev === '/' ? prev + path : prev + '/' + path;
}
return prev;
});
}
/**

@@ -142,3 +168,3 @@ * A simple client-side router for single-page applications. It uses

* @public
* @type {!Promise<?Node>}
* @type {!Promise<!Vaadin.Router.Location>}
*/

@@ -149,12 +175,12 @@ this.ready;

/**
* A read-only list of the currently active routes (starting from the root
* down to a leaf of the routes config tree). The list is initially empty
* and gets updated after each _completed_ render call. When a render fails
* the `activeRoutes` is set to an empty list.
* Contains read-only information about the current router location:
* pathname, active routes, parameters. See the
* [Location type declaration](#/classes/Vaadin.Router.Location)
* for more details.
*
* @public
* @type {!Array<Route>}
* @type {!Vaadin.Router.Location}
*/
this.activeRoutes;
this.activeRoutes = [];
this.location;
this.location = createLocation({});

@@ -170,7 +196,7 @@ this.__lastStartedRenderId = 0;

const updatedContext = Object.assign({
redirect: path => redirect(context, path),
const commands = {
redirect: path => createRedirect(context, path),
component: component => renderComponent(context, component)
}, context);
const actionResult = runCallbackIfPossible(processAction, updatedContext, route);
};
const actionResult = runCallbackIfPossible(route.action, [context, commands], route);
if (isResultNotEmpty(actionResult)) {

@@ -181,3 +207,3 @@ return actionResult;

if (isString(route.redirect)) {
return redirect(context, route.redirect);
return commands.redirect(route.redirect);
}

@@ -196,3 +222,3 @@

callbacks = callbacks
.then(() => route.children(Object.assign({}, context, {next: undefined})))
.then(() => route.children(copyContextWithoutNext(context)))
.then(children => {

@@ -204,7 +230,11 @@ // The route.children() callback might have re-written the

}
processNewChildren(children, route, context);
processNewChildren(children, route);
});
}
return callbacks.then(() => processComponent(route, context));
return callbacks.then(() => {
if (isString(route.component)) {
return commands.component(route.component);
}
});
}

@@ -257,3 +287,6 @@

*
* * `bundle` – `.js` or `.mjs` bundle to load before resolving the route. Each bundle is only loaded once.
* * `bundle` – string containing the path to `.js` or `.mjs` bundle to load before resolving the route,
* or the object with "module" and "nomodule" keys referring to different bundles.
* Each bundle is only loaded once. If "module" and "nomodule" are set, only one bundle is loaded,
* depending on whether the browser supports ES modules or not.
* The property is ignored when either an `action` returns the result or `redirect` property is present.

@@ -325,41 +358,55 @@ * Any error, e.g. 404 while loading bundle will cause route resolution to throw.

const renderId = ++this.__lastStartedRenderId;
const pathname = pathnameOrContext.pathname || pathnameOrContext;
// Find the first route that resolves to a non-empty result
this.ready = this.resolve(pathnameOrContext)
.then(originalContext => this.__fullyResolveChain(originalContext, originalContext))
// Process the result of this.resolve() and handle all special commands:
// (redirect / prevent / component). If the result is a 'component',
// then go deeper and build the entire chain of nested components matching
// the pathname. Also call all 'on before' callbacks along the way.
.then(context => this.__fullyResolveChain(context))
.then(context => {
if (renderId === this.__lastStartedRenderId) {
const previousContext = this.__previousContext;
// Check if the render was prevented and make an early return in that case
if (context === previousContext) {
return this.location;
}
if (shouldUpdateHistory) {
this.__updateBrowserHistory(context.result.route.pathname, context.from);
this.__updateBrowserHistory(context.pathname, context.redirectFrom);
}
if (context !== this.__previousContext) {
return this.__runOnAfterCallbacks(context, this.__previousContext, 'onAfterLeave')
.then(() => this.__setOutletContent(context))
.then(() => this.__runOnAfterCallbacks(context, context, 'onAfterEnter'))
.then(() => context);
}
return Promise.resolve(context);
this.__addAppearingContent(context, previousContext);
const animationDone = this.__animateIfNeeded(context);
this.__runOnAfterEnterCallbacks(context);
this.__runOnAfterLeaveCallbacks(context, previousContext);
return animationDone.then(() => {
if (renderId === this.__lastStartedRenderId) {
// If there is another render pass started after this one,
// the 'disappearing content' would be removed when the other
// render pass calls `this.__addAppearingContent()`
this.__removeDisappearingContent();
this.__previousContext = context;
this.location = createLocation(context);
fireRouterEvent('location-changed', {router: this, location: this.location});
return this.location;
}
});
}
})
.then(context => {
if (renderId === this.__lastStartedRenderId) {
return this.__animateIfNeeded(context);
}
})
.then(context => {
if (renderId === this.__lastStartedRenderId) {
this.__removeOldOutletContent();
}
this.__previousContext = context;
this.activeRoutes = [...context.chain];
fireRouterEvent('route-changed', {router: this, params: context.params, pathname: context.pathname});
return this.__outlet;
})
.catch(error => {
if (renderId === this.__lastStartedRenderId) {
if (shouldUpdateHistory) {
this.__updateBrowserHistory(pathnameOrContext);
this.__updateBrowserHistory(pathname);
}
this.__removeOutletContent();
this.activeRoutes = [];
fireRouterEvent('error', {router: this, error});
removeDomNodes(this.__outlet && this.__outlet.children);
this.location = createLocation({pathname});
fireRouterEvent('error', {router: this, error, pathname});
throw error;

@@ -371,3 +418,3 @@ }

__fullyResolveChain(originalContext, currentContext) {
__fullyResolveChain(originalContext, currentContext = originalContext) {
return this.__amendWithResolutionResult(currentContext)

@@ -378,5 +425,10 @@ .then(amendedContext => {

.then(nextContext => {
if (nextContext === null) {
if (amendedContext.pathname !== getMatchedPath(amendedContext.chain)) {
throw getNotFoundError(initialContext);
}
}
return nextContext
? this.__fullyResolveChain(initialContext, nextContext)
: this.__amendWithLifecycleCallbacks(initialContext);
: this.__amendWithOnBeforeCallbacks(initialContext);
});

@@ -407,21 +459,24 @@ });

__amendWithLifecycleCallbacks(contextWithFullChain) {
return this.__runLifecycleCallbacks(contextWithFullChain).then(amendedContext => {
__amendWithOnBeforeCallbacks(contextWithFullChain) {
return this.__runOnBeforeCallbacks(contextWithFullChain).then(amendedContext => {
if (amendedContext === this.__previousContext || amendedContext === contextWithFullChain) {
return amendedContext;
}
return this.__fullyResolveChain(amendedContext, amendedContext);
return this.__fullyResolveChain(amendedContext);
});
}
__runLifecycleCallbacks(newContext) {
const previousChain = (this.__previousContext || {}).chain;
__runOnBeforeCallbacks(newContext) {
const previousContext = this.__previousContext || {};
const previousChain = previousContext.chain || [];
const newChain = newContext.chain;
let callbacks = Promise.resolve();
const prevent = () => ({cancel: true});
const redirect = (pathname) => createRedirect(newContext, pathname);
newContext.__divergedChainIndex = 0;
if (previousChain && previousChain.length) {
for (; newContext.__divergedChainIndex < Math.min(previousChain.length, newChain.length); newContext.__divergedChainIndex++) {
if (previousChain[newContext.__divergedChainIndex] !== newChain[newContext.__divergedChainIndex]) {
if (previousChain.length) {
for (let i = 0; i < Math.min(previousChain.length, newChain.length); i = ++newContext.__divergedChainIndex) {
if (previousChain[i].route !== newChain[i].route || previousChain[i].path !== newChain[i].path) {
break;

@@ -432,4 +487,5 @@ }

for (let i = previousChain.length - 1; i >= newContext.__divergedChainIndex; i--) {
const location = createLocation(newContext);
callbacks = callbacks
.then(amend('onBeforeLeave', newContext, previousChain[i]))
.then(amend('onBeforeLeave', [location, {prevent}, this], previousChain[i].element))
.then(result => {

@@ -443,5 +499,5 @@ if (!(result || {}).redirect) {

const onBeforeEnterContext = Object.assign({redirect: path => redirect(newContext, path)}, newContext);
for (let i = newContext.__divergedChainIndex; i < newChain.length; i++) {
callbacks = callbacks.then(amend('onBeforeEnter', onBeforeEnterContext, newChain[i]));
const location = createLocation(newContext, newChain[i].route);
callbacks = callbacks.then(amend('onBeforeEnter', [location, {prevent, redirect}, this], newChain[i].element));
}

@@ -469,3 +525,3 @@

pathname: Router.pathToRegexp.compile(redirectData.pathname)(redirectData.params),
from: redirectData.from,
redirectFrom: redirectData.from,
__redirectCount: (counter || 0) + 1

@@ -481,4 +537,3 @@ });

__updateBrowserHistory(pathnameOrContext, replace) {
const pathname = pathnameOrContext.pathname || pathnameOrContext;
__updateBrowserHistory(pathname, replace) {
if (window.location.pathname !== pathname) {

@@ -491,27 +546,20 @@ const changeState = replace ? 'replaceState' : 'pushState';

__setOutletContent(context) {
this.__removePendingContent();
function containsElement(htmlElements, elementToSearch) {
for (let i = 0; i < htmlElements.length; i++) {
if (htmlElements[i] === elementToSearch) {
return true;
}
}
return false;
}
__addAppearingContent(context, previousContext) {
this.__ensureOutlet();
let lastUnchangedComponent = this.__outlet;
// If the previous 'entering' animation has not completed yet,
// stop it and remove that content from the DOM before adding new one.
this.__removeAppearingContent();
if (context) {
for (let i = 0; i < context.__divergedChainIndex; i++) {
const unchangedComponent = context.chain[i].__component;
if (unchangedComponent) {
if (containsElement(lastUnchangedComponent.children || [], unchangedComponent)) {
lastUnchangedComponent = unchangedComponent;
} else {
break;
}
// Find the deepest common parent between the last and the new component
// chains. Update references for the unchanged elements in the new chain
let deepestCommonParent = this.__outlet;
for (let i = 0; i < context.__divergedChainIndex; i++) {
const unchangedElement = previousContext && previousContext.chain[i].element;
if (unchangedElement) {
if (unchangedElement.parentNode === deepestCommonParent) {
context.chain[i].element = unchangedElement;
deepestCommonParent = unchangedElement;
} else {
break;
}

@@ -521,14 +569,21 @@ }

this.__oldContent = Array.from(lastUnchangedComponent.childNodes);
this.__newContent = [];
// Keep two lists of DOM elements:
// - those that should be removed once the transition animation is over
// - and those that should remain
this.__disappearingContent = Array.from(deepestCommonParent.children);
this.__appearingContent = [];
if (context) {
let parentElement = lastUnchangedComponent;
for (let i = context.__divergedChainIndex; i < context.chain.length; i++) {
const componentToAdd = context.chain[i].__component;
if (componentToAdd) {
parentElement.appendChild(componentToAdd);
parentElement = componentToAdd;
this.__newContent.push(componentToAdd);
// Add new elements (starting after the deepest common parent) to the DOM.
// That way only the components that are actually different between the two
// locations are added to the DOM (and those that are common remain in the
// DOM without first removing and then adding them again).
let parentElement = deepestCommonParent;
for (let i = context.__divergedChainIndex; i < context.chain.length; i++) {
const elementToAdd = context.chain[i].element;
if (elementToAdd) {
parentElement.appendChild(elementToAdd);
if (parentElement === deepestCommonParent) {
this.__appearingContent.push(elementToAdd);
}
parentElement = elementToAdd;
}

@@ -538,43 +593,56 @@ }

__removeOldOutletContent() {
if (this.__oldContent && this.__oldContent.length) {
this.__removeOutletContent(this.__oldContent);
__removeDisappearingContent() {
if (this.__disappearingContent) {
removeDomNodes(this.__disappearingContent);
}
this.__oldContent = null;
this.__newContent = null;
this.__disappearingContent = null;
this.__appearingContent = null;
}
__removePendingContent() {
if (this.__oldContent && this.__newContent) {
this.__oldContent = this.__newContent;
this.__removeOldOutletContent();
__removeAppearingContent() {
if (this.__disappearingContent && this.__appearingContent) {
removeDomNodes(this.__appearingContent);
this.__disappearingContent = null;
this.__appearingContent = null;
}
}
__removeOutletContent(content) {
content = content || (this.__outlet && this.__outlet.children);
if (content && content.length) {
const parent = content[0].parentNode;
for (let i = 0; i < content.length; i += 1) {
parent.removeChild(content[i]);
__runOnAfterLeaveCallbacks(currentContext, targetContext) {
if (!targetContext) {
return;
}
// REVERSE iteration: from Z to A
for (let i = targetContext.chain.length - 1; i >= currentContext.__divergedChainIndex; i--) {
const currentComponent = targetContext.chain[i].element;
if (!currentComponent) {
continue;
}
try {
const location = createLocation(currentContext);
runCallbackIfPossible(
currentComponent.onAfterLeave,
[location, {}, targetContext.resolver],
currentComponent);
} finally {
removeDomNodes(currentComponent.children);
}
}
}
__runOnAfterCallbacks(currentContext, targetContext, callbackName) {
let promises = Promise.resolve();
if (targetContext) {
const callbackContext = Object.assign({}, currentContext, {next: undefined});
for (let i = currentContext.__divergedChainIndex; i < targetContext.chain.length; i++) {
const currentComponent = targetContext.chain[i].__component || {};
promises = promises.then(() => runCallbackIfPossible(currentComponent[callbackName], callbackContext, currentComponent));
}
__runOnAfterEnterCallbacks(currentContext) {
// forward iteration: from A to Z
for (let i = currentContext.__divergedChainIndex; i < currentContext.chain.length; i++) {
const currentComponent = currentContext.chain[i].element || {};
const location = createLocation(currentContext, currentContext.chain[i].route);
runCallbackIfPossible(
currentComponent.onAfterEnter,
[location, {}, currentContext.resolver],
currentComponent);
}
return promises;
}
__animateIfNeeded(context) {
const from = this.__oldContent && this.__oldContent[0];
const to = this.__newContent && this.__newContent[0];
const from = (this.__disappearingContent || [])[0];
const to = (this.__appearingContent || [])[0];
const promises = [];

@@ -585,4 +653,4 @@

for (let i = chain.length; i > 0; i--) {
if (chain[i - 1].animate) {
config = chain[i - 1].animate;
if (chain[i - 1].route.animate) {
config = chain[i - 1].route.animate;
break;

@@ -593,5 +661,4 @@ }

if (from && to && config) {
const isObj = isObject(config);
const leave = isObj && config.leave || 'leaving';
const enter = isObj && config.enter || 'entering';
const leave = isObject(config) && config.leave || 'leaving';
const enter = isObject(config) && config.enter || 'entering';
promises.push(animate(from, leave));

@@ -601,9 +668,3 @@ promises.push(animate(to, enter));

if (promises.length) {
return new Promise(resolve => {
Promise.all(promises).then(() => resolve(context));
});
}
return context;
return Promise.all(promises).then(() => context);
}

@@ -610,0 +671,0 @@

@@ -10,2 +10,14 @@ export function toArray(objectOrArray) {

const MODULE = 'module';
const NOMODULE = 'nomodule';
const bundleKeys = [MODULE, NOMODULE];
function ensureBundle(src) {
if (!src.match(/.+\.[m]?js$/)) {
throw new Error(
log(`Unsupported type for bundle "${src}": .js or .mjs expected.`)
);
}
}
export function ensureRoute(route) {

@@ -18,2 +30,4 @@ if (!route || !isString(route.path)) {

const bundle = route.bundle;
const stringKeys = ['component', 'redirect', 'bundle'];

@@ -24,3 +38,3 @@ if (

!isFunction(route.children) &&
!isObject(route.bundle) &&
!isObject(bundle) &&
!stringKeys.some(key => isString(route[key]))

@@ -36,8 +50,11 @@ ) {

if (route.bundle) {
const src = isString(route.bundle) ? route.bundle : route.bundle.src;
if (!src.match(/.+\.[m]?js$/)) {
if (bundle) {
if (isString(bundle)) {
ensureBundle(bundle);
} else if (!bundleKeys.some(key => key in bundle)) {
throw new Error(
log(`Unsupported type for bundle "${src}": .js or .mjs expected.`)
log('Expected route bundle to include either "' + NOMODULE + '" or "' + MODULE + '" keys, or both')
);
} else {
bundleKeys.forEach(key => key in bundle && ensureBundle(bundle[key]));
}

@@ -64,31 +81,15 @@ }

export function loadBundle(bundle) {
const path = isString(bundle) ? bundle : bundle.src;
let script = document.head.querySelector('script[src="' + path + '"][async]');
if (script && script.parentNode === document.head) {
if (script.__dynamicImportLoaded) {
return Promise.resolve();
} else {
return new Promise((resolve, reject) => {
const originalOnLoad = script.onload;
script.onreadystatechange = script.onload = e => {
originalOnLoad();
resolve(e);
};
const originalOnError = script.onerror;
script.onerror = e => {
originalOnError();
reject(e);
};
});
function loadScript(src, key) {
let script = document.head.querySelector('script[src="' + src + '"][async]');
if (!script) {
script = document.createElement('script');
script.setAttribute('src', src);
if (key === MODULE) {
script.setAttribute('type', MODULE);
} else if (key === NOMODULE) {
script.setAttribute(NOMODULE, '');
}
script.async = true;
}
return new Promise((resolve, reject) => {
script = document.createElement('script');
script.setAttribute('src', path);
if (isObject(bundle) && bundle.type === 'module') {
script.setAttribute('type', 'module');
}
script.async = true;
script.onreadystatechange = script.onload = e => {

@@ -104,6 +105,22 @@ script.__dynamicImportLoaded = true;

};
document.head.appendChild(script);
if (script.parentNode === null) {
document.head.appendChild(script);
} else if (script.__dynamicImportLoaded) {
resolve();
}
});
}
export function loadBundle(bundle) {
if (isString(bundle)) {
return loadScript(bundle);
} else {
return Promise.race(
bundleKeys
.filter(key => key in bundle)
.map(key => loadScript(bundle[key], key))
);
}
}
export function fireRouterEvent(type, detail) {

@@ -116,3 +133,4 @@ window.dispatchEvent(

export function isObject(o) {
return typeof o === 'object';
// guard against null passing the typeof check
return typeof o === 'object' && !!o;
}

@@ -127,1 +145,8 @@

}
export function getNotFoundError(context) {
const error = new Error(log(`Page not found (${context.pathname})`));
error.context = context;
error.code = 404;
return error;
}

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc