/* This Source Code Form is subject to the terms of the Mozilla Public * License, v. 2.0. If a copy of the MPL was not distributed with this * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ import { html, when } from "chrome://global/content/vendor/lit.all.mjs"; import { MozLitElement } from "chrome://global/content/lit-utils.mjs"; // eslint-disable-next-line import/no-unassigned-import import "chrome://global/content/elements/moz-support-link.mjs"; /** * A grouping of navigation buttons that is displayed at the page level, * intended to change the selected view, provide a heading, and have links * to external resources. * * @tagname moz-page-nav * @property {string} currentView - The currently selected view. * @property {string} heading - A heading to be displayed at the top of the navigation. * @slot [default] - Used to append moz-page-nav-button elements to the navigation. * @slot [subheading] - Used to append page specific search input or notification to the nav. */ export default class MozPageNav extends MozLitElement { static properties = { currentView: { type: String }, heading: { type: String, fluent: true }, }; static queries = { headingEl: "#page-nav-heading", primaryNavGroupSlot: ".primary-nav-group slot", secondaryNavGroupSlot: "#secondary-nav-group slot", }; get pageNavButtons() { return this.getVisibleSlottedChildren(this.primaryNavGroupSlot); } get secondaryNavButtons() { return this.getVisibleSlottedChildren(this.secondaryNavGroupSlot); } getVisibleSlottedChildren(el) { return el ?.assignedElements() .filter( element => element?.localName === "moz-page-nav-button" && this.checkElementVisibility(element) ); } checkElementVisibility(element) { let computedStyles = window.getComputedStyle(element); return ( !element.hidden && computedStyles.getPropertyValue("display") !== "none" && computedStyles.getPropertyValue("visibility") !== "hidden" && computedStyles.getPropertyValue("opacity") > 0 ); } onChangeView(e) { this.currentView = e.target.view; } handleFocus(e) { if (e.key == "ArrowDown" || e.key == "ArrowRight") { e.preventDefault(); this.focusNextView(); } else if (e.key == "ArrowUp" || e.key == "ArrowLeft") { e.preventDefault(); this.focusPreviousView(); } } focusPreviousView() { let pageNavButtons = this.pageNavButtons; let currentIndex = pageNavButtons.findIndex(b => b.selected); let prev = pageNavButtons[currentIndex - 1]; if (prev) { prev.activate(); prev.buttonEl.focus(); } } focusNextView() { let pageNavButtons = this.pageNavButtons; let currentIndex = pageNavButtons.findIndex(b => b.selected); let next = pageNavButtons[currentIndex + 1]; if (next) { next.activate(); next.buttonEl.focus(); } } onSecondaryNavChange(event) { let secondaryNavElements = event.target.assignedElements(); this.hasSecondaryNav = !!secondaryNavElements.length; secondaryNavElements?.forEach(el => { el.classList.add("secondary-nav-item"); }); } render() { return html`