import { LightningElement, api } from "lwc";
import cx from "classnames";
import { Brand, OptionWithLink, OptionWithNested } from "typings/custom";
import { toJson, normalizeBoolean } from "dxUtils/normalizers";
import { track } from "dxUtils/analytics";
const VALID_BRANDS = [
"analytics",
"commerce",
"employees",
"data",
"industries",
"integration",
"learning",
"marketing",
"partners",
"platform",
"revenue",
"sales",
"service",
"success",
"einstein"
];
export const ANALYTICS_INFO = {
click_text: "browse trials",
element_type: "button",
content_category: "cta"
};
export abstract class HeaderBase extends LightningElement {
@api bailHref?: string | null = null;
@api bailLabel?: string | null = null;
@api brand: Brand | null = null;
@api coveoOrganizationId: string | null = null;
@api coveoPublicAccessToken: string | null = null;
@api coveoSearchHub: string | null = null;
@api coveoSearchPipeline: string | null = null;
@api signupLink?: string | null = null;
@api href = null;
@api subtitle!: string;
@api tbidApiBaseUrl: string | null = null;
@api tbidBaseUrl: string | null = null;
@api header: string = "Salesforce";
@api version?: string | null = null;
@api bannerMarkup =
'Share your feedbackabout our new site.';
@api
get navItems() {
return this._navItems;
}
set navItems(value) {
this._navItems = toJson(value);
}
@api
get versions() {
return this._versions;
}
set versions(value) {
this._versions = toJson(value);
}
@api
get showBanner() {
return this._showBanner && this.bannerMarkup;
}
set showBanner(value) {
this._showBanner = normalizeBoolean(value);
}
private _navItems!: OptionWithNested[];
private _versions!: OptionWithLink[];
private matchMedia!: MediaQueryList;
protected mobile: boolean = false;
private mobileNavMenuValue: string | null = null;
private showMobileNavMenu: boolean = false;
private showNavScrollShadow: boolean = false;
protected isSearchOpen: boolean = false;
private _showBanner?: boolean = false;
get url() {
return this.href ? new URL(this.href!) : window.location;
}
get hasBailLink(): boolean {
return !!(this.bailHref && this.bailLabel);
}
get hasSearch() {
return (
this.coveoOrganizationId &&
this.coveoPublicAccessToken &&
this.coveoSearchHub &&
this.coveoSearchPipeline
);
}
get pathname() {
return this.url.pathname;
}
get className() {
return cx(
this.hasNavItems && "has-nav-items",
this.showMobileNavMenu && "state-show-mobile-nav",
this.showNavScrollShadow &&
!this.showMobileNavMenu &&
"has-navscrollshadow",
this.additionalClasses()
);
}
get versionLabel() {
const selectedVersion = (this.versions || []).find(
(v) => v.id === this.version
);
return selectedVersion ? selectedVersion.label : "";
}
get mobileMenuIconSymbol() {
return this.showMobileNavMenu ? "close" : "rows";
}
get isValidBrand() {
return this.brand && VALID_BRANDS.includes(this.brand);
}
get hasNavItems(): boolean {
return this.navItems && this.navItems.length > 0;
}
connectedCallback() {
this.matchMedia = window.matchMedia(
`(max-width: ${this.mobileBreakpoint()})`
);
this.onMediaChange(this.matchMedia);
this.matchMedia.addEventListener("change", this.onMediaChange);
this.hashLinkScroll();
}
disconnectedCallback() {
this.matchMedia.removeEventListener("change", this.onMediaChange);
}
// Temporary solution to restore native anchor scrolling
private hashLinkScroll() {
const hash = window.location.hash;
if (hash !== "") {
// Push onto callback queue so it runs after the DOM is updated
setTimeout(() => {
const id = hash.replace("#", "");
const element = document.getElementById(id);
if (element && element.scrollIntoView) {
element.scrollIntoView();
}
}, 0);
}
}
private handleStateChange(event: CustomEvent) {
event.stopPropagation();
this.isSearchOpen = event.detail;
}
onVersionChange(e: CustomEvent) {
this.dispatchEvent(
new CustomEvent("versionchange", {
detail: e.detail
})
);
}
onRequestOpenNavMenu(e: { detail: string }) {
this.mobileNavMenuValue = e.detail;
this.showMobileNavMenu = true;
}
private onMobileNavMenuChange(e: { detail: string }) {
this.mobileNavMenuValue = e.detail;
}
private toggleMobileNavMenu() {
this.showMobileNavMenu = !this.showMobileNavMenu;
}
private closeMobileNavMenu() {
this.showMobileNavMenu = false;
}
private onNavScroll(e: Event) {
this.showNavScrollShadow =
(e.currentTarget).scrollLeft > 4;
}
private onMediaChange = (e: MediaQueryListEvent | MediaQueryList) => {
if (!e.matches) {
this.mobile = false;
this.closeMobileNavMenu();
} else {
this.mobile = true;
}
};
private handleSignUpClick(e: PointerEvent) {
const payload = {
...ANALYTICS_INFO,
click_url: this.signupLink,
element_title: this.header
};
track(e.currentTarget!, "custEv_browseTrialsClick", payload);
track(e.currentTarget!, "custEv_linkClick", payload);
}
protected additionalClasses(): string {
return "";
}
protected abstract mobileBreakpoint(): string;
}