import { LightningElement, api } from "lwc"; import cx from "classnames"; import { OptionWithNested } from "typings/custom"; import { deepmapOptions } from "dxUtils/options"; export default class HeaderMobileNavMenu extends LightningElement { @api open: boolean = false; @api value: string | null = null; @api pathname: string | null = null; @api set navItems(_navItems: OptionWithNested[]) { this._navItems = _navItems; } get navItems() { // first we assign container classnames to the topmost layer of options groupings // (deepmapper only affects actual root options, not groups of options made for the purposes of labeling) const navItems = this._navItems?.map((app) => { const open = app.options ? app.id === this.value : null; const liClassName = cx("nav-menu_item", open && "state-open"); return { ...app, open, liClassName }; }); // then we use deepmapper to affect the actual root options (actual links) return deepmapOptions( navItems, (app: OptionWithNested, index: number, level: number) => { const active = app.link ? app.link.href === this.pathname : false; const className = cx( "nav-menu_item_cta", active && "state-active", level > 1 ? "nav-menu_item_cta-sub" : "nav-menu_item_cta-main" ); const iconSymbol = app.link && app.link.target ? "new_window" : null; return { ...app, className, iconSymbol }; } ); } private _navItems: OptionWithNested[] = []; private navElement: HTMLElement | null = null; private wasOpen: boolean = false; private showScrollShadow: boolean = false; private get className() { return cx( "nav-menu", !this.open && "state-closed", this.showScrollShadow && "has-scrollshadow" ); } renderedCallback() { if (!this.navElement) { this.navElement = this.template.querySelector("nav"); } if (this.open && !this.wasOpen && this.value) { this.scrollToAccordianSection(); } if (this.open !== this.wasOpen) { this.wasOpen = this.open; } } private scrollToAccordianSection() { const element = this.template.querySelector( `li[data-id="${this.value}"]` ); const container = this.template.querySelector(".nav-menu"); if (element && container) { container.scrollTop = element.offsetTop - 8; } } private onScroll(e: Event) { this.showScrollShadow = (e.currentTarget).scrollTop > 4; } private onChange(e: PointerEvent) { const id = (e.currentTarget).getAttribute("data-id"); const detail = id === this.value ? null : id; // toggles accordian open/closed this.dispatchEvent(new CustomEvent("change", { detail })); } private onClickLink() { this.dispatchEvent(new CustomEvent("requestclose")); } private onClickBackground() { this.dispatchEvent(new CustomEvent("requestclose")); } }