131 lines
4.6 KiB
JavaScript
Executable file
131 lines
4.6 KiB
JavaScript
Executable file
import { createEvent, h, Host, proxyCustomElement } from '@stencil/core/internal/client';
|
|
import { b as getIonMode } from './ionic-global.js';
|
|
|
|
const RadioGroup = class extends HTMLElement {
|
|
constructor() {
|
|
super();
|
|
this.__registerHost();
|
|
this.ionChange = createEvent(this, "ionChange", 7);
|
|
this.inputId = `ion-rg-${radioGroupIds++}`;
|
|
this.labelId = `${this.inputId}-lbl`;
|
|
/**
|
|
* If `true`, the radios can be deselected.
|
|
*/
|
|
this.allowEmptySelection = false;
|
|
/**
|
|
* The name of the control, which is submitted with the form data.
|
|
*/
|
|
this.name = this.inputId;
|
|
this.setRadioTabindex = (value) => {
|
|
const radios = this.getRadios();
|
|
// Get the first radio that is not disabled and the checked one
|
|
const first = radios.find(radio => !radio.disabled);
|
|
const checked = radios.find(radio => (radio.value === value && !radio.disabled));
|
|
if (!first && !checked) {
|
|
return;
|
|
}
|
|
// If an enabled checked radio exists, set it to be the focusable radio
|
|
// otherwise we default to focus the first radio
|
|
const focusable = checked || first;
|
|
for (const radio of radios) {
|
|
const tabindex = radio === focusable ? 0 : -1;
|
|
radio.setButtonTabindex(tabindex);
|
|
}
|
|
};
|
|
this.onClick = (ev) => {
|
|
ev.preventDefault();
|
|
const selectedRadio = ev.target && ev.target.closest('ion-radio');
|
|
if (selectedRadio) {
|
|
const currentValue = this.value;
|
|
const newValue = selectedRadio.value;
|
|
if (newValue !== currentValue) {
|
|
this.value = newValue;
|
|
}
|
|
else if (this.allowEmptySelection) {
|
|
this.value = undefined;
|
|
}
|
|
}
|
|
};
|
|
}
|
|
valueChanged(value) {
|
|
this.setRadioTabindex(value);
|
|
this.ionChange.emit({ value });
|
|
}
|
|
componentDidLoad() {
|
|
this.setRadioTabindex(this.value);
|
|
}
|
|
async connectedCallback() {
|
|
// Get the list header if it exists and set the id
|
|
// this is used to set aria-labelledby
|
|
const header = this.el.querySelector('ion-list-header') || this.el.querySelector('ion-item-divider');
|
|
if (header) {
|
|
const label = this.label = header.querySelector('ion-label');
|
|
if (label) {
|
|
this.labelId = label.id = this.name + '-lbl';
|
|
}
|
|
}
|
|
}
|
|
getRadios() {
|
|
return Array.from(this.el.querySelectorAll('ion-radio'));
|
|
}
|
|
onKeydown(ev) {
|
|
const inSelectPopover = !!this.el.closest('ion-select-popover');
|
|
if (ev.target && !this.el.contains(ev.target)) {
|
|
return;
|
|
}
|
|
// Get all radios inside of the radio group and then
|
|
// filter out disabled radios since we need to skip those
|
|
const radios = this.getRadios().filter(radio => !radio.disabled);
|
|
// Only move the radio if the current focus is in the radio group
|
|
if (ev.target && radios.includes(ev.target)) {
|
|
const index = radios.findIndex(radio => radio === ev.target);
|
|
const current = radios[index];
|
|
let next;
|
|
// If hitting arrow down or arrow right, move to the next radio
|
|
// If we're on the last radio, move to the first radio
|
|
if (['ArrowDown', 'ArrowRight'].includes(ev.code)) {
|
|
next = (index === radios.length - 1)
|
|
? radios[0]
|
|
: radios[index + 1];
|
|
}
|
|
// If hitting arrow up or arrow left, move to the previous radio
|
|
// If we're on the first radio, move to the last radio
|
|
if (['ArrowUp', 'ArrowLeft'].includes(ev.code)) {
|
|
next = (index === 0)
|
|
? radios[radios.length - 1]
|
|
: radios[index - 1];
|
|
}
|
|
if (next && radios.includes(next)) {
|
|
next.setFocus(ev);
|
|
if (!inSelectPopover) {
|
|
this.value = next.value;
|
|
}
|
|
}
|
|
// Update the radio group value when a user presses the
|
|
// space bar on top of a selected radio
|
|
if (['Space'].includes(ev.code)) {
|
|
this.value = (this.allowEmptySelection && this.value !== undefined)
|
|
? undefined
|
|
: current.value;
|
|
// Prevent browsers from jumping
|
|
// to the bottom of the screen
|
|
ev.preventDefault();
|
|
}
|
|
}
|
|
}
|
|
render() {
|
|
const { label, labelId } = this;
|
|
const mode = getIonMode(this);
|
|
return (h(Host, { role: "radiogroup", "aria-labelledby": label ? labelId : null, onClick: this.onClick, class: mode }));
|
|
}
|
|
get el() { return this; }
|
|
static get watchers() { return {
|
|
"value": ["valueChanged"]
|
|
}; }
|
|
};
|
|
let radioGroupIds = 0;
|
|
|
|
const IonRadioGroup = /*@__PURE__*/proxyCustomElement(RadioGroup, [0,"ion-radio-group",{"allowEmptySelection":[4,"allow-empty-selection"],"name":[1],"value":[1032]},[[4,"keydown","onKeydown"]]]);
|
|
|
|
export { IonRadioGroup };
|