import {Component, Element, h, Host, Listen, Prop, State} from '@stencil/core'; @Component({ tag: 'hy-menu-level-container', styleUrl: 'menu-level-container.scss', shadow: false }) export class MenuLevelContainer { @Element() el: HTMLElement; @State() open: boolean = false; @Prop() menuLevel: number; @Prop() menuType?: string; @Prop({mutable: true, reflect: true}) triggerItem: string; @Prop({mutable: true, reflect: true}) depth: number = 0; @Prop({reflect: true}) activeTrailTriggered: boolean = false; @Prop({mutable: true}) headingItem: any; // Add/Remove is-hidden class from each upper level menu-items // to make browsing more accessible. assignMenuItemClass(parentMenu: Element, type: string) { const items = Array.from(parentMenu.children); items.forEach((item) => { if (type === 'remove') { item.classList.remove('is-hidden'); } else { item.classList.add('is-hidden'); } }); } @Listen('menuContainerActiveTrail', {target: 'document', capture: true}) menuContainerActiveTrail(data) { const currentMenuContainer = this.el.getAttribute('trigger-item'); if (currentMenuContainer === data.detail.triggerItem) { this.activeTrailTriggered = true; this.open = true; this.assignMenuItemClass(this.el.parentElement.closest('hy-menu-level-container'), 'add'); } } @Listen('menuContainerToggled', {target: 'document', capture: true}) menuContainerToggled(data) { // Toggle submenu. if (this.triggerItem == data.detail.triggerItem) { this.activeTrailTriggered = false; this.open = !this.open; this.assignMenuItemClass(this.el.parentElement.closest('hy-menu-level-container'), data.detail.triggerType); // Scroll to .hy-menu top. let hyMenu = this.el.parentElement.closest('hy-menu'); hyMenu.shadowRoot.querySelector('.hy-menu').scrollTop = 0; } } componentWillUpdate() { if (this.menuType) { const items = Array.from(this.el.children); items.forEach((item) => { item.setAttribute('menu-type', this.menuType); }); } } componentWillRender() { let parentMenu = this.el.closest('hy-menu-level-container'); let nextParentMenu; this.depth = 0; while (parentMenu) { nextParentMenu = parentMenu.parentElement.closest('hy-menu-level-container'); if (nextParentMenu === parentMenu) { break; } else { parentMenu = nextParentMenu; this.depth = this.depth + 1; } } // Set trigger item for each menu level container and handle only submenus. // Add a heading element foreach level. if (this.menuLevel > 1) { const parentMenuItem = this.el.closest('hy-menu-item'); this.triggerItem = parentMenuItem.getAttribute('menu-link-id'); this.headingItem = {...this.headingItem, url: parentMenuItem.getAttribute('url')}; this.headingItem = {...this.headingItem, label: parentMenuItem.getAttribute('label')}; } else { this.triggerItem = 'home'; } } render() { let classAttributes = ['hy-menu-level-container', 'hy-menu-level-container--level-' + this.depth]; if (this.menuType === 'desktop') { classAttributes = [...classAttributes, 'hy-menu--desktop']; return ( <Host class={classAttributes.join(' ')}> <slot /> </Host> ); } else { classAttributes = [...classAttributes, 'hy-menu--mobile']; if (this.depth === 1) { this.open = true; classAttributes = [...classAttributes, this.open ? 'is-open' : null]; return ( <Host aria-expanded={this.open.toString()} class={classAttributes.join(' ')} tabindex={'-1'}> <slot /> </Host> ); } else { classAttributes = [...classAttributes, this.open ? 'is-open' : null]; return ( <Host aria-expanded={this.open.toString()} class={classAttributes.join(' ')} tabindex={'-1'}> <hy-menu-item label={this.headingItem.label} url={this.headingItem.url} isHeading={true} menu-type={'mobile'} /> <slot /> </Host> ); } } } }