UNPKG

ez-nav

Version:

A responsive, configurable Angular navigation bar component with support for dropdown menus, mobile drawer toggles, and custom layouts. Easily integrate a dynamic navbar using a simple configuration object.

140 lines (133 loc) 14.1 kB
import * as i0 from '@angular/core'; import { Injectable, EventEmitter, Output, Input, Component, NgModule } from '@angular/core'; import * as i2 from '@angular/common'; import { CommonModule } from '@angular/common'; import { RouterLink, RouterModule } from '@angular/router'; import { BehaviorSubject } from 'rxjs'; class ScreenSizeService { ngZone; screenWidthSubject = new BehaviorSubject("desktop"); screenWidth$ = this.screenWidthSubject.asObservable(); constructor(ngZone) { this.ngZone = ngZone; // Listen to window resize in the service if (window.innerWidth <= 600) { this.screenWidthSubject.next("mobile"); } else if (window.innerWidth > 600 && window.innerWidth <= 1024) { this.screenWidthSubject.next("tablet"); } else if (window.innerWidth > 1024) { this.screenWidthSubject.next("desktop"); } this.listenToResize(); } listenToResize() { this.ngZone.runOutsideAngular(() => { window.addEventListener('resize', () => { this.ngZone.run(() => { if (window.innerWidth <= 600) { this.screenWidthSubject.next("mobile"); } else if (window.innerWidth > 600 && window.innerWidth <= 1024) { this.screenWidthSubject.next("tablet"); } else if (window.innerWidth > 1024) { this.screenWidthSubject.next("desktop"); } }); }); }); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.9", ngImport: i0, type: ScreenSizeService, deps: [{ token: i0.NgZone }], target: i0.ɵɵFactoryTarget.Injectable }); static ɵprov = i0.ɵɵngDeclareInjectable({ minVersion: "12.0.0", version: "19.2.9", ngImport: i0, type: ScreenSizeService, providedIn: 'root' }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.9", ngImport: i0, type: ScreenSizeService, decorators: [{ type: Injectable, args: [{ providedIn: 'root' }] }], ctorParameters: () => [{ type: i0.NgZone }] }); class NavDrawerComponent { screenSizeService; navRow; drawerPosition = new EventEmitter(false); screenType = null; isDrawerOpen = false; screenSizeSubscription; subNavsOpen = []; constructor(screenSizeService) { this.screenSizeService = screenSizeService; } ngOnInit() { this.screenSizeSubscription = this.screenSizeService.screenWidth$.subscribe(screenType => { this.screenType = screenType; }); this.subNavsOpen = this.navRow.items.map(item => !!item.subNav?.length && false); } toggleSubNav(index, event) { event.preventDefault(); event.stopPropagation(); // Close all others, open the clicked one this.subNavsOpen = this.subNavsOpen.map((open, i) => i === index ? !open : false); } ngOnDestroy() { if (this.screenSizeSubscription) { this.screenSizeSubscription.unsubscribe(); } } updateDrawer(drawerPosition) { this.isDrawerOpen = drawerPosition; this.drawerPosition.emit(drawerPosition); } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.9", ngImport: i0, type: NavDrawerComponent, deps: [{ token: ScreenSizeService }], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.9", type: NavDrawerComponent, isStandalone: true, selector: "ez-nav-nav-drawer", inputs: { navRow: "navRow" }, outputs: { drawerPosition: "drawerPosition" }, ngImport: i0, template: "\n<div class=\"row\">\n <ng-container *ngIf=\"screenType === 'desktop' || screenType === 'tablet'\">\n <ng-container *ngFor=\"let link of navRow.items; let i = index\">\n <div [ngClass]=\"link.gridClasses\" (click)=\"toggleSubNav(i, $event)\">\n <a [routerLink]=\"link.route\" [ngClass]=\"link.anchorTagClass\" class=\"d-flex align-items-center gap-1\">\n <span>{{ link.title }}</span>\n\n <!-- Subnav Icons -->\n <ng-container *ngIf=\"link.subNav?.length\">\n <i class=\"bi\"\n [ngClass]=\"subNavsOpen[i] ? link.subNavOpenClasses : link.subNavCloseClasses\"\n style=\"cursor: pointer;\">\n </i>\n </ng-container>\n </a>\n\n <div *ngIf=\"subNavsOpen[i]\" [ngClass]=\"link.dropDownParentClasses\">\n <ng-container *ngFor=\"let sub of link.subNav\">\n <div>\n <a\n [routerLink]=\"sub.route\"\n [ngClass]=\"sub.cssClasses\">\n {{ sub.title }}\n </a>\n </div>\n </ng-container>\n </div>\n\n </div>\n </ng-container>\n </ng-container>\n <ng-container *ngIf=\"screenType==='mobile'\">\n <!--\n drawerIcon bi bi-filter-right\n drawerIcon bi bi-filter-left\n -->\n <i (click)=\"updateDrawer(true)\" *ngIf=\"!isDrawerOpen\" [ngClass]=\"navRow.drawerIconOpen\"></i>\n <i (click)=\"updateDrawer(false)\" *ngIf=\"isDrawerOpen\" [ngClass]=\"navRow.drawerIconClosed\"></i>\n </ng-container>\n </div>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { 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: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }] }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.9", ngImport: i0, type: NavDrawerComponent, decorators: [{ type: Component, args: [{ selector: 'ez-nav-nav-drawer', standalone: true, imports: [CommonModule, RouterLink], template: "\n<div class=\"row\">\n <ng-container *ngIf=\"screenType === 'desktop' || screenType === 'tablet'\">\n <ng-container *ngFor=\"let link of navRow.items; let i = index\">\n <div [ngClass]=\"link.gridClasses\" (click)=\"toggleSubNav(i, $event)\">\n <a [routerLink]=\"link.route\" [ngClass]=\"link.anchorTagClass\" class=\"d-flex align-items-center gap-1\">\n <span>{{ link.title }}</span>\n\n <!-- Subnav Icons -->\n <ng-container *ngIf=\"link.subNav?.length\">\n <i class=\"bi\"\n [ngClass]=\"subNavsOpen[i] ? link.subNavOpenClasses : link.subNavCloseClasses\"\n style=\"cursor: pointer;\">\n </i>\n </ng-container>\n </a>\n\n <div *ngIf=\"subNavsOpen[i]\" [ngClass]=\"link.dropDownParentClasses\">\n <ng-container *ngFor=\"let sub of link.subNav\">\n <div>\n <a\n [routerLink]=\"sub.route\"\n [ngClass]=\"sub.cssClasses\">\n {{ sub.title }}\n </a>\n </div>\n </ng-container>\n </div>\n\n </div>\n </ng-container>\n </ng-container>\n <ng-container *ngIf=\"screenType==='mobile'\">\n <!--\n drawerIcon bi bi-filter-right\n drawerIcon bi bi-filter-left\n -->\n <i (click)=\"updateDrawer(true)\" *ngIf=\"!isDrawerOpen\" [ngClass]=\"navRow.drawerIconOpen\"></i>\n <i (click)=\"updateDrawer(false)\" *ngIf=\"isDrawerOpen\" [ngClass]=\"navRow.drawerIconClosed\"></i>\n </ng-container>\n </div>\n" }] }], ctorParameters: () => [{ type: ScreenSizeService }], propDecorators: { navRow: [{ type: Input }], drawerPosition: [{ type: Output }] } }); class EzNavComponent { header; isDrawerOpen = false; subNavsOpen = []; ngOnInit() { this.subNavsOpen = this.header.navRow.items.map(item => !!(item.subNav && item.subNav.length > 0) ? false : false); } toggleSubNav(index) { this.subNavsOpen[index] = !this.subNavsOpen[index]; } handleDrawerStatus(status) { this.isDrawerOpen = status; } static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.9", ngImport: i0, type: EzNavComponent, deps: [], target: i0.ɵɵFactoryTarget.Component }); static ɵcmp = i0.ɵɵngDeclareComponent({ minVersion: "14.0.0", version: "19.2.9", type: EzNavComponent, isStandalone: true, selector: "ez-nav", inputs: { header: "header" }, ngImport: i0, template: "<div [ngClass]=\"header.wrappingClass\">\n <div class=\"row\">\n <div [ngClass]=\"header.parentRowLogoClasses\">\n <img [src]=\"header.logo.src\" [alt]=\"header.logo.alt\" [ngClass]=\"header.logo.imageClassNames\" />\n </div>\n <div [ngClass]=\"header.parentNavItemsClasses\">\n <ez-nav-nav-drawer (drawerPosition)=\"handleDrawerStatus($event)\" [navRow]=\"header.navRow\"></ez-nav-nav-drawer>\n </div>\n </div>\n <div *ngIf=\"isDrawerOpen\">\n <ng-container *ngFor=\"let link of header.navRow.items; let i = index\">\n <div class=\"col-md-12 col-sm-12\" (click)=\"toggleSubNav(i); $event.preventDefault(); $event.stopPropagation();\">\n <a [ngClass]=\"link.anchorTagClassMobile\" [routerLink]=\"link.route\">\n {{ link.title }}\n <ng-container *ngIf=\"link.subNav?.length\">\n <i\n class=\"bi\"\n [ngClass]=\"subNavsOpen[i] ? link.subNavOpenClasses : link.subNavCloseClasses\">\n </i>\n </ng-container>\n </a>\n </div>\n <ng-container *ngIf=\"subNavsOpen[i] && link.subNav?.length\">\n <div class=\"row\">\n <a *ngFor=\"let sub of link.subNav\" [routerLink]=\"sub.route\" [ngClass]=\"sub.cssClasses\">\n {{ sub.title }}\n </a>\n </div>\n </ng-container>\n </ng-container>\n </div>\n</div>\n", dependencies: [{ kind: "ngmodule", type: CommonModule }, { 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: RouterLink, selector: "[routerLink]", inputs: ["target", "queryParams", "fragment", "queryParamsHandling", "state", "info", "relativeTo", "preserveFragment", "skipLocationChange", "replaceUrl", "routerLink"] }, { kind: "component", type: NavDrawerComponent, selector: "ez-nav-nav-drawer", inputs: ["navRow"], outputs: ["drawerPosition"] }] }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.9", ngImport: i0, type: EzNavComponent, decorators: [{ type: Component, args: [{ selector: 'ez-nav', standalone: true, imports: [CommonModule, RouterLink, NavDrawerComponent], template: "<div [ngClass]=\"header.wrappingClass\">\n <div class=\"row\">\n <div [ngClass]=\"header.parentRowLogoClasses\">\n <img [src]=\"header.logo.src\" [alt]=\"header.logo.alt\" [ngClass]=\"header.logo.imageClassNames\" />\n </div>\n <div [ngClass]=\"header.parentNavItemsClasses\">\n <ez-nav-nav-drawer (drawerPosition)=\"handleDrawerStatus($event)\" [navRow]=\"header.navRow\"></ez-nav-nav-drawer>\n </div>\n </div>\n <div *ngIf=\"isDrawerOpen\">\n <ng-container *ngFor=\"let link of header.navRow.items; let i = index\">\n <div class=\"col-md-12 col-sm-12\" (click)=\"toggleSubNav(i); $event.preventDefault(); $event.stopPropagation();\">\n <a [ngClass]=\"link.anchorTagClassMobile\" [routerLink]=\"link.route\">\n {{ link.title }}\n <ng-container *ngIf=\"link.subNav?.length\">\n <i\n class=\"bi\"\n [ngClass]=\"subNavsOpen[i] ? link.subNavOpenClasses : link.subNavCloseClasses\">\n </i>\n </ng-container>\n </a>\n </div>\n <ng-container *ngIf=\"subNavsOpen[i] && link.subNav?.length\">\n <div class=\"row\">\n <a *ngFor=\"let sub of link.subNav\" [routerLink]=\"sub.route\" [ngClass]=\"sub.cssClasses\">\n {{ sub.title }}\n </a>\n </div>\n </ng-container>\n </ng-container>\n </div>\n</div>\n" }] }], propDecorators: { header: [{ type: Input }] } }); class NavbarModule { static ɵfac = i0.ɵɵngDeclareFactory({ minVersion: "12.0.0", version: "19.2.9", ngImport: i0, type: NavbarModule, deps: [], target: i0.ɵɵFactoryTarget.NgModule }); static ɵmod = i0.ɵɵngDeclareNgModule({ minVersion: "14.0.0", version: "19.2.9", ngImport: i0, type: NavbarModule, imports: [CommonModule, RouterModule, EzNavComponent, NavDrawerComponent], exports: [EzNavComponent, NavDrawerComponent] }); static ɵinj = i0.ɵɵngDeclareInjector({ minVersion: "12.0.0", version: "19.2.9", ngImport: i0, type: NavbarModule, imports: [CommonModule, RouterModule, EzNavComponent, NavDrawerComponent] }); } i0.ɵɵngDeclareClassMetadata({ minVersion: "12.0.0", version: "19.2.9", ngImport: i0, type: NavbarModule, decorators: [{ type: NgModule, args: [{ declarations: [], imports: [CommonModule, RouterModule, EzNavComponent, NavDrawerComponent], exports: [EzNavComponent, NavDrawerComponent] }] }] }); /** * Generated bundle index. Do not edit. */ export { EzNavComponent, NavDrawerComponent, NavbarModule, ScreenSizeService }; //# sourceMappingURL=ez-nav.mjs.map