UNPKG

@miesil/pp-breadcrumbs

Version:

PP-Breadcrumbs is an Angular 7 module generating breadcrumbs based on the routing state.

291 lines (282 loc) 9.51 kB
import { of, Observable, BehaviorSubject, concat, from } from 'rxjs'; import { template, templateSettings } from 'lodash'; import { filter, mergeMap, distinct, toArray, first, tap } from 'rxjs/operators'; import { Injectable, Injector, Component, EventEmitter, Output, NgModule, defineInjectable, inject, INJECTOR } from '@angular/core'; import { ActivatedRoute, NavigationEnd, Router, RouterModule } from '@angular/router'; import { CommonModule } from '@angular/common'; /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ templateSettings.interpolate = /{{([\s\S]+?)}}/g; class PpBreadcrumbsResolver { /** * @param {?} route * @param {?} state * @return {?} */ resolve(route, state) { /** @type {?} */ const data = route.routeConfig.data; /** @type {?} */ const path = this.getFullPath(route); /** @type {?} */ const rawText = typeof data.breadcrumbs === 'string' ? data.breadcrumbs : data.breadcrumbs.text || data.text || path; return of([ { path: path, text: this.stringFormat(rawText, route.data) } ]); } /** * @param {?} route * @return {?} */ getFullPath(route) { /** @type {?} */ const relativePath = (/** * @param {?} segments * @return {?} */ (segments) => segments.reduce((/** * @param {?} a * @param {?} v * @return {?} */ (a, v) => (a += '/' + v.path)), '')); /** @type {?} */ const fullPath = (/** * @param {?} routes * @return {?} */ (routes) => routes.reduce((/** * @param {?} a * @param {?} v * @return {?} */ (a, v) => (a += relativePath(v.url))), '')); return fullPath(route.pathFromRoot); } /** * @private * @param {?} templateString * @param {?} binding * @return {?} */ stringFormat(templateString, binding) { /** @type {?} */ const compiled = template(templateString); return compiled(binding); } } PpBreadcrumbsResolver.decorators = [ { type: Injectable } ]; /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ class PpBreadcrumbsService { /** * @param {?} router * @param {?} route * @param {?} injector */ constructor(router, route, injector) { this.router = router; this.injector = injector; this.breadcrumbs = new BehaviorSubject([]); this.defaultResolver = new PpBreadcrumbsResolver(); this.breadcrumbsSource = []; this.router.events.pipe(filter((/** * @param {?} x * @return {?} */ x => x instanceof NavigationEnd))).subscribe((/** * @param {?} event * @return {?} */ (event) => { this.resolveCrumbs(router.routerState.snapshot.root) .pipe(mergeMap((/** * @param {?} breadcrumbs * @return {?} */ breadcrumbs => breadcrumbs)), distinct((/** * @param {?} breadcrumb * @return {?} */ breadcrumb => breadcrumb.text)), toArray(), tap((/** * @param {?} breadcrumbs * @return {?} */ breadcrumbs => this.breadcrumbsSource = breadcrumbs)), mergeMap((/** * @param {?} breadcrumbs * @return {?} */ breadcrumbs => { return this.postProcess ? this.wrapIntoObservable(this.postProcess(breadcrumbs)).pipe(first()) : of(breadcrumbs); }))) .subscribe((/** * @param {?} breadcrumbs * @return {?} */ breadcrumbs => { this.breadcrumbs.next(breadcrumbs); })); })); } /** * @return {?} */ get crumbs$() { return this.breadcrumbs; } /** * @return {?} */ refreshBreadcrumbs() { (this.postProcess ? this.wrapIntoObservable(this.postProcess(this.breadcrumbsSource)).pipe(first()) : of(this.breadcrumbsSource)) .subscribe((/** * @param {?} breadcrumbs * @return {?} */ breadcrumbs => { this.breadcrumbs.next(breadcrumbs); })); } /** * @private * @param {?} route * @return {?} */ resolveCrumbs(route) { /** @type {?} */ let crumbs$ = of([]); /** @type {?} */ const data = route.routeConfig && route.routeConfig.data; if (data && data.breadcrumbs) { /** @type {?} */ const resolver = data.breadcrumbs.prototype instanceof PpBreadcrumbsResolver ? this.injector.get(data.breadcrumbs) : this.defaultResolver; /** @type {?} */ const result = resolver.resolve(route, this.router.routerState.snapshot); crumbs$ = this.wrapIntoObservable(result).pipe(first()); } return route.firstChild ? concat(crumbs$, this.resolveCrumbs(route.firstChild)) : crumbs$; } /** * @private * @template T * @param {?} value * @return {?} */ wrapIntoObservable(value) { return value instanceof Observable ? value : this.isPromise(value) ? from(Promise.resolve(value)) : of((/** @type {?} */ (value))); } /** * @private * @param {?} value * @return {?} */ isPromise(value) { return value && typeof value.then === 'function'; } } PpBreadcrumbsService.decorators = [ { type: Injectable, args: [{ providedIn: 'root' },] } ]; /** @nocollapse */ PpBreadcrumbsService.ctorParameters = () => [ { type: Router }, { type: ActivatedRoute }, { type: Injector } ]; /** @nocollapse */ PpBreadcrumbsService.ngInjectableDef = defineInjectable({ factory: function PpBreadcrumbsService_Factory() { return new PpBreadcrumbsService(inject(Router), inject(ActivatedRoute), inject(INJECTOR)); }, token: PpBreadcrumbsService, providedIn: "root" }); /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ class PpBreadcrumbsComponent { /** * @param {?} service */ constructor(service) { this.service = service; this.subscriptions = []; this.onNavigate = new EventEmitter(); } /** * @return {?} */ ngOnInit() { this.subscriptions.push(this.service.crumbs$.subscribe((/** * @param {?} x * @return {?} */ x => { this.crumbs = x; }))); } /** * @return {?} */ ngOnDestroy() { this.subscriptions.forEach((/** * @param {?} x * @return {?} */ x => x.unsubscribe())); this.onNavigate.complete(); this.onNavigate = undefined; } /** * @return {?} */ click() { this.onNavigate.emit({}); } } PpBreadcrumbsComponent.decorators = [ { type: Component, args: [{ selector: 'pp-breadcrumbs', template: "<ol *ngIf=\"crumbs.length\" class=\"breadcrumb\">\r\n <li *ngFor=\"let crumb of crumbs; let first = first; let last = last\" [ngClass]=\"{ 'active': last }\" class=\"breadcrumb-item\">\r\n <a *ngIf=\"!last; else lastBreadcrumb\" [routerLink]=\"crumb.path\" [innerHTML]=\"crumb.text\" (click)=\"click()\"></a>\r\n <ng-template #lastBreadcrumb>\r\n <span [innerHTML]=\"crumb.text\"></span>\r\n </ng-template>\r\n </li>\r\n</ol>\r\n", styles: [""] }] } ]; /** @nocollapse */ PpBreadcrumbsComponent.ctorParameters = () => [ { type: PpBreadcrumbsService } ]; PpBreadcrumbsComponent.propDecorators = { onNavigate: [{ type: Output }] }; /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ class PpBreadcrumbsModule { } PpBreadcrumbsModule.decorators = [ { type: NgModule, args: [{ declarations: [PpBreadcrumbsComponent], imports: [CommonModule, RouterModule], exports: [PpBreadcrumbsComponent] },] } ]; /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ /** * @fileoverview added by tsickle * @suppress {checkTypes,extraRequire,missingOverride,missingReturn,unusedPrivateMembers,uselessCode} checked by tsc */ export { PpBreadcrumbsService, PpBreadcrumbsComponent, PpBreadcrumbsResolver, PpBreadcrumbsModule }; //# sourceMappingURL=miesil-pp-breadcrumbs.js.map