/* 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 { classMap, html, ifDefined } from "../vendor/lit.all.mjs"; import { MozLitElement } from "../lit-utils.mjs"; /** * Functions to wrap a string in a heading. * * @type {Record ReturnType>} */ const HEADING_LEVEL_TEMPLATES = { 1: label => html`

${label}

`, 2: label => html`

${label}

`, 3: label => html`

${label}

`, 4: label => html`

${label}

`, 5: label => html`
${label}
`, 6: label => html`
${label}
`, }; /** * Fieldset wrapper to lay out form inputs consistently. * * @tagname moz-fieldset * @property {string} label - The label for the fieldset's legend. * @property {string} description - The description for the fieldset. * @property {string} supportPage - Name of the SUMO support page to link to. * @property {number} headingLevel - Render the legend in a heading of this level. * @property {boolean} disabled - Whether the fieldset and its children are disabled. * @property {string} iconSrc - The src for an optional icon. */ export default class MozFieldset extends MozLitElement { static properties = { label: { type: String, fluent: true }, description: { type: String, fluent: true }, supportPage: { type: String, attribute: "support-page" }, ariaLabel: { type: String, fluent: true, mapped: true }, ariaOrientation: { type: String, mapped: true }, headingLevel: { type: Number }, disabled: { type: Boolean, reflect: true }, iconSrc: { type: String }, }; constructor() { super(); /** @type {number} */ this.headingLevel = -1; /** @type {boolean} */ this.disabled = false; /** @type {string} */ this.iconSrc = ""; /**@type {string | undefined} */ this.label = undefined; /**@type {string | undefined} */ this.description = undefined; /**@type {string | undefined} */ this.supportPage = undefined; } updated(changedProperties) { super.updated(changedProperties); if (changedProperties.has("disabled")) { this.#updateChildDisabledState(); } if ( changedProperties.has("headingLevel") || changedProperties.has("label") ) { this.toggleAttribute("hasheading", this.hasHeading); } } /** * Returns true when the fieldset should render its label as a heading element. * * @returns {boolean} */ get hasHeading() { return !!this.label && !!HEADING_LEVEL_TEMPLATES[this.headingLevel]; } #updateChildDisabledState() { const formControls = [...this.querySelectorAll("*")].filter( element => "disabled" in element || "parentDisabled" in element ); formControls.forEach(control => { if ("parentDisabled" in control) { control.parentDisabled = this.disabled; } if (this.disabled) { control.setAttribute("disabled", ""); } else { control.removeAttribute("disabled"); } }); } descriptionTemplate() { if (this.description) { return html`
${this.description} ${this.supportPageTemplate()}
`; } return ""; } supportPageTemplate() { if (this.supportPage) { return html``; } return html``; } legendTemplate() { let label = HEADING_LEVEL_TEMPLATES[this.headingLevel]?.(this.label) || this.label; return html`${this.iconTemplate()}${label}`; } iconTemplate() { if (!this.iconSrc) { return ""; } return html`= 1 && this.headingLevel <= 3, })} />`; } render() { return html`
${this.label ? this.legendTemplate() : ""} ${!this.description ? this.supportPageTemplate() : ""} ${this.descriptionTemplate()}
`; } } customElements.define("moz-fieldset", MozFieldset);