static: add argument support to Router and add RouteMatch
This commit is contained in:
parent
1432f0648f
commit
feabd38173
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
|
@ -24,7 +24,7 @@ export class Route {
|
||||||
url: RegExp;
|
url: RegExp;
|
||||||
|
|
||||||
private element?: TemplateResult;
|
private element?: TemplateResult;
|
||||||
private callback?: () => TemplateResult;
|
private callback?: (args: { [key: string]: string; }) => TemplateResult;
|
||||||
|
|
||||||
constructor(url: RegExp, element?: TemplateResult) {
|
constructor(url: RegExp, element?: TemplateResult) {
|
||||||
this.url = url;
|
this.url = url;
|
||||||
|
@ -40,9 +40,14 @@ export class Route {
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
render(): TemplateResult {
|
then(render: (args: { [key: string]: string; }) => TemplateResult): Route {
|
||||||
|
this.callback = render;
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
render(args: { [key: string]: string; }): TemplateResult {
|
||||||
if (this.callback) {
|
if (this.callback) {
|
||||||
return this.callback();
|
return this.callback(args);
|
||||||
}
|
}
|
||||||
if (this.element) {
|
if (this.element) {
|
||||||
return this.element;
|
return this.element;
|
||||||
|
@ -51,16 +56,36 @@ export class Route {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const SLUG_REGEX = "[-a-zA-Z0-9_]+";
|
||||||
export const ROUTES: Route[] = [
|
export const ROUTES: Route[] = [
|
||||||
// Prevent infinite Shell loops
|
// Prevent infinite Shell loops
|
||||||
new Route(new RegExp("^/$")).redirect("/-/overview/"),
|
new Route(new RegExp(`^/$`)).redirect("/-/overview/"),
|
||||||
new Route(new RegExp("^/applications/$"), html`<h1>test</h1>`),
|
new Route(new RegExp(`^/applications/$`), html`<h1>test</h1>`),
|
||||||
|
new Route(new RegExp(`^/-/applications/(?<slug>${SLUG_REGEX})/$`)).then((args) => {
|
||||||
|
return html`<h1>test</h1>
|
||||||
|
|
||||||
|
<span>${args.slug}</span>`;
|
||||||
|
}),
|
||||||
];
|
];
|
||||||
|
|
||||||
|
class RouteMatch {
|
||||||
|
route: Route;
|
||||||
|
arguments?: RegExpExecArray;
|
||||||
|
fullUrl?: string;
|
||||||
|
|
||||||
|
constructor(route: Route) {
|
||||||
|
this.route = route;
|
||||||
|
}
|
||||||
|
|
||||||
|
render(): TemplateResult {
|
||||||
|
return this.route.render(this.arguments!.groups || {});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
@customElement("pb-router-outlet")
|
@customElement("pb-router-outlet")
|
||||||
export class RouterOutlet extends LitElement {
|
export class RouterOutlet extends LitElement {
|
||||||
@property()
|
@property()
|
||||||
activeRoute?: Route;
|
current?: RouteMatch;
|
||||||
|
|
||||||
@property()
|
@property()
|
||||||
defaultUrl?: string;
|
defaultUrl?: string;
|
||||||
|
@ -98,28 +123,35 @@ export class RouterOutlet extends LitElement {
|
||||||
window.location.hash = `#${activeUrl}`;
|
window.location.hash = `#${activeUrl}`;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let selectedRoute: Route | null = null;
|
let matchedRoute: RouteMatch | null = null;
|
||||||
ROUTES.forEach((route) => {
|
ROUTES.forEach((route) => {
|
||||||
if (route.url.exec(activeUrl)) {
|
console.log(`matching ${activeUrl} against ${route.url}`);
|
||||||
selectedRoute = route;
|
const match = route.url.exec(activeUrl);
|
||||||
|
if (match != null) {
|
||||||
|
matchedRoute = new RouteMatch(route);
|
||||||
|
matchedRoute.arguments = match;
|
||||||
|
matchedRoute.fullUrl = activeUrl;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
if (!selectedRoute) {
|
if (!matchedRoute) {
|
||||||
console.log(
|
console.log(
|
||||||
`passbook/router: route "${activeUrl}" not defined, defaulting to shell`
|
`passbook/router: route "${activeUrl}" not defined, defaulting to shell`
|
||||||
);
|
);
|
||||||
selectedRoute = new Route(
|
const route = new Route(
|
||||||
RegExp(""),
|
RegExp(""),
|
||||||
html`<pb-site-shell url=${activeUrl}>
|
html`<pb-site-shell url=${activeUrl}>
|
||||||
<div slot="body"></div>
|
<div slot="body"></div>
|
||||||
</pb-site-shell>`
|
</pb-site-shell>`
|
||||||
);
|
);
|
||||||
|
matchedRoute = new RouteMatch(route);
|
||||||
|
matchedRoute.arguments = route.url.exec(activeUrl)!;
|
||||||
|
matchedRoute.fullUrl = activeUrl;
|
||||||
}
|
}
|
||||||
this.activeRoute = selectedRoute;
|
this.current = matchedRoute;
|
||||||
}
|
}
|
||||||
|
|
||||||
render() {
|
render() {
|
||||||
return this.activeRoute?.render();
|
return this.current?.render();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Reference in New Issue