UNPKG

@exalif/ngx-breadcrumbs

Version:

Angular 4+ breadcrumbs on top of native Angular router

248 lines (239 loc) 11 kB
import * as i0 from '@angular/core'; import { Injectable, Component, NgModule } from '@angular/core'; import * as i2 from '@angular/common'; import { CommonModule } from '@angular/common'; import * as i1 from '@angular/router'; import { NavigationEnd, RouterModule } from '@angular/router'; import { Observable, from, of, BehaviorSubject, concat } from 'rxjs'; import { filter, flatMap, distinct, tap, toArray, first } from 'rxjs/operators'; class BreadcrumbsConfig { constructor(options = { postProcess: null, applyDistinctOn: 'text', }) { this.postProcess = null; this.applyDistinctOn = 'text'; if (!options) { return; } Object.keys(options).forEach((optionKey) => { this[optionKey] = options[optionKey]; }); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.1", ngImport: i0, type: BreadcrumbsConfig, deps: [{ token: BreadcrumbsConfig }], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.0.1", ngImport: i0, type: BreadcrumbsConfig }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.1", ngImport: i0, type: BreadcrumbsConfig, decorators: [{ type: Injectable }], ctorParameters: function () { return [{ type: BreadcrumbsConfig }]; } }); class BreadcrumbsUtils { static stringFormat(rawTemplate, data) { const templateRegex = new RegExp('{{[\\s]*[a-zA-Z._]+?[\\s]*}}', 'g'); return rawTemplate.replace(templateRegex, (match) => { const keyRegex = new RegExp('([a-zA-Z._]+)', 'g'); const key = match.match(keyRegex); if (!key || !key.length) { return match; } const value = BreadcrumbsUtils.leaf(data, key[0]); if (!value) { return key[0]; } return value; }); } static wrapIntoObservable(value) { if (value instanceof Observable) { return value; } if (this.isPromise(value)) { return from(Promise.resolve(value)); } return of(value); } static isPromise(value) { return value && (typeof value.then === 'function'); } /** * Access object nested value by giving a path * * @param obj The object you want to access value from * @param path The value path. e.g: `bar.baz` * @example * const obj = { foo: { bar: 'Baz' } }; * const path = 'foo.bar'; * leaf(obj, path) // 'Baz' */ static leaf(obj, path) { const result = path.split('.').reduce((value, el) => value[el] || {}, obj); return BreadcrumbsUtils.isEmptyObject(result) ? null : result; } /** * checks whether an object is empty or not * * @param object object to extract values from * @returns boolean */ static isEmptyObject(obj) { if (typeof obj === 'object' && Object.prototype.toString.call(obj) === '[object Object]') { for (const key in obj) { if (Object.prototype.hasOwnProperty.call(obj, key)) { return false; } } return true; } return false; } } class BreadcrumbsResolver { resolve(route, state) { const data = route.routeConfig.data; const path = this.getFullPath(route); let text = typeof (data.breadcrumbs) === 'string' ? data.breadcrumbs : data.breadcrumbs.text || data.text || path; text = BreadcrumbsUtils.stringFormat(text, route.data); const crumbs = [{ text, path }]; return of(crumbs); } getFullPath(route) { return this.fetchFullPath(route.pathFromRoot); } fetchFullPath(routes) { return routes.reduce((path, route) => path += this.fetchRelativePath(route.url), ''); } fetchRelativePath(urlSegments) { return urlSegments.reduce((path, urlSegment) => path += '/' + urlSegment.path, ''); } } class BreadcrumbsService { constructor(route, router, config, injector) { this.route = route; this.router = router; this.config = config; this.injector = injector; this.breadcrumbs = new BehaviorSubject([]); this.defaultResolver = new BreadcrumbsResolver(); this.router.events.pipe(filter((x) => x instanceof NavigationEnd)) .subscribe((_) => { const routeRoot = router.routerState.snapshot.root; this.resolveCrumbs(routeRoot).pipe(flatMap((crumbs) => crumbs), this.config.applyDistinctOn ? distinct((crumb) => crumb[this.config.applyDistinctOn]) : tap(), toArray(), flatMap((crumbs) => { if (this.config.postProcess) { const postProcessedCrumb = this.config.postProcess(crumbs); return BreadcrumbsUtils.wrapIntoObservable(postProcessedCrumb).pipe(first()); } else { return of(crumbs); } })) .subscribe((crumbs) => { this.breadcrumbs.next(crumbs); }); }); } get crumbs$() { return this.breadcrumbs; } getCrumbs() { return this.crumbs$; } resolveCrumbs(route) { let crumbs$; const data = route.routeConfig && route.routeConfig.data; if (data && data.breadcrumbs) { let resolver; if (data.breadcrumbs.prototype instanceof BreadcrumbsResolver) { resolver = this.injector.get(data.breadcrumbs); } else { resolver = this.defaultResolver; } const result = resolver.resolve(route, this.router.routerState.snapshot); crumbs$ = BreadcrumbsUtils.wrapIntoObservable(result).pipe(first()); } else { crumbs$ = of([]); } if (route.firstChild) { crumbs$ = concat(crumbs$, this.resolveCrumbs(route.firstChild)); } return crumbs$; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.1", ngImport: i0, type: BreadcrumbsService, deps: [{ token: i1.ActivatedRoute }, { token: i1.Router }, { token: BreadcrumbsConfig }, { token: i0.Injector }], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "16.0.1", ngImport: i0, type: BreadcrumbsService }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.1", ngImport: i0, type: BreadcrumbsService, decorators: [{ type: Injectable }], ctorParameters: function () { return [{ type: i1.ActivatedRoute }, { type: i1.Router }, { type: BreadcrumbsConfig }, { type: i0.Injector }]; } }); class BreadcrumbsComponent { constructor(breadcrumbsService) { this.breadcrumbsService = breadcrumbsService; this.crumbs$ = this.breadcrumbsService.getCrumbs(); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.1", ngImport: i0, type: BreadcrumbsComponent, deps: [{ token: BreadcrumbsService }], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "16.0.1", type: BreadcrumbsComponent, selector: "lib-breadcrumbs", ngImport: i0, template: ` <ol *ngIf="crumbs$ | async as crumbs" class="breadcrumbs__container"> <li *ngFor="let crumb of crumbs; let last = last" [ngClass]="{ 'breadcrumbs__item--active': last }" class="breadcrumbs__item" > <a *ngIf="!last" [routerLink]="crumb.path">{{ crumb.text }}</a> <span *ngIf="last">{{ crumb.text }}</span> </li> </ol> `, isInline: true, dependencies: [{ kind: "directive", type: i2.NgClass, selector: "[ngClass]", inputs: ["class", "ngClass"] }, { kind: "directive", type: i2.NgForOf, selector: "[ngFor][ngForOf]", inputs: ["ngForOf", "ngForTrackBy", "ngForTemplate"] }, { kind: "directive", type: i2.NgIf, selector: "[ngIf]", inputs: ["ngIf", "ngIfThen", "ngIfElse"] }, { kind: "directive", type: i1.RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "pipe", type: i2.AsyncPipe, name: "async" }] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.1", ngImport: i0, type: BreadcrumbsComponent, decorators: [{ type: Component, args: [{ selector: 'lib-breadcrumbs', template: ` <ol *ngIf="crumbs$ | async as crumbs" class="breadcrumbs__container"> <li *ngFor="let crumb of crumbs; let last = last" [ngClass]="{ 'breadcrumbs__item--active': last }" class="breadcrumbs__item" > <a *ngIf="!last" [routerLink]="crumb.path">{{ crumb.text }}</a> <span *ngIf="last">{{ crumb.text }}</span> </li> </ol> ` }] }], ctorParameters: function () { return [{ type: BreadcrumbsService }]; } }); // @dynamic class BreadcrumbsModule { static forRoot(config) { return { ngModule: BreadcrumbsModule, providers: [ { provide: BreadcrumbsConfig, useFactory: () => new BreadcrumbsConfig(config) }, BreadcrumbsService, ], }; } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "16.0.1", ngImport: i0, type: BreadcrumbsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); } static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "16.0.1", ngImport: i0, type: BreadcrumbsModule, declarations: [BreadcrumbsComponent], imports: [CommonModule, RouterModule], exports: [BreadcrumbsComponent] }); } static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "16.0.1", ngImport: i0, type: BreadcrumbsModule, imports: [CommonModule, RouterModule] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "16.0.1", ngImport: i0, type: BreadcrumbsModule, decorators: [{ type: NgModule, args: [{ imports: [ CommonModule, RouterModule, ], declarations: [BreadcrumbsComponent], exports: [BreadcrumbsComponent], }] }] }); /** * Generated bundle index. Do not edit. */ export { BreadcrumbsComponent, BreadcrumbsConfig, BreadcrumbsModule, BreadcrumbsResolver, BreadcrumbsService }; //# sourceMappingURL=exalif-ngx-breadcrumbs.mjs.map