/* 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 } from "chrome://global/content/vendor/lit.all.mjs";
import { MozLitElement } from "chrome://global/content/lit-utils.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.
*/
export default class MozPageNav extends MozLitElement {
static properties = {
currentView: { type: String },
heading: { type: String },
};
static queries = {
headingEl: "#page-nav-header",
primaryNavGroupSlot: ".primary-nav-group slot",
secondaryNavGroupSlot: "#secondary-nav-group slot",
};
get pageNavButtons() {
return this.primaryNavGroupSlot
.assignedNodes()
.filter(
node => node?.localName === "moz-page-nav-button" && !node.hidden
);
}
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();
}
}
render() {
return html`
`;
}
updated() {
let isViewSelected = false;
let assignedPageNavButtons = this.pageNavButtons;
for (let button of assignedPageNavButtons) {
button.selected = button.view == this.currentView;
isViewSelected = isViewSelected || button.selected;
}
if (!isViewSelected && assignedPageNavButtons.length) {
// Current page nav has no matching view, reset to the first view.
assignedPageNavButtons[0].activate();
}
}
}
customElements.define("moz-page-nav", MozPageNav);
/**
* A navigation button intended to change the selected view within a page.
*
* @tagname moz-page-nav-button
* @property {string} iconSrc - The chrome:// url for the icon used for the button.
* @property {string} l10nId - The fluent ID for the button's text
* @property {boolean} selected - Whether or not the button is currently selected.
* @slot [default] - Used to append the l10n string to the button.
*/
export class MozPageNavButton extends MozLitElement {
static properties = {
iconSrc: { type: String },
l10nId: { type: String },
selected: { type: Boolean },
};
connectedCallback() {
super.connectedCallback();
this.setAttribute("role", "none");
}
static queries = {
buttonEl: "button",
};
get view() {
return this.getAttribute("view");
}
activate() {
this.dispatchEvent(
new CustomEvent("change-view", {
bubbles: true,
composed: true,
})
);
}
render() {
return html`
`;
}
}
customElements.define("moz-page-nav-button", MozPageNavButton);