From 6bf0a5cb5034a7e684dcc3500e841785237ce2dd Mon Sep 17 00:00:00 2001 From: Daniel Baumann Date: Sun, 7 Apr 2024 19:32:43 +0200 Subject: Adding upstream version 1:115.7.0. Signed-off-by: Daniel Baumann --- .../unifiedtoolbar/content/search-bar.mjs | 121 +++++++++++++++++++++ 1 file changed, 121 insertions(+) create mode 100644 comm/mail/components/unifiedtoolbar/content/search-bar.mjs (limited to 'comm/mail/components/unifiedtoolbar/content/search-bar.mjs') diff --git a/comm/mail/components/unifiedtoolbar/content/search-bar.mjs b/comm/mail/components/unifiedtoolbar/content/search-bar.mjs new file mode 100644 index 0000000000..a450f7349f --- /dev/null +++ b/comm/mail/components/unifiedtoolbar/content/search-bar.mjs @@ -0,0 +1,121 @@ +/* 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/. */ + +/** + * Search input with customizable search button and placeholder. + * Attributes: + * - label: Search field label for accessibility tree. + * - disabled: When present, disable the search field and button. + * Slots in template (#searchBarTemplate): + * - placeholder: Content displayed as placeholder. When not provided, the value + * of the label attribute is shown as placeholder. + * - button: Content displayed on the search button. + * + * @emits search: Event when a search should be executed. detail holds the + * search term. + * @emits autocomplte: Auto complete update. detail holds the current search + * term. + */ +export class SearchBar extends HTMLElement { + static get observedAttributes() { + return ["label", "disabled"]; + } + + /** + * Reference to the input field in the form. + * + * @type {?HTMLInputElement} + */ + #input = null; + + /** + * Reference to the search button in the form. + * + * @type {?HTMLButtonElement} + */ + #button = null; + + #onSubmit = event => { + event.preventDefault(); + if (!this.#input.value) { + return; + } + + const searchEvent = new CustomEvent("search", { + detail: this.#input.value, + cancelable: true, + }); + if (this.dispatchEvent(searchEvent)) { + this.reset(); + } + }; + + #onInput = () => { + const autocompleteEvent = new CustomEvent("autocomplete", { + detail: this.#input.value, + }); + this.dispatchEvent(autocompleteEvent); + }; + + connectedCallback() { + if (this.shadowRoot) { + return; + } + + const shadowRoot = this.attachShadow({ mode: "open" }); + + const template = document + .getElementById("searchBarTemplate") + .content.cloneNode(true); + this.#input = template.querySelector("input"); + this.#button = template.querySelector("button"); + + template.querySelector("form").addEventListener("submit", this.#onSubmit, { + passive: false, + }); + + this.#input.setAttribute("aria-label", this.getAttribute("label")); + template.querySelector("slot[name=placeholder]").textContent = + this.getAttribute("label"); + this.#input.addEventListener("input", this.#onInput); + + const styles = document.createElement("link"); + styles.setAttribute("rel", "stylesheet"); + styles.setAttribute( + "href", + "chrome://messenger/skin/shared/search-bar.css" + ); + shadowRoot.append(styles, template); + } + + attributeChangedCallback(attributeName, oldValue, newValue) { + if (!this.#input) { + return; + } + switch (attributeName) { + case "label": + this.#input.setAttribute("aria-label", newValue); + this.shadowRoot.querySelector("slot[name=placeholder]").textContent = + newValue; + break; + case "disabled": { + const isDisabled = this.hasAttribute("disabled"); + this.#input.disabled = isDisabled; + this.#button.disabled = isDisabled; + } + } + } + + focus() { + this.#input.focus(); + } + + /** + * Reset the search bar to its empty state. + */ + reset() { + this.#input.value = ""; + } +} +customElements.define("search-bar", SearchBar); -- cgit v1.2.3