@fluentui/web-components 3.0.0-beta.39 → 3.0.0-beta.40
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +13 -2
- package/dist/dts/accordion/accordion.d.ts +35 -12
- package/dist/dts/accordion-item/accordion-item.d.ts +42 -14
- package/dist/dts/accordion-item/accordion-item.options.d.ts +2 -2
- package/dist/dts/accordion-item/index.d.ts +1 -1
- package/dist/dts/checkbox/checkbox.d.ts +98 -48
- package/dist/dts/field/field.d.ts +30 -1
- package/dist/dts/field/field.options.d.ts +2 -0
- package/dist/dts/index.d.ts +1 -1
- package/dist/dts/radio/index.d.ts +1 -1
- package/dist/dts/radio/radio.d.ts +38 -35
- package/dist/dts/radio/radio.options.d.ts +14 -0
- package/dist/dts/radio/radio.styles.d.ts +3 -1
- package/dist/dts/radio/radio.template.d.ts +13 -1
- package/dist/dts/radio-group/radio-group.d.ts +211 -49
- package/dist/dts/radio-group/radio-group.template.d.ts +1 -1
- package/dist/dts/styles/states/index.d.ts +20 -0
- package/dist/dts/switch/switch.d.ts +1 -0
- package/dist/dts/utils/root-active-element.d.ts +1 -0
- package/dist/esm/accordion/accordion.js +46 -85
- package/dist/esm/accordion/accordion.js.map +1 -1
- package/dist/esm/accordion-item/accordion-item.js +63 -19
- package/dist/esm/accordion-item/accordion-item.js.map +1 -1
- package/dist/esm/accordion-item/accordion-item.options.js +1 -1
- package/dist/esm/accordion-item/accordion-item.options.js.map +1 -1
- package/dist/esm/accordion-item/accordion-item.styles.js +41 -63
- package/dist/esm/accordion-item/accordion-item.styles.js.map +1 -1
- package/dist/esm/accordion-item/accordion-item.template.js +24 -43
- package/dist/esm/accordion-item/accordion-item.template.js.map +1 -1
- package/dist/esm/accordion-item/index.js +1 -1
- package/dist/esm/accordion-item/index.js.map +1 -1
- package/dist/esm/checkbox/checkbox.js +146 -97
- package/dist/esm/checkbox/checkbox.js.map +1 -1
- package/dist/esm/checkbox/checkbox.styles.js +1 -6
- package/dist/esm/checkbox/checkbox.styles.js.map +1 -1
- package/dist/esm/checkbox/checkbox.template.js.map +1 -1
- package/dist/esm/field/field.js +91 -29
- package/dist/esm/field/field.js.map +1 -1
- package/dist/esm/field/field.options.js.map +1 -1
- package/dist/esm/field/field.styles.js +31 -16
- package/dist/esm/field/field.styles.js.map +1 -1
- package/dist/esm/field/field.template.js +1 -1
- package/dist/esm/field/field.template.js.map +1 -1
- package/dist/esm/index.js +1 -1
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/radio/radio.js +59 -72
- package/dist/esm/radio/radio.js.map +1 -1
- package/dist/esm/radio/radio.options.js +2 -0
- package/dist/esm/radio/radio.options.js.map +1 -0
- package/dist/esm/radio/radio.styles.js +95 -88
- package/dist/esm/radio/radio.styles.js.map +1 -1
- package/dist/esm/radio/radio.template.js +21 -24
- package/dist/esm/radio/radio.template.js.map +1 -1
- package/dist/esm/radio-group/radio-group.js +416 -313
- package/dist/esm/radio-group/radio-group.js.map +1 -1
- package/dist/esm/radio-group/radio-group.styles.js +26 -32
- package/dist/esm/radio-group/radio-group.styles.js.map +1 -1
- package/dist/esm/radio-group/radio-group.template.js +6 -21
- package/dist/esm/radio-group/radio-group.template.js.map +1 -1
- package/dist/esm/styles/states/index.js +20 -0
- package/dist/esm/styles/states/index.js.map +1 -1
- package/dist/esm/switch/switch.js +4 -0
- package/dist/esm/switch/switch.js.map +1 -1
- package/dist/esm/switch/switch.styles.js +3 -6
- package/dist/esm/switch/switch.styles.js.map +1 -1
- package/dist/esm/switch/switch.template.js.map +1 -1
- package/dist/esm/theme/set-theme.js +3 -6
- package/dist/esm/theme/set-theme.js.map +1 -1
- package/dist/esm/utils/root-active-element.js +9 -0
- package/dist/esm/utils/root-active-element.js.map +1 -0
- package/dist/web-components.d.ts +461 -181
- package/dist/web-components.js +1387 -1233
- package/dist/web-components.min.js +262 -258
- package/package.json +1 -1
- package/dist/dts/radio/radio.form-associated.d.ts +0 -14
- package/dist/esm/radio/radio.form-associated.js +0 -14
- package/dist/esm/radio/radio.form-associated.js.map +0 -1
|
@@ -1,367 +1,470 @@
|
|
|
1
1
|
import { __decorate } from "tslib";
|
|
2
|
-
import { attr, FASTElement, observable } from '@microsoft/fast-element';
|
|
3
|
-
import {
|
|
2
|
+
import { attr, FASTElement, Observable, observable, Updates } from '@microsoft/fast-element';
|
|
3
|
+
import { findLastIndex } from '@microsoft/fast-web-utilities';
|
|
4
4
|
import { Radio } from '../radio/radio.js';
|
|
5
|
-
import { getDirection } from '../utils/
|
|
5
|
+
import { getDirection } from '../utils/direction.js';
|
|
6
|
+
import { getRootActiveElement } from '../utils/root-active-element.js';
|
|
6
7
|
import { RadioGroupOrientation } from './radio-group.options.js';
|
|
7
8
|
/**
|
|
8
|
-
*
|
|
9
|
+
* A Radio Group Custom HTML Element.
|
|
10
|
+
* Implements the {@link https://w3c.github.io/aria/#radiogroup | ARIA `radiogroup` role}.
|
|
11
|
+
*
|
|
9
12
|
* @public
|
|
13
|
+
*
|
|
14
|
+
* @slot - The default slot for the radio group
|
|
10
15
|
*/
|
|
11
16
|
export class RadioGroup extends FASTElement {
|
|
17
|
+
/**
|
|
18
|
+
* Sets the checked state of the nearest enabled radio when the `checkedIndex` changes.
|
|
19
|
+
*
|
|
20
|
+
* @param prev - the previous index
|
|
21
|
+
* @param next - the current index
|
|
22
|
+
* @internal
|
|
23
|
+
*/
|
|
24
|
+
checkedIndexChanged(prev, next) {
|
|
25
|
+
if (!this.enabledRadios) {
|
|
26
|
+
return;
|
|
27
|
+
}
|
|
28
|
+
this.checkRadio(next);
|
|
29
|
+
}
|
|
30
|
+
/**
|
|
31
|
+
* Sets the `disabled` attribute on all child radios when the `disabled` property changes.
|
|
32
|
+
*
|
|
33
|
+
* @param prev - the previous disabled value
|
|
34
|
+
* @param next - the current disabled value
|
|
35
|
+
* @internal
|
|
36
|
+
*/
|
|
37
|
+
disabledChanged(prev, next) {
|
|
38
|
+
var _a;
|
|
39
|
+
if (this.$fastController.isConnected) {
|
|
40
|
+
this.checkedIndex = -1;
|
|
41
|
+
(_a = this.radios) === null || _a === void 0 ? void 0 : _a.forEach(radio => {
|
|
42
|
+
radio.disabled = radio.disabledAttribute || this.disabled;
|
|
43
|
+
});
|
|
44
|
+
this.restrictFocus();
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
/**
|
|
48
|
+
* Sets the matching radio to checked when the value changes. If no radio matches the value, no radio will be checked.
|
|
49
|
+
*
|
|
50
|
+
* @param prev - the previous value
|
|
51
|
+
* @param next - the current value
|
|
52
|
+
*/
|
|
53
|
+
initialValueChanged(prev, next) {
|
|
54
|
+
this.value = next !== null && next !== void 0 ? next : '';
|
|
55
|
+
}
|
|
56
|
+
/**
|
|
57
|
+
* Sets the `name` attribute on all child radios when the `name` property changes.
|
|
58
|
+
*
|
|
59
|
+
* @internal
|
|
60
|
+
*/
|
|
61
|
+
nameChanged(prev, next) {
|
|
62
|
+
var _a;
|
|
63
|
+
if (this.isConnected && next) {
|
|
64
|
+
(_a = this.radios) === null || _a === void 0 ? void 0 : _a.forEach(radio => {
|
|
65
|
+
radio.name = this.name;
|
|
66
|
+
});
|
|
67
|
+
}
|
|
68
|
+
}
|
|
69
|
+
/**
|
|
70
|
+
* Sets the ariaOrientation attribute when the orientation changes.
|
|
71
|
+
*
|
|
72
|
+
* @param prev - the previous orientation
|
|
73
|
+
* @param next - the current orientation
|
|
74
|
+
* @internal
|
|
75
|
+
*/
|
|
76
|
+
orientationChanged(prev, next) {
|
|
77
|
+
var _a;
|
|
78
|
+
this.elementInternals.ariaOrientation = (_a = this.orientation) !== null && _a !== void 0 ? _a : RadioGroupOrientation.horizontal;
|
|
79
|
+
}
|
|
80
|
+
/**
|
|
81
|
+
* Updates the enabled radios collection when properties on the child radios change.
|
|
82
|
+
*
|
|
83
|
+
* @param prev - the previous radios
|
|
84
|
+
* @param next - the current radios
|
|
85
|
+
*/
|
|
86
|
+
radiosChanged(prev, next) {
|
|
87
|
+
const setSize = next === null || next === void 0 ? void 0 : next.length;
|
|
88
|
+
if (!setSize) {
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
if (!this.name && next.every(x => x.name === next[0].name)) {
|
|
92
|
+
this.name = next[0].name;
|
|
93
|
+
}
|
|
94
|
+
const checkedIndex = findLastIndex(this.enabledRadios, x => x.initialChecked);
|
|
95
|
+
next.forEach((radio, index) => {
|
|
96
|
+
var _a;
|
|
97
|
+
radio.ariaPosInSet = `${index + 1}`;
|
|
98
|
+
radio.ariaSetSize = `${setSize}`;
|
|
99
|
+
if (this.initialValue && !this.dirtyState) {
|
|
100
|
+
radio.checked = radio.value === this.initialValue;
|
|
101
|
+
}
|
|
102
|
+
else {
|
|
103
|
+
radio.checked = index === checkedIndex;
|
|
104
|
+
}
|
|
105
|
+
radio.name = (_a = this.name) !== null && _a !== void 0 ? _a : radio.name;
|
|
106
|
+
radio.disabled = this.disabled || radio.disabledAttribute;
|
|
107
|
+
});
|
|
108
|
+
if (!this.dirtyState && this.initialValue) {
|
|
109
|
+
this.value = this.initialValue;
|
|
110
|
+
}
|
|
111
|
+
if (!this.value) {
|
|
112
|
+
// TODO: Switch to standard `Array.findLastIndex` when TypeScript 5 is available
|
|
113
|
+
this.checkedIndex = checkedIndex;
|
|
114
|
+
}
|
|
115
|
+
// prettier-ignore
|
|
116
|
+
const radioIds = next.map(radio => radio.id).join(' ').trim();
|
|
117
|
+
if (radioIds) {
|
|
118
|
+
this.setAttribute('aria-owns', radioIds);
|
|
119
|
+
}
|
|
120
|
+
Updates.enqueue(() => {
|
|
121
|
+
this.restrictFocus();
|
|
122
|
+
});
|
|
123
|
+
}
|
|
124
|
+
/**
|
|
125
|
+
*
|
|
126
|
+
* @param prev - the previous required value
|
|
127
|
+
* @param next - the current required value
|
|
128
|
+
*/
|
|
129
|
+
requiredChanged(prev, next) {
|
|
130
|
+
this.elementInternals.ariaRequired = next ? 'true' : null;
|
|
131
|
+
this.setValidity();
|
|
132
|
+
}
|
|
133
|
+
/**
|
|
134
|
+
* A collection of child radios that are not disabled.
|
|
135
|
+
*
|
|
136
|
+
* @internal
|
|
137
|
+
*/
|
|
138
|
+
get enabledRadios() {
|
|
139
|
+
var _a, _b;
|
|
140
|
+
if (this.disabled) {
|
|
141
|
+
return [];
|
|
142
|
+
}
|
|
143
|
+
return (_b = (_a = this.radios) === null || _a === void 0 ? void 0 : _a.filter(x => !x.disabled)) !== null && _b !== void 0 ? _b : [];
|
|
144
|
+
}
|
|
145
|
+
/**
|
|
146
|
+
* The validation message. Uses the browser's default validation message for native checkboxes if not otherwise
|
|
147
|
+
* specified (e.g., via `setCustomValidity`).
|
|
148
|
+
*
|
|
149
|
+
* @internal
|
|
150
|
+
*/
|
|
151
|
+
get validationMessage() {
|
|
152
|
+
var _a, _b;
|
|
153
|
+
if (this.elementInternals.validationMessage) {
|
|
154
|
+
return this.elementInternals.validationMessage;
|
|
155
|
+
}
|
|
156
|
+
if ((_b = (_a = this.enabledRadios) === null || _a === void 0 ? void 0 : _a[0]) === null || _b === void 0 ? void 0 : _b.validationMessage) {
|
|
157
|
+
return this.enabledRadios[0].validationMessage;
|
|
158
|
+
}
|
|
159
|
+
if (!this._validationFallbackMessage) {
|
|
160
|
+
const validationMessageFallbackControl = document.createElement('input');
|
|
161
|
+
validationMessageFallbackControl.type = 'radio';
|
|
162
|
+
validationMessageFallbackControl.required = true;
|
|
163
|
+
validationMessageFallbackControl.checked = false;
|
|
164
|
+
this._validationFallbackMessage = validationMessageFallbackControl.validationMessage;
|
|
165
|
+
}
|
|
166
|
+
return this._validationFallbackMessage;
|
|
167
|
+
}
|
|
168
|
+
/**
|
|
169
|
+
* The element's validity state.
|
|
170
|
+
*
|
|
171
|
+
* @public
|
|
172
|
+
* @remarks
|
|
173
|
+
* Reflects the {@link https://developer.mozilla.org/docs/Web/API/ElementInternals/validity | `ElementInternals.validity`} property.
|
|
174
|
+
*/
|
|
175
|
+
get validity() {
|
|
176
|
+
return this.elementInternals.validity;
|
|
177
|
+
}
|
|
178
|
+
/**
|
|
179
|
+
* The current value of the checked radio.
|
|
180
|
+
*
|
|
181
|
+
* @public
|
|
182
|
+
*/
|
|
183
|
+
get value() {
|
|
184
|
+
var _a, _b;
|
|
185
|
+
Observable.notify(this, 'value');
|
|
186
|
+
return (_b = (_a = this.enabledRadios.find(x => x.checked)) === null || _a === void 0 ? void 0 : _a.value) !== null && _b !== void 0 ? _b : null;
|
|
187
|
+
}
|
|
188
|
+
set value(next) {
|
|
189
|
+
const index = this.enabledRadios.findIndex(x => x.value === next);
|
|
190
|
+
this.checkedIndex = index;
|
|
191
|
+
if (this.$fastController.isConnected) {
|
|
192
|
+
this.setFormValue(next);
|
|
193
|
+
this.setValidity();
|
|
194
|
+
}
|
|
195
|
+
Observable.track(this, 'value');
|
|
196
|
+
}
|
|
197
|
+
/**
|
|
198
|
+
* Sets the checked state of all radios when any radio emits a `change` event.
|
|
199
|
+
*
|
|
200
|
+
* @param e - the change event
|
|
201
|
+
*/
|
|
202
|
+
changeHandler(e) {
|
|
203
|
+
if (this === e.target) {
|
|
204
|
+
return true;
|
|
205
|
+
}
|
|
206
|
+
this.dirtyState = true;
|
|
207
|
+
const radioIndex = this.enabledRadios.indexOf(e.target);
|
|
208
|
+
this.checkRadio(radioIndex);
|
|
209
|
+
return true;
|
|
210
|
+
}
|
|
211
|
+
/**
|
|
212
|
+
* Checks the radio at the specified index.
|
|
213
|
+
*
|
|
214
|
+
* @param index - the index of the radio to check
|
|
215
|
+
* @internal
|
|
216
|
+
*/
|
|
217
|
+
checkRadio(index = this.checkedIndex) {
|
|
218
|
+
let checkedIndex = this.checkedIndex;
|
|
219
|
+
this.enabledRadios.forEach((item, i) => {
|
|
220
|
+
const shouldCheck = i === index;
|
|
221
|
+
item.checked = shouldCheck;
|
|
222
|
+
if (shouldCheck) {
|
|
223
|
+
checkedIndex = i;
|
|
224
|
+
}
|
|
225
|
+
});
|
|
226
|
+
this.checkedIndex = checkedIndex;
|
|
227
|
+
this.setFormValue(this.value);
|
|
228
|
+
this.setValidity();
|
|
229
|
+
}
|
|
230
|
+
/**
|
|
231
|
+
* Checks the validity of the element and returns the result.
|
|
232
|
+
*
|
|
233
|
+
* @public
|
|
234
|
+
* @remarks
|
|
235
|
+
* Reflects the {@link https://developer.mozilla.org/docs/Web/API/ElementInternals/checkValidity | `HTMLInputElement.checkValidity()`} method.
|
|
236
|
+
*/
|
|
237
|
+
checkValidity() {
|
|
238
|
+
return this.elementInternals.checkValidity();
|
|
239
|
+
}
|
|
240
|
+
/**
|
|
241
|
+
* Handles click events for the radio group.
|
|
242
|
+
*
|
|
243
|
+
* @param e - the click event
|
|
244
|
+
* @internal
|
|
245
|
+
*/
|
|
246
|
+
clickHandler(e) {
|
|
247
|
+
var _a;
|
|
248
|
+
if (this === e.target) {
|
|
249
|
+
(_a = this.enabledRadios[Math.max(0, this.checkedIndex)]) === null || _a === void 0 ? void 0 : _a.focus();
|
|
250
|
+
}
|
|
251
|
+
return true;
|
|
252
|
+
}
|
|
12
253
|
constructor() {
|
|
13
|
-
|
|
254
|
+
var _a;
|
|
255
|
+
super();
|
|
14
256
|
/**
|
|
15
|
-
*
|
|
16
|
-
*
|
|
17
|
-
* @public
|
|
18
|
-
* @remarks
|
|
19
|
-
* HTML Attribute: stacked
|
|
257
|
+
* Indicates that the value has been changed by the user.
|
|
20
258
|
*/
|
|
21
|
-
this.
|
|
259
|
+
this.dirtyState = false;
|
|
22
260
|
/**
|
|
23
|
-
*
|
|
261
|
+
* Disables the radio group and child radios.
|
|
24
262
|
*
|
|
25
263
|
* @public
|
|
26
264
|
* @remarks
|
|
27
|
-
* HTML Attribute:
|
|
265
|
+
* HTML Attribute: `disabled`
|
|
28
266
|
*/
|
|
29
|
-
this.
|
|
30
|
-
this.radioChangeHandler = (e) => {
|
|
31
|
-
const changedRadio = e.target;
|
|
32
|
-
if (changedRadio.checked) {
|
|
33
|
-
this.slottedRadioButtons.forEach((radio) => {
|
|
34
|
-
if (radio instanceof Radio && radio !== changedRadio) {
|
|
35
|
-
radio.checked = false;
|
|
36
|
-
if (!this.isInsideFoundationToolbar) {
|
|
37
|
-
radio.setAttribute('tabindex', '-1');
|
|
38
|
-
}
|
|
39
|
-
}
|
|
40
|
-
});
|
|
41
|
-
this.selectedRadio = changedRadio;
|
|
42
|
-
this.value = changedRadio.value;
|
|
43
|
-
changedRadio.setAttribute('tabindex', '0');
|
|
44
|
-
this.focusedRadio = changedRadio;
|
|
45
|
-
}
|
|
46
|
-
e.stopPropagation();
|
|
47
|
-
};
|
|
48
|
-
this.moveToRadioByIndex = (group, index) => {
|
|
49
|
-
const radio = group[index];
|
|
50
|
-
if (!this.isInsideToolbar) {
|
|
51
|
-
radio.setAttribute('tabindex', '0');
|
|
52
|
-
radio.checked = true;
|
|
53
|
-
this.selectedRadio = radio;
|
|
54
|
-
}
|
|
55
|
-
this.focusedRadio = radio;
|
|
56
|
-
radio.focus();
|
|
57
|
-
};
|
|
58
|
-
this.moveRightOffGroup = () => {
|
|
59
|
-
var _a;
|
|
60
|
-
(_a = this.nextElementSibling) === null || _a === void 0 ? void 0 : _a.focus();
|
|
61
|
-
};
|
|
62
|
-
this.moveLeftOffGroup = () => {
|
|
63
|
-
var _a;
|
|
64
|
-
(_a = this.previousElementSibling) === null || _a === void 0 ? void 0 : _a.focus();
|
|
65
|
-
};
|
|
66
|
-
/**
|
|
67
|
-
* @internal
|
|
68
|
-
*/
|
|
69
|
-
this.focusOutHandler = (e) => {
|
|
70
|
-
const group = this.slottedRadioButtons;
|
|
71
|
-
const radio = e.target;
|
|
72
|
-
const index = radio !== null ? group.indexOf(radio) : 0;
|
|
73
|
-
const focusedIndex = this.focusedRadio ? group.indexOf(this.focusedRadio) : -1;
|
|
74
|
-
if ((focusedIndex === 0 && index === focusedIndex) ||
|
|
75
|
-
(focusedIndex === group.length - 1 && focusedIndex === index)) {
|
|
76
|
-
if (!this.selectedRadio) {
|
|
77
|
-
this.focusedRadio = group[0];
|
|
78
|
-
this.focusedRadio.setAttribute('tabindex', '0');
|
|
79
|
-
group.forEach((nextRadio) => {
|
|
80
|
-
if (radio instanceof Radio && nextRadio !== this.focusedRadio) {
|
|
81
|
-
nextRadio.setAttribute('tabindex', '-1');
|
|
82
|
-
}
|
|
83
|
-
});
|
|
84
|
-
}
|
|
85
|
-
else {
|
|
86
|
-
this.focusedRadio = this.selectedRadio;
|
|
87
|
-
if (!this.isInsideFoundationToolbar) {
|
|
88
|
-
this.selectedRadio.setAttribute('tabindex', '0');
|
|
89
|
-
group.forEach((nextRadio) => {
|
|
90
|
-
if (nextRadio !== this.selectedRadio) {
|
|
91
|
-
nextRadio.setAttribute('tabindex', '-1');
|
|
92
|
-
}
|
|
93
|
-
});
|
|
94
|
-
}
|
|
95
|
-
}
|
|
96
|
-
}
|
|
97
|
-
return true;
|
|
98
|
-
};
|
|
99
|
-
/**
|
|
100
|
-
* @internal
|
|
101
|
-
*/
|
|
102
|
-
this.handleDisabledClick = (e) => {
|
|
103
|
-
// prevent focus events on items from the click handler when disabled
|
|
104
|
-
if (this.disabled) {
|
|
105
|
-
e.preventDefault();
|
|
106
|
-
return;
|
|
107
|
-
}
|
|
108
|
-
return true;
|
|
109
|
-
};
|
|
267
|
+
this.disabled = false;
|
|
110
268
|
/**
|
|
269
|
+
* The internal {@link https://developer.mozilla.org/docs/Web/API/ElementInternals | `ElementInternals`} instance for the component.
|
|
270
|
+
*
|
|
111
271
|
* @internal
|
|
112
272
|
*/
|
|
113
|
-
this.
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
this.
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
273
|
+
this.elementInternals = this.attachInternals();
|
|
274
|
+
this.elementInternals.role = 'radiogroup';
|
|
275
|
+
this.elementInternals.ariaOrientation = (_a = this.orientation) !== null && _a !== void 0 ? _a : RadioGroupOrientation.horizontal;
|
|
276
|
+
}
|
|
277
|
+
/**
|
|
278
|
+
* Focuses the checked radio or the first enabled radio.
|
|
279
|
+
*
|
|
280
|
+
* @internal
|
|
281
|
+
*/
|
|
282
|
+
focus() {
|
|
283
|
+
var _a;
|
|
284
|
+
(_a = this.enabledRadios[Math.max(0, this.checkedIndex)]) === null || _a === void 0 ? void 0 : _a.focus();
|
|
285
|
+
}
|
|
286
|
+
/**
|
|
287
|
+
* Enables tabbing through the radio group when the group receives focus.
|
|
288
|
+
*
|
|
289
|
+
* @param e - the focus event
|
|
290
|
+
* @internal
|
|
291
|
+
*/
|
|
292
|
+
focusinHandler(e) {
|
|
293
|
+
if (!this.disabled) {
|
|
294
|
+
this.enabledRadios.forEach(radio => {
|
|
295
|
+
radio.tabIndex = 0;
|
|
296
|
+
});
|
|
297
|
+
}
|
|
298
|
+
return true;
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Sets the tabindex of the radios based on the checked state when the radio group loses focus.
|
|
302
|
+
*
|
|
303
|
+
* @param e - the focusout event
|
|
304
|
+
* @internal
|
|
305
|
+
*/
|
|
306
|
+
focusoutHandler(e) {
|
|
307
|
+
var _a, _b;
|
|
308
|
+
if (((_a = this.radios) === null || _a === void 0 ? void 0 : _a.includes(e.relatedTarget)) && ((_b = this.radios) === null || _b === void 0 ? void 0 : _b.some(x => x.checked))) {
|
|
309
|
+
this.restrictFocus();
|
|
310
|
+
}
|
|
311
|
+
return true;
|
|
312
|
+
}
|
|
313
|
+
formResetCallback() {
|
|
314
|
+
this.dirtyState = false;
|
|
315
|
+
this.checkedIndex = -1;
|
|
316
|
+
this.setFormValue(this.value);
|
|
317
|
+
this.setValidity();
|
|
318
|
+
}
|
|
319
|
+
getEnabledIndexInBounds(index, upperBound = this.enabledRadios.length) {
|
|
320
|
+
if (upperBound === 0) {
|
|
321
|
+
return -1;
|
|
322
|
+
}
|
|
323
|
+
return (index + upperBound) % upperBound;
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* Handles keydown events for the radio group.
|
|
327
|
+
*
|
|
328
|
+
* @param e - the keyboard event
|
|
329
|
+
* @internal
|
|
330
|
+
*/
|
|
331
|
+
keydownHandler(e) {
|
|
332
|
+
var _a, _b;
|
|
333
|
+
const isRtl = getDirection(this) === 'rtl';
|
|
334
|
+
const checkedIndex = (_a = this.enabledRadios.findIndex(x => x === getRootActiveElement(this))) !== null && _a !== void 0 ? _a : this.checkedIndex;
|
|
335
|
+
let increment = 0;
|
|
336
|
+
switch (e.key) {
|
|
337
|
+
case 'ArrowLeft': {
|
|
338
|
+
increment = isRtl ? 1 : -1;
|
|
339
|
+
break;
|
|
151
340
|
}
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
if (!group[index].disabled) {
|
|
156
|
-
this.moveToRadioByIndex(group, index);
|
|
157
|
-
break;
|
|
158
|
-
}
|
|
159
|
-
else if (this.focusedRadio && index === group.indexOf(this.focusedRadio)) {
|
|
160
|
-
break;
|
|
161
|
-
}
|
|
162
|
-
else if (index + 1 >= group.length) {
|
|
163
|
-
if (this.isInsideToolbar) {
|
|
164
|
-
break;
|
|
165
|
-
}
|
|
166
|
-
else {
|
|
167
|
-
index = 0;
|
|
168
|
-
}
|
|
169
|
-
}
|
|
170
|
-
else {
|
|
171
|
-
index += 1;
|
|
172
|
-
}
|
|
341
|
+
case 'ArrowUp': {
|
|
342
|
+
increment = -1;
|
|
343
|
+
break;
|
|
173
344
|
}
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
let index = 0;
|
|
178
|
-
index = this.focusedRadio ? group.indexOf(this.focusedRadio) - 1 : 0;
|
|
179
|
-
index = index < 0 ? group.length - 1 : index;
|
|
180
|
-
if (this.shouldMoveOffGroupToTheLeft(group, e.key)) {
|
|
181
|
-
this.moveLeftOffGroup();
|
|
182
|
-
return;
|
|
345
|
+
case 'ArrowRight': {
|
|
346
|
+
increment = isRtl ? -1 : 1;
|
|
347
|
+
break;
|
|
183
348
|
}
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
this.moveToRadioByIndex(group, index);
|
|
188
|
-
break;
|
|
189
|
-
}
|
|
190
|
-
else if (this.focusedRadio && index === group.indexOf(this.focusedRadio)) {
|
|
191
|
-
break;
|
|
192
|
-
}
|
|
193
|
-
else if (index - 1 < 0) {
|
|
194
|
-
index = group.length - 1;
|
|
195
|
-
}
|
|
196
|
-
else {
|
|
197
|
-
index -= 1;
|
|
198
|
-
}
|
|
349
|
+
case 'ArrowDown': {
|
|
350
|
+
increment = 1;
|
|
351
|
+
break;
|
|
199
352
|
}
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
* navigation is different when there is an ancestor with role='toolbar'
|
|
204
|
-
*
|
|
205
|
-
* @internal
|
|
206
|
-
*/
|
|
207
|
-
this.keydownHandler = (e) => {
|
|
208
|
-
const key = e.key;
|
|
209
|
-
if (key in ArrowKeys && (this.isInsideFoundationToolbar || this.disabled)) {
|
|
210
|
-
return true;
|
|
353
|
+
case 'Tab': {
|
|
354
|
+
this.restrictFocus();
|
|
355
|
+
break;
|
|
211
356
|
}
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
break;
|
|
216
|
-
}
|
|
217
|
-
case keyArrowRight:
|
|
218
|
-
case keyArrowDown: {
|
|
219
|
-
if (this.direction === Direction.ltr) {
|
|
220
|
-
this.moveRight(e);
|
|
221
|
-
}
|
|
222
|
-
else {
|
|
223
|
-
this.moveLeft(e);
|
|
224
|
-
}
|
|
225
|
-
break;
|
|
226
|
-
}
|
|
227
|
-
case keyArrowLeft:
|
|
228
|
-
case keyArrowUp: {
|
|
229
|
-
if (this.direction === Direction.ltr) {
|
|
230
|
-
this.moveLeft(e);
|
|
231
|
-
}
|
|
232
|
-
else {
|
|
233
|
-
this.moveRight(e);
|
|
234
|
-
}
|
|
235
|
-
break;
|
|
236
|
-
}
|
|
237
|
-
default: {
|
|
238
|
-
return true;
|
|
239
|
-
}
|
|
357
|
+
case ' ': {
|
|
358
|
+
this.checkRadio();
|
|
359
|
+
break;
|
|
240
360
|
}
|
|
241
|
-
};
|
|
242
|
-
}
|
|
243
|
-
nameChanged() {
|
|
244
|
-
if (this.slottedRadioButtons) {
|
|
245
|
-
this.slottedRadioButtons.forEach((radio) => {
|
|
246
|
-
radio.setAttribute('name', this.name);
|
|
247
|
-
});
|
|
248
361
|
}
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
if (this.slottedRadioButtons) {
|
|
252
|
-
this.slottedRadioButtons.forEach((radio) => {
|
|
253
|
-
if (radio instanceof Radio) {
|
|
254
|
-
if (radio.value === this.value) {
|
|
255
|
-
radio.checked = true;
|
|
256
|
-
this.selectedRadio = radio;
|
|
257
|
-
}
|
|
258
|
-
}
|
|
259
|
-
});
|
|
362
|
+
if (!increment) {
|
|
363
|
+
return true;
|
|
260
364
|
}
|
|
261
|
-
|
|
365
|
+
const nextIndex = checkedIndex + increment;
|
|
366
|
+
this.checkedIndex = this.getEnabledIndexInBounds(nextIndex);
|
|
367
|
+
(_b = this.enabledRadios[this.checkedIndex]) === null || _b === void 0 ? void 0 : _b.focus();
|
|
262
368
|
}
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
369
|
+
/**
|
|
370
|
+
*
|
|
371
|
+
* @param e - the disabled event
|
|
372
|
+
*/
|
|
373
|
+
disabledRadioHandler(e) {
|
|
374
|
+
if (e.detail === true && e.target.checked) {
|
|
375
|
+
this.checkedIndex = -1;
|
|
266
376
|
}
|
|
267
377
|
}
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
378
|
+
/**
|
|
379
|
+
* Reports the validity of the element.
|
|
380
|
+
*
|
|
381
|
+
* @public
|
|
382
|
+
* @remarks
|
|
383
|
+
* Reflects the {@link https://developer.mozilla.org/docs/Web/API/ElementInternals/reportValidity | `HTMLInputElement.reportValidity()`} method.
|
|
384
|
+
*/
|
|
385
|
+
reportValidity() {
|
|
386
|
+
return this.elementInternals.reportValidity();
|
|
274
387
|
}
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
388
|
+
/**
|
|
389
|
+
* Resets the `tabIndex` for all child radios when the radio group loses focus.
|
|
390
|
+
*
|
|
391
|
+
* @internal
|
|
392
|
+
*/
|
|
393
|
+
restrictFocus() {
|
|
394
|
+
let activeIndex = Math.max(this.checkedIndex, 0);
|
|
395
|
+
const focusedRadioIndex = this.enabledRadios.indexOf(getRootActiveElement(this));
|
|
396
|
+
if (focusedRadioIndex !== -1) {
|
|
397
|
+
activeIndex = focusedRadioIndex;
|
|
398
|
+
}
|
|
399
|
+
activeIndex = this.getEnabledIndexInBounds(activeIndex);
|
|
400
|
+
this.enabledRadios.forEach((item, index) => {
|
|
401
|
+
item.tabIndex = index === activeIndex ? 0 : -1;
|
|
402
|
+
});
|
|
278
403
|
}
|
|
279
404
|
/**
|
|
405
|
+
* Reflects the {@link https://developer.mozilla.org/docs/Web/API/ElementInternals/setFormValue | `ElementInternals.setFormValue()`} method.
|
|
406
|
+
*
|
|
280
407
|
* @internal
|
|
281
408
|
*/
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
this.direction = getDirection(this);
|
|
285
|
-
this.setupRadioButtons();
|
|
409
|
+
setFormValue(value, state) {
|
|
410
|
+
this.elementInternals.setFormValue(value, value !== null && value !== void 0 ? value : state);
|
|
286
411
|
}
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
412
|
+
/**
|
|
413
|
+
* Sets the validity of the element.
|
|
414
|
+
*
|
|
415
|
+
* @param flags - Validity flags to set.
|
|
416
|
+
* @param message - Optional message to supply. If not provided, the element's `validationMessage` will be used.
|
|
417
|
+
* @param anchor - Optional anchor to use for the validation message.
|
|
418
|
+
*
|
|
419
|
+
* @internal
|
|
420
|
+
*/
|
|
421
|
+
setValidity(flags, message, anchor) {
|
|
422
|
+
if (this.$fastController.isConnected) {
|
|
423
|
+
if (this.disabled || !this.required) {
|
|
424
|
+
this.elementInternals.setValidity({});
|
|
425
|
+
return;
|
|
291
426
|
}
|
|
292
|
-
|
|
293
|
-
}
|
|
294
|
-
setupRadioButtons() {
|
|
295
|
-
const checkedRadios = this.slottedRadioButtons.filter((radio) => {
|
|
296
|
-
return radio.hasAttribute('checked');
|
|
297
|
-
});
|
|
298
|
-
const numberOfCheckedRadios = checkedRadios ? checkedRadios.length : 0;
|
|
299
|
-
if (numberOfCheckedRadios > 1) {
|
|
300
|
-
const lastCheckedRadio = checkedRadios[numberOfCheckedRadios - 1];
|
|
301
|
-
lastCheckedRadio.checked = true;
|
|
427
|
+
this.elementInternals.setValidity({ valueMissing: this.required && !this.value, ...flags }, message !== null && message !== void 0 ? message : this.validationMessage, anchor !== null && anchor !== void 0 ? anchor : this.enabledRadios[0]);
|
|
302
428
|
}
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
radio.setAttribute('tabindex', '0');
|
|
314
|
-
foundMatchingVal = true;
|
|
315
|
-
}
|
|
316
|
-
else {
|
|
317
|
-
if (!this.isInsideFoundationToolbar) {
|
|
318
|
-
radio.setAttribute('tabindex', '-1');
|
|
319
|
-
}
|
|
320
|
-
radio.checked = false;
|
|
321
|
-
}
|
|
322
|
-
radio.addEventListener('change', this.radioChangeHandler);
|
|
323
|
-
}
|
|
429
|
+
}
|
|
430
|
+
/**
|
|
431
|
+
* Updates the collection of child radios when the slot changes.
|
|
432
|
+
*
|
|
433
|
+
* @param e - the slot change event
|
|
434
|
+
* @internal
|
|
435
|
+
*/
|
|
436
|
+
slotchangeHandler(e) {
|
|
437
|
+
Updates.enqueue(() => {
|
|
438
|
+
this.radios = [...this.querySelectorAll('*')].filter(x => x instanceof Radio);
|
|
324
439
|
});
|
|
325
|
-
if (this.value === undefined && this.slottedRadioButtons.length > 0) {
|
|
326
|
-
const checkedRadios = this.slottedRadioButtons.filter((radio) => {
|
|
327
|
-
return radio.hasAttribute('checked');
|
|
328
|
-
});
|
|
329
|
-
const numberOfCheckedRadios = checkedRadios !== null ? checkedRadios.length : 0;
|
|
330
|
-
if (numberOfCheckedRadios > 0 && !foundMatchingVal) {
|
|
331
|
-
const lastCheckedRadio = checkedRadios[numberOfCheckedRadios - 1];
|
|
332
|
-
lastCheckedRadio.checked = true;
|
|
333
|
-
this.focusedRadio = lastCheckedRadio;
|
|
334
|
-
lastCheckedRadio.setAttribute('tabindex', '0');
|
|
335
|
-
}
|
|
336
|
-
else {
|
|
337
|
-
this.slottedRadioButtons[0].setAttribute('tabindex', '0');
|
|
338
|
-
this.focusedRadio = this.slottedRadioButtons[0];
|
|
339
|
-
}
|
|
340
|
-
}
|
|
341
440
|
}
|
|
342
441
|
}
|
|
442
|
+
/**
|
|
443
|
+
* The form-associated flag.
|
|
444
|
+
* @see {@link https://html.spec.whatwg.org/multipage/custom-elements.html#custom-elements-face-example | Form-associated custom elements}
|
|
445
|
+
*
|
|
446
|
+
* @public
|
|
447
|
+
*/
|
|
448
|
+
RadioGroup.formAssociated = true;
|
|
343
449
|
__decorate([
|
|
344
|
-
|
|
345
|
-
], RadioGroup.prototype, "
|
|
346
|
-
__decorate([
|
|
347
|
-
attr({ attribute: 'readonly', mode: 'boolean' })
|
|
348
|
-
], RadioGroup.prototype, "readOnly", void 0);
|
|
450
|
+
observable
|
|
451
|
+
], RadioGroup.prototype, "checkedIndex", void 0);
|
|
349
452
|
__decorate([
|
|
350
453
|
attr({ attribute: 'disabled', mode: 'boolean' })
|
|
351
454
|
], RadioGroup.prototype, "disabled", void 0);
|
|
352
455
|
__decorate([
|
|
353
|
-
attr
|
|
354
|
-
], RadioGroup.prototype, "
|
|
456
|
+
attr({ attribute: 'value', mode: 'fromView' })
|
|
457
|
+
], RadioGroup.prototype, "initialValue", void 0);
|
|
355
458
|
__decorate([
|
|
356
459
|
attr
|
|
357
|
-
], RadioGroup.prototype, "
|
|
460
|
+
], RadioGroup.prototype, "name", void 0);
|
|
358
461
|
__decorate([
|
|
359
462
|
attr
|
|
360
463
|
], RadioGroup.prototype, "orientation", void 0);
|
|
361
464
|
__decorate([
|
|
362
465
|
observable
|
|
363
|
-
], RadioGroup.prototype, "
|
|
466
|
+
], RadioGroup.prototype, "radios", void 0);
|
|
364
467
|
__decorate([
|
|
365
|
-
|
|
366
|
-
], RadioGroup.prototype, "
|
|
468
|
+
attr({ mode: 'boolean' })
|
|
469
|
+
], RadioGroup.prototype, "required", void 0);
|
|
367
470
|
//# sourceMappingURL=radio-group.js.map
|