UNPKG

ng-hub-ui-breadcrumbs

Version:

A flexible and reusable breadcrumb component for Angular applications that automatically generates breadcrumbs based on routing configuration

133 lines (125 loc) 10.4 kB
import * as i0 from '@angular/core'; import { inject, TemplateRef, Directive, Injectable, Component, ContentChild, NgModule } from '@angular/core'; import { AsyncPipe, NgTemplateOutlet } from '@angular/common'; import { Router, ActivatedRoute, NavigationEnd, RouterLink } from '@angular/router'; import { filter, startWith, map } from 'rxjs'; class HubBreadcrumbItemDirective { constructor() { this.template = inject((TemplateRef)); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: HubBreadcrumbItemDirective, deps: [], target: i0.ɵɵFactoryTarget.Directive }); } static { this.ɵdir = i0.ɵɵngDeclareDirective({ minVersion: "14.0.0", version: "19.0.4", type: HubBreadcrumbItemDirective, isStandalone: true, selector: "[hubBreadcrumbItem]", ngImport: i0 }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: HubBreadcrumbItemDirective, decorators: [{ type: Directive, args: [{ selector: '[hubBreadcrumbItem]', standalone: true }] }] }); class HubBreadcrumbsService { constructor() { this.#router = inject(Router); this.#activatedRoute = inject(ActivatedRoute); this.breadcrumbs$ = this.#router.events.pipe(filter((event) => event instanceof NavigationEnd), startWith(undefined), map(() => this.createBreadcrumbs(this.#activatedRoute.root))); } #router; #activatedRoute; createBreadcrumbs(route, url = '', breadcrumbs = []) { const children = route.children; if (children.length === 0) { return breadcrumbs; } for (const child of children) { const routeSegments = child.snapshot.url; // Construir la URL para este nivel const routeURL = routeSegments .map((segment) => segment.path) .join('/'); const nextUrl = routeURL ? `${url}/${routeURL}` : url; // Verificar si esta ruta específica tiene datos de breadcrumb const hasBreadcrumbData = this.hasOwnBreadcrumbData(child); if (hasBreadcrumbData) { const label = this.getBreadcrumbLabel(child); breadcrumbs.push({ label, url: nextUrl, data: child.snapshot.data }); } // Continuar con los hijos return this.createBreadcrumbs(child, nextUrl, breadcrumbs); } return breadcrumbs; } hasOwnBreadcrumbData(route) { // Verificar si la ruta tiene su propia configuración de breadcrumb const routeConfig = route.routeConfig; return !!(routeConfig && routeConfig.data && routeConfig.data['breadcrumb']); } getBreadcrumbLabel(route) { const data = route.snapshot.data; let label = data['breadcrumb']; if (typeof label === 'function') { label = label(data); } if (data['resolvedData']) { label = this.getResolvedBreadcrumb(label, data['resolvedData']); } return label; } getResolvedBreadcrumb(template, data) { return template.replace(/\{([^}]+)\}/g, (match, key) => { return data[key] || match; }); } static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: HubBreadcrumbsService, deps: [], target: i0.ɵɵFactoryTarget.Injectable }); } static { this.ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: HubBreadcrumbsService, providedIn: 'root' }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: HubBreadcrumbsService, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }] }); class HubBreadcrumbsComponent { constructor() { this.#breadcrumbsSvc = inject(HubBreadcrumbsService); this.breadcrumbs$ = this.#breadcrumbsSvc.breadcrumbs$; } #breadcrumbsSvc; static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: HubBreadcrumbsComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); } static { this.ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "17.0.0", version: "19.0.4", type: HubBreadcrumbsComponent, isStandalone: true, selector: "hub-breadcrumbs", host: { classAttribute: "hub-breadcrumb" }, queries: [{ propertyName: "itemTemplate", first: true, predicate: HubBreadcrumbItemDirective, descendants: true }], ngImport: i0, template: "<nav aria-label=\"breadcrumb\" class=\"hub-breadcrumb__nav\">\n\t<ol class=\"hub-breadcrumb__list\">\n\t\t@for (item of breadcrumbs$ | async; track item; let last = $last) {\n\t\t<li\n\t\t\tclass=\"hub-breadcrumb__item\"\n\t\t\t[class.hub-breadcrumb__item--active]=\"last\"\n\t\t>\n\t\t\t@if (itemTemplate) {\n\t\t\t<ng-container\n\t\t\t\t[ngTemplateOutlet]=\"itemTemplate.template\"\n\t\t\t\t[ngTemplateOutletContext]=\"{ $implicit: item, isLast: last }\"\n\t\t\t/>\n\t\t\t} @else { @if (!last) {\n\t\t\t<a [routerLink]=\"item.url\" class=\"hub-breadcrumb__link\">\n\t\t\t\t{{ item.label }}\n\t\t\t</a>\n\t\t\t} @else {\n\t\t\t<span class=\"hub-breadcrumb__text\">{{ item.label }}</span>\n\t\t\t} }\n\t\t</li>\n\t\t}\n\t</ol>\n</nav>\n", styles: [".hub-breadcrumb__list{--hub-breadcrumb-padding-x: 1rem;--hub-breadcrumb-padding-y: .25rem;--hub-breadcrumb-margin-bottom: 0;--hub-breadcrumb-bg: white;--hub-breadcrumb-border-radius: 50rem;--hub-breadcrumb-divider-color: black;--hub-breadcrumb-item-padding-x: .5rem;--hub-breadcrumb-item-active-color: black;display:flex;flex-wrap:wrap;padding:var(--hub-breadcrumb-padding-y) var(--hub-breadcrumb-padding-x);margin-bottom:var(--hub-breadcrumb-margin-bottom);list-style:none;background-color:var(--hub-breadcrumb-bg)}.hub-breadcrumb__item+.hub-breadcrumb__item{padding-left:var(--hub-breadcrumb-item-padding-x)}.hub-breadcrumb__item+.hub-breadcrumb__item:before{float:left;padding-right:var(--hub-breadcrumb-item-padding-x);color:var(--hub-breadcrumb-divider-color);content:var(--hub-breadcrumb-divider, \">\")}.hub-breadcrumb__item--active{color:var(--hub-breadcrumb-item-active-color)}\n"], dependencies: [{ kind: "pipe", type: AsyncPipe, name: "async" }, { kind: "directive", type: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "directive", type: NgTemplateOutlet, selector: "[ngTemplateOutlet]", inputs: ["ngTemplateOutletContext", "ngTemplateOutlet", "ngTemplateOutletInjector"] }] }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: HubBreadcrumbsComponent, decorators: [{ type: Component, args: [{ selector: 'hub-breadcrumbs', standalone: true, imports: [AsyncPipe, RouterLink, NgTemplateOutlet], host: { class: 'hub-breadcrumb' }, template: "<nav aria-label=\"breadcrumb\" class=\"hub-breadcrumb__nav\">\n\t<ol class=\"hub-breadcrumb__list\">\n\t\t@for (item of breadcrumbs$ | async; track item; let last = $last) {\n\t\t<li\n\t\t\tclass=\"hub-breadcrumb__item\"\n\t\t\t[class.hub-breadcrumb__item--active]=\"last\"\n\t\t>\n\t\t\t@if (itemTemplate) {\n\t\t\t<ng-container\n\t\t\t\t[ngTemplateOutlet]=\"itemTemplate.template\"\n\t\t\t\t[ngTemplateOutletContext]=\"{ $implicit: item, isLast: last }\"\n\t\t\t/>\n\t\t\t} @else { @if (!last) {\n\t\t\t<a [routerLink]=\"item.url\" class=\"hub-breadcrumb__link\">\n\t\t\t\t{{ item.label }}\n\t\t\t</a>\n\t\t\t} @else {\n\t\t\t<span class=\"hub-breadcrumb__text\">{{ item.label }}</span>\n\t\t\t} }\n\t\t</li>\n\t\t}\n\t</ol>\n</nav>\n", styles: [".hub-breadcrumb__list{--hub-breadcrumb-padding-x: 1rem;--hub-breadcrumb-padding-y: .25rem;--hub-breadcrumb-margin-bottom: 0;--hub-breadcrumb-bg: white;--hub-breadcrumb-border-radius: 50rem;--hub-breadcrumb-divider-color: black;--hub-breadcrumb-item-padding-x: .5rem;--hub-breadcrumb-item-active-color: black;display:flex;flex-wrap:wrap;padding:var(--hub-breadcrumb-padding-y) var(--hub-breadcrumb-padding-x);margin-bottom:var(--hub-breadcrumb-margin-bottom);list-style:none;background-color:var(--hub-breadcrumb-bg)}.hub-breadcrumb__item+.hub-breadcrumb__item{padding-left:var(--hub-breadcrumb-item-padding-x)}.hub-breadcrumb__item+.hub-breadcrumb__item:before{float:left;padding-right:var(--hub-breadcrumb-item-padding-x);color:var(--hub-breadcrumb-divider-color);content:var(--hub-breadcrumb-divider, \">\")}.hub-breadcrumb__item--active{color:var(--hub-breadcrumb-item-active-color)}\n"] }] }], propDecorators: { itemTemplate: [{ type: ContentChild, args: [HubBreadcrumbItemDirective] }] } }); class HubBreadcrumbsModule { static { this.ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: HubBreadcrumbsModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); } static { this.ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.0.4", ngImport: i0, type: HubBreadcrumbsModule, imports: [HubBreadcrumbsComponent, HubBreadcrumbItemDirective], exports: [HubBreadcrumbsComponent, HubBreadcrumbItemDirective] }); } static { this.ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: HubBreadcrumbsModule }); } } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.0.4", ngImport: i0, type: HubBreadcrumbsModule, decorators: [{ type: NgModule, args: [{ declarations: [], imports: [HubBreadcrumbsComponent, HubBreadcrumbItemDirective], exports: [HubBreadcrumbsComponent, HubBreadcrumbItemDirective] }] }] }); /* * Public API Surface of breadcrumbs */ /** * Generated bundle index. Do not edit. */ export { HubBreadcrumbItemDirective, HubBreadcrumbsComponent, HubBreadcrumbsModule, HubBreadcrumbsService }; //# sourceMappingURL=ng-hub-ui-breadcrumbs.mjs.map