import { Component, Input, Output, EventEmitter, ChangeDetectionStrategy, ViewEncapsulation, signal, computed, inject, OnInit, OnDestroy, HostListener } from '@angular/core';
import { CommonModule } from '@angular/common';
import { RouterModule } from '@angular/router';
import { Subject, takeUntil } from 'rxjs';
import { faBars, faXmark } from '@fortawesome/free-solid-svg-icons';
import { LandingHeaderConfig, NavigationItem, LogoConfig } from '../../interfaces/navigation.interfaces';
import { CTAButton } from '../../interfaces/shared.interfaces';
import { ButtonComponent, ContainerComponent, FlexComponent, IconButtonComponent } from 'ui-essentials';
@Component({
selector: 'ui-lp-header',
standalone: true,
imports: [
CommonModule,
RouterModule,
ButtonComponent,
ContainerComponent,
FlexComponent,
IconButtonComponent
],
changeDetection: ChangeDetectionStrategy.OnPush,
encapsulation: ViewEncapsulation.None,
template: `
`,
styleUrl: './landing-header.component.scss'
})
export class LandingHeaderComponent implements OnInit, OnDestroy {
private destroy$ = new Subject();
// FontAwesome icons
faXmark = faXmark;
faBars = faBars;
config = signal({
logo: { text: 'Logo' },
navigation: [],
transparent: false,
sticky: true,
showMobileMenu: true,
size: 'xl',
theme: 'light'
});
isScrolled = signal(false);
mobileMenuOpen = signal(false);
openDropdown = signal(null);
openMobileDropdown = signal(null);
@Input() set configuration(value: LandingHeaderConfig) {
this.config.set(value);
}
@Output() navigationClicked = new EventEmitter();
@Output() ctaClicked = new EventEmitter();
ngOnInit(): void {
if (this.config().sticky) {
this.setupScrollListener();
}
}
ngOnDestroy(): void {
this.destroy$.next();
this.destroy$.complete();
}
@HostListener('window:scroll', [])
onWindowScroll(): void {
if (this.config().sticky) {
const scrollTop = window.pageYOffset || document.documentElement.scrollTop;
this.isScrolled.set(scrollTop > 10);
}
}
@HostListener('document:click', ['$event'])
onDocumentClick(event: Event): void {
const target = event.target as HTMLElement;
if (!target.closest('.ui-lp-header__nav-link--dropdown')) {
this.openDropdown.set(null);
}
}
@HostListener('window:resize', [])
onWindowResize(): void {
if (window.innerWidth > 768) {
this.mobileMenuOpen.set(false);
}
}
private setupScrollListener(): void {
// Initial scroll check
this.onWindowScroll();
}
toggleMobileMenu(): void {
this.mobileMenuOpen.set(!this.mobileMenuOpen());
this.openMobileDropdown.set(null);
// Prevent body scroll when mobile menu is open
document.body.style.overflow = this.mobileMenuOpen() ? 'hidden' : '';
}
closeMobileMenu(): void {
this.mobileMenuOpen.set(false);
this.openMobileDropdown.set(null);
document.body.style.overflow = '';
}
toggleDropdown(itemId: string): void {
this.openDropdown.set(this.openDropdown() === itemId ? null : itemId);
}
toggleMobileDropdown(itemId: string): void {
this.openMobileDropdown.set(this.openMobileDropdown() === itemId ? null : itemId);
}
handleNavClick(item: NavigationItem): void {
if (item.action) {
item.action();
}
this.navigationClicked.emit(item);
this.closeMobileMenu();
this.openDropdown.set(null);
}
handleCTAClick(): void {
const cta = this.config().ctaButton;
if (cta) {
cta.action();
this.ctaClicked.emit(cta);
}
}
}