@tinijs/router
Version:
The router module for the TiniJS framework.
104 lines • 4.38 kB
JavaScript
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
import { LitElement } from 'lit';
import { property } from 'lit/decorators.js';
import { NO_ROUTER_FOR_OUTLET_ERROR } from './consts.js';
import { Router } from './router.js';
export class RouterOutletComponent extends LitElement {
connectedCallback() {
super.connectedCallback();
if (!this.router)
throw new Error(NO_ROUTER_FOR_OUTLET_ERROR);
this.router.setCallback(this.handleRoute.bind(this));
this.handleRoute(this.router.match(new URL(location.href)));
}
async handleRoute(activeRoute) {
const { layoutRoute, pageRoute } = activeRoute;
// lazy load
if (layoutRoute?.action)
await layoutRoute.action();
if (pageRoute?.action)
await pageRoute.action();
// render
const layoutTagName = layoutRoute?.component;
const pageTagName = pageRoute?.component;
if (layoutTagName === this.currentLayout &&
pageTagName === this.currentPage)
return;
if (layoutTagName === this.currentLayout)
return this.renderPage(activeRoute, pageTagName);
return this.renderFull(activeRoute, pageTagName, layoutTagName);
}
async renderPage(activeRoute, pageTagName) {
this.currentPage = pageTagName;
const rootEl = !this.currentLayout
? this.renderRoot
: this.renderRoot.querySelector(this.currentLayout) || this.renderRoot;
if (!pageTagName || !rootEl)
return;
return this.renderer(activeRoute, rootEl, pageTagName);
}
async renderFull(activeRoute, pageTagName, layoutTagName) {
this.currentLayout = layoutTagName;
this.currentPage = pageTagName;
let rootEl = this.renderRoot;
if (!pageTagName || !rootEl)
return;
// layout
if (layoutTagName) {
const layoutEl = await this.renderer(activeRoute, rootEl, layoutTagName);
if (layoutEl)
rootEl = layoutEl;
}
// page
return this.renderer(activeRoute, rootEl, pageTagName);
}
async renderer(activeRoute, rootEl, newTagName) {
const currentEl = rootEl.firstElementChild;
const newEl = document.createElement(newTagName);
// hooks
const currentBeforeLeave = currentEl?.onBeforeLeave;
const currentAfterLeave = currentEl?.onAfterLeave;
const newBeforeEnter = newEl?.onBeforeEnter;
const newAfterEnter = newEl?.onAfterEnter;
// stage 1
if (await this.runBeforeHook(currentBeforeLeave, activeRoute, newEl, currentEl))
return;
if (await this.runBeforeHook(newBeforeEnter, activeRoute, newEl, currentEl))
return;
// main action
rootEl.replaceChildren(newEl);
// stage 2
await this.runAfterHook(newAfterEnter, activeRoute, newEl, currentEl);
await this.runAfterHook(currentAfterLeave, activeRoute, newEl, currentEl);
// continue
return newEl;
}
async runBeforeHook(hook, activeRoute, newEl, currentEl) {
const hookCommand = !hook
? undefined
: await hook.call(newEl, this.router, activeRoute, newEl, currentEl);
if (!hookCommand)
return false;
if (typeof hookCommand === 'string') {
this.router.redirect(hookCommand);
}
else {
hookCommand();
}
return true;
}
async runAfterHook(hook, activeRoute, newEl, currentEl) {
if (hook)
await hook.call(newEl, this.router, activeRoute, newEl, currentEl);
return false;
}
}
__decorate([
property({ type: Object })
], RouterOutletComponent.prototype, "router", void 0);
//# sourceMappingURL=router-outlet.js.map