UNPKG

@nent/core

Version:

Functional elements to add routing, data-binding, dynamic HTML, declarative actions, audio, video, and so much more. Supercharge static HTML files into web apps without script or builds.

247 lines (246 loc) 7.09 kB
/*! * NENT 2022 */ import { Component, Element, h, Prop, State } from '@stencil/core'; import { eventBus } from '../../services/actions'; import { ROUTE_EVENTS, } from '../n-views/services/interfaces'; import { onRoutingChange, routingState, } from '../n-views/services/state'; /** * Display a list of routes related to the current route. * Modes: * **siblings**: all routes at the same depth level (nav) * **parents**: all parent routes. (breadcrumbs) * **children**: all child routes within a hierarchy. (sub-menu) * * @system routing */ export class ViewLinkList { constructor() { this.route = null; this.match = null; this.routes = []; /** * The display mode for which routes to display. */ this.mode = 'parents'; /** * The active-class to use with the n-view-link elements. */ this.activeClass = 'active'; /** * The class to add to the anchor tag. */ this.linkClass = ''; /** * The list-class to use with the UL tag */ this.listClass = ''; /** * The list-item-class to use with the li tag */ this.itemClass = ''; /** * Specify if the '/' route should * be skipped in the list. */ this.excludeRoot = false; } get parentView() { return this.el.closest('n-view'); } get parentViewPrompt() { return this.el.closest('n-view-prompt'); } componentWillLoad() { if (routingState.router) { this.setupRoute(); } else { const dispose = onRoutingChange('router', () => { this.setupRoute(); dispose(); }); } } get inView() { return this.parentView != null || this.parentViewPrompt != null; } setupRoute() { var _a, _b; if (this.parentViewPrompt) { this.route = ((_a = this.parentViewPrompt) === null || _a === void 0 ? void 0 : _a.route) || null; } else if (this.parentView) { this.route = ((_b = this.parentView) === null || _b === void 0 ? void 0 : _b.route) || null; } if (this.route == null) this.subscribe(); } subscribe() { var _a, _b, _c; this.matchSubscription = eventBus.on(ROUTE_EVENTS.RouteMatchedExact, ({ route, match }) => { this.route = route; this.match = match; if (this.inView) { this.matchSubscription.call(this); } }); this.route = ((_a = routingState.router) === null || _a === void 0 ? void 0 : _a.exactRoute) || null; this.match = ((_c = (_b = routingState.router) === null || _b === void 0 ? void 0 : _b.exactRoute) === null || _c === void 0 ? void 0 : _c.match) || null; } async componentWillRender() { let routes = await this.getRoutes(); if (this.mode == 'parents' && (routes === null || routes === void 0 ? void 0 : routes.length) && this.excludeRoot) routes.shift(); this.routes = routes || []; } async getRoutes() { var _a, _b, _c; switch (this.mode) { case 'parents': return await ((_a = this.route) === null || _a === void 0 ? void 0 : _a.getParentRoutes()); case 'siblings': return await ((_b = this.route) === null || _b === void 0 ? void 0 : _b.getSiblingRoutes()); case 'children': return await ((_c = this.route) === null || _c === void 0 ? void 0 : _c.getChildRoutes()); } } getUrl(route) { var _a, _b; let url = ((_a = route.match) === null || _a === void 0 ? void 0 : _a.url) || route.path; if (this.match) { Object.keys((_b = this.match) === null || _b === void 0 ? void 0 : _b.params).forEach(param => { url = url.replace(`:${param}`, this.match.params[param]); }); } return url; } render() { var _a; return (h("ul", { class: this.listClass }, (_a = this.routes) === null || _a === void 0 ? void 0 : _a.map((r) => [ h("li", { class: this.itemClass }, h("n-view-link", { path: this.getUrl(r.route), exact: true, "link-class": this.linkClass, "active-class": this.activeClass }, r.title)), ]))); } disconnectedCallback() { var _a; (_a = this.matchSubscription) === null || _a === void 0 ? void 0 : _a.call(this); } static get is() { return "n-view-link-list"; } static get properties() { return { "mode": { "type": "string", "mutable": false, "complexType": { "original": "'children' | 'parents' | 'siblings'", "resolved": "\"children\" | \"parents\" | \"siblings\"", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "The display mode for which routes to display." }, "attribute": "mode", "reflect": false, "defaultValue": "'parents'" }, "activeClass": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string | undefined", "references": {} }, "required": false, "optional": true, "docs": { "tags": [], "text": "The active-class to use with the n-view-link elements." }, "attribute": "active-class", "reflect": false, "defaultValue": "'active'" }, "linkClass": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string | undefined", "references": {} }, "required": false, "optional": true, "docs": { "tags": [], "text": "The class to add to the anchor tag." }, "attribute": "link-class", "reflect": false, "defaultValue": "''" }, "listClass": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string | undefined", "references": {} }, "required": false, "optional": true, "docs": { "tags": [], "text": "The list-class to use with the UL tag" }, "attribute": "list-class", "reflect": false, "defaultValue": "''" }, "itemClass": { "type": "string", "mutable": false, "complexType": { "original": "string", "resolved": "string | undefined", "references": {} }, "required": false, "optional": true, "docs": { "tags": [], "text": "The list-item-class to use with the li tag" }, "attribute": "item-class", "reflect": false, "defaultValue": "''" }, "excludeRoot": { "type": "boolean", "mutable": false, "complexType": { "original": "boolean", "resolved": "boolean", "references": {} }, "required": false, "optional": false, "docs": { "tags": [], "text": "Specify if the '/' route should\nbe skipped in the list." }, "attribute": "exclude-root", "reflect": false, "defaultValue": "false" } }; } static get states() { return { "route": {}, "match": {}, "routes": {} }; } static get elementRef() { return "el"; } }