@esri/calcite-components
Version:
Web Components for Esri's Calcite Design System.
95 lines (94 loc) • 5.53 kB
JavaScript
/*! All material copyright ESRI, All Rights Reserved, unless otherwise specified.
See https://github.com/Esri/calcite-design-system/blob/dev/LICENSE.md for details.
v3.2.1 */
import { c as customElement } from "../../chunks/runtime.js";
import { html } from "lit";
import { LitElement, createEvent, stringOrBoolean, safeClassMap } from "@arcgis/lumina";
import { c as createObserver } from "../../chunks/observers.js";
import { c as componentFocusable } from "../../chunks/component.js";
import { V as Validation } from "../../chunks/Validation.js";
import { h as focusFirstTabbable } from "../../chunks/dom.js";
import { css } from "@lit/reactive-element/css-tag.js";
const CSS = {
itemWrapper: "item-wrapper"
};
const IDS = {
validationMessage: "radioButtonGroupValidationMessage"
};
const styles = css`:host{display:flex;flex-direction:column}:host>.item-wrapper{display:flex;max-inline-size:100vw}:host([layout=horizontal])>.item-wrapper{flex-direction:row;flex-wrap:wrap}:host([layout=horizontal][scale=s])>.item-wrapper{column-gap:var(--calcite-radio-button-group-gap, var(--calcite-spacing-lg))}:host([layout=horizontal][scale=m])>.item-wrapper{column-gap:var(--calcite-radio-button-group-gap, var(--calcite-spacing-xl))}:host([layout=horizontal][scale=l])>.item-wrapper{column-gap:var(--calcite-radio-button-group-gap, var(--calcite-spacing-xxl))}:host([layout=vertical])>.item-wrapper{flex-direction:column;inline-size:fit-content}:host([scale=s]) calcite-input-message{--calcite-input-message-spacing: var( --calcite-radio-button-input-message-spacing, calc(var(--calcite-spacing-xxs) * -1) )}:host([scale=m]) calcite-input-message{--calcite-input-message-spacing: var( --calcite-radio-button-input-message-spacing, calc(var(--calcite-spacing-sm) * -1) )}:host([scale=l]) calcite-input-message{--calcite-input-message-spacing: var( --calcite-radio-button-input-message-spacing, calc(var(--calcite-spacing-md) * -1) )}.validation-container{display:flex;flex-direction:column;align-items:flex-start;align-self:stretch}:host([scale=m]) .validation-container,:host([scale=l]) .validation-container{padding-block-start:.5rem}:host([scale=s]) .validation-container{padding-block-start:.25rem}:host([hidden]){display:none}[hidden]{display:none}`;
class RadioButtonGroup extends LitElement {
constructor() {
super();
this.mutationObserver = createObserver("mutation", () => this.passPropsToRadioButtons());
this.radioButtons = [];
this.disabled = false;
this.layout = "horizontal";
this.required = false;
this.scale = "m";
this.selectedItem = null;
this.status = "idle";
this.calciteRadioButtonGroupChange = createEvent({ cancelable: false });
this.listen("calciteRadioButtonChange", this.radioButtonChangeHandler);
}
static {
this.properties = { radioButtons: [16, {}, { state: true }], disabled: [7, {}, { reflect: true, type: Boolean }], layout: [3, {}, { reflect: true }], name: [3, {}, { reflect: true }], required: [7, {}, { reflect: true, type: Boolean }], scale: [3, {}, { reflect: true }], selectedItem: [0, {}, { attribute: false }], status: [3, {}, { reflect: true }], validationIcon: [3, { converter: stringOrBoolean }, { reflect: true }], validationMessage: 1 };
}
static {
this.styles = styles;
}
async setFocus() {
await componentFocusable(this);
if (this.selectedItem && !this.selectedItem.disabled) {
focusFirstTabbable(this.selectedItem);
}
if (this.radioButtons.length > 0) {
focusFirstTabbable(this.getFocusableRadioButton());
}
}
connectedCallback() {
super.connectedCallback();
this.passPropsToRadioButtons();
this.mutationObserver?.observe(this.el, { childList: true, subtree: true });
}
willUpdate(changes) {
if (changes.has("disabled") && (this.hasUpdated || this.disabled !== false) || changes.has("layout") && (this.hasUpdated || this.layout !== "horizontal") || changes.has("scale") && (this.hasUpdated || this.scale !== "m")) {
this.passPropsToRadioButtons();
}
}
loaded() {
this.passPropsToRadioButtons();
}
disconnectedCallback() {
super.disconnectedCallback();
this.mutationObserver?.disconnect();
}
passPropsToRadioButtons() {
this.radioButtons = Array.from(this.el.querySelectorAll("calcite-radio-button"));
this.selectedItem = Array.from(this.radioButtons).reverse().find((radioButton) => radioButton.checked) || null;
if (this.radioButtons.length > 0) {
this.radioButtons.forEach((radioButton) => {
if (this.hasUpdated) {
radioButton.disabled = this.disabled || radioButton.disabled;
}
radioButton.name = this.name;
radioButton.required = this.required;
radioButton.scale = this.scale;
});
}
}
getFocusableRadioButton() {
return this.radioButtons.find((radiobutton) => !radiobutton.disabled) ?? null;
}
radioButtonChangeHandler(event) {
this.selectedItem = event.target;
this.calciteRadioButtonGroupChange.emit();
}
render() {
this.el.role = "radiogroup";
return html`<div aria-errormessage=${IDS.validationMessage} .ariaInvalid=${this.status === "invalid"} class=${safeClassMap(CSS.itemWrapper)}><slot></slot></div>${this.validationMessage && this.status === "invalid" ? Validation({ icon: this.validationIcon, id: IDS.validationMessage, message: this.validationMessage, scale: this.scale, status: this.status }) : null}`;
}
}
customElement("calcite-radio-button-group", RadioButtonGroup);
export {
RadioButtonGroup
};