@politiet/sheriff-web-components 2.12.0 → 2.13.1

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.
Files changed (57) hide show
  1. package/custom-elements.json +224 -8
  2. package/dist/frameworks/vue.d.ts +79 -30
  3. package/dist/frameworks/vue.d.ts.map +1 -1
  4. package/dist/mixins/sds-dialog-target-mixin.d.ts.map +1 -1
  5. package/dist/mixins/sds-dialog-target-mixin.js +10 -0
  6. package/dist/mixins/sds-dialog-target-mixin.js.map +1 -1
  7. package/dist/sds-alert/sds-alert.component.js +3 -3
  8. package/dist/sds-alert/sds-alert.component.js.map +1 -1
  9. package/dist/sds-alert/sds-alert.styles.d.ts.map +1 -1
  10. package/dist/sds-alert/sds-alert.styles.js +0 -6
  11. package/dist/sds-alert/sds-alert.styles.js.map +1 -1
  12. package/dist/sds-button/sds-button.component.d.ts +1 -0
  13. package/dist/sds-button/sds-button.component.d.ts.map +1 -1
  14. package/dist/sds-button/sds-button.component.js.map +1 -1
  15. package/dist/sds-button/sds-button.styles.d.ts.map +1 -1
  16. package/dist/sds-button/sds-button.styles.js +7 -2
  17. package/dist/sds-button/sds-button.styles.js.map +1 -1
  18. package/dist/sds-details/sds-details.styles.d.ts.map +1 -1
  19. package/dist/sds-details/sds-details.styles.js +4 -2
  20. package/dist/sds-details/sds-details.styles.js.map +1 -1
  21. package/dist/sds-dialog/sds-dialog.styles.d.ts.map +1 -1
  22. package/dist/sds-dialog/sds-dialog.styles.js +2 -0
  23. package/dist/sds-dialog/sds-dialog.styles.js.map +1 -1
  24. package/dist/sds-icon/sds-icon-loader.d.ts +1 -0
  25. package/dist/sds-icon/sds-icon-loader.d.ts.map +1 -1
  26. package/dist/sds-icon/sds-icon-loader.js +21 -14
  27. package/dist/sds-icon/sds-icon-loader.js.map +1 -1
  28. package/dist/sds-radio/sds-radio.d.ts +53 -1
  29. package/dist/sds-radio/sds-radio.d.ts.map +1 -1
  30. package/dist/sds-radio/sds-radio.js +218 -41
  31. package/dist/sds-radio/sds-radio.js.map +1 -1
  32. package/dist/sds-radio/sds-radio.styles.js +36 -36
  33. package/dist/sds-radio/sds-radio.styles.js.map +1 -1
  34. package/dist/sds-radio-group/sds-radio-group.d.ts +4 -2
  35. package/dist/sds-radio-group/sds-radio-group.d.ts.map +1 -1
  36. package/dist/sds-radio-group/sds-radio-group.js +10 -3
  37. package/dist/sds-radio-group/sds-radio-group.js.map +1 -1
  38. package/dist/sds-text/sds-text.component.d.ts +2 -0
  39. package/dist/sds-text/sds-text.component.d.ts.map +1 -1
  40. package/dist/sds-text/sds-text.component.js +4 -0
  41. package/dist/sds-text/sds-text.component.js.map +1 -1
  42. package/dist/sds-text/sds-text.styles.d.ts.map +1 -1
  43. package/dist/sds-text/sds-text.styles.js +4 -0
  44. package/dist/sds-text/sds-text.styles.js.map +1 -1
  45. package/dist/sds-textarea/sds-textarea.styles.d.ts.map +1 -1
  46. package/dist/sds-textarea/sds-textarea.styles.js +2 -0
  47. package/dist/sds-textarea/sds-textarea.styles.js.map +1 -1
  48. package/dist/shared/assets/positioning.js +1 -1
  49. package/dist/sheriff-web-components.js +206 -194
  50. package/dist/skill/SKILL.md +127 -41
  51. package/dist/skill/references/components.md +247 -35
  52. package/dist/skill/references/react-wrappers.md +34 -9
  53. package/dist/version.d.ts +1 -1
  54. package/dist/version.js +1 -1
  55. package/dist/version.js.map +1 -1
  56. package/package.json +78 -36
  57. package/web-types.json +163 -45
@@ -4,7 +4,8 @@ var __decorate = (this && this.__decorate) || function (decorators, target, key,
4
4
  else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
5
  return c > 3 && r && Object.defineProperty(target, key, r), r;
6
6
  };
7
- import { html, nothing } from 'lit';
7
+ var SDSRadio_1;
8
+ import { LitElement, html, nothing } from 'lit';
8
9
  import { SDSElement } from '../utils/sds-element';
9
10
  import { property, query, state } from 'lit/decorators.js';
10
11
  import { ifDefined } from 'lit/directives/if-defined.js';
@@ -12,7 +13,7 @@ import { classMap } from 'lit/directives/class-map.js';
12
13
  import { guardedCustomElement } from '../utils/guarded-custom-element';
13
14
  import { styles } from './sds-radio.styles';
14
15
  import { SDSDelegateInteractionMixin, SDSEventDispatcherMixin, SDSFormControlMixin } from '../mixins';
15
- let SDSRadio = class SDSRadio extends SDSDelegateInteractionMixin(SDSEventDispatcherMixin(SDSFormControlMixin(SDSElement))) {
16
+ let SDSRadio = SDSRadio_1 = class SDSRadio extends SDSDelegateInteractionMixin(SDSEventDispatcherMixin(SDSFormControlMixin(SDSElement))) {
16
17
  constructor() {
17
18
  super(...arguments);
18
19
  this.required = false;
@@ -23,65 +24,91 @@ let SDSRadio = class SDSRadio extends SDSDelegateInteractionMixin(SDSEventDispat
23
24
  this.error = false;
24
25
  this.size = 'md';
25
26
  this._hasSlottedLabel = false;
27
+ // Reactive even though it is never rendered: _syncHostAria() reads it from updated(),
28
+ // so replacing one slotted label with another must schedule a pass.
29
+ this._slottedLabelText = '';
30
+ this._rootNode = null;
26
31
  this._disabled = false;
27
32
  this._disabledIsAuthorControlled = false;
28
33
  this._settingDisabledFromParent = false;
29
34
  this._parentRequestDisabled = false;
30
35
  this._initialChecked = false;
36
+ this._pendingGroupSync = false;
37
+ /** Not every browser focuses a tabindex host on click, and the host must hold focus. */
38
+ this._handleMouseDown = () => {
39
+ if (this.disabled)
40
+ return;
41
+ this.focus();
42
+ };
43
+ /**
44
+ * The label is deliberately not associated with the inert input — a `for` would make
45
+ * getByLabel and friends resolve to an unclickable element — so selection is driven here.
46
+ */
47
+ this._handleClick = () => this._select();
48
+ // `readOnly` is deliberately not an early return: the group is a single tab stop, so
49
+ // blocking the arrow keys would leave every option but the tab stop unreachable.
31
50
  this._handleKeydown = (event) => {
32
- if (!this.name || this.disabled || this.readOnly)
51
+ if (this.disabled)
33
52
  return;
34
53
  // If modifier keys are in play no changes should be applied
35
54
  if (event.altKey || event.ctrlKey || event.shiftKey || event.metaKey) {
36
55
  return;
37
56
  }
38
- const root = this.getRootNode();
39
- const radios = Array.from(root.querySelectorAll(`sds-radio[name="${this.name}"]`));
57
+ // The host holds focus now, so Space no longer reaches the native input.
58
+ if (event.key === ' ') {
59
+ event.preventDefault();
60
+ this.click();
61
+ return;
62
+ }
63
+ if (!this.name)
64
+ return;
65
+ // Native radios skip disabled options rather than stranding focus on them.
66
+ const radios = this._getGroupRadios().filter((radio) => !radio.disabled);
40
67
  const currentIndex = radios.indexOf(this);
41
68
  if (currentIndex === -1)
42
69
  return;
43
- let targetIndex = null;
70
+ let targetRadio;
44
71
  switch (event.key) {
45
72
  case 'ArrowUp':
46
73
  case 'ArrowLeft':
47
- targetIndex = currentIndex > 0 ? currentIndex - 1 : radios.length - 1;
74
+ targetRadio = radios[currentIndex > 0 ? currentIndex - 1 : radios.length - 1];
48
75
  break;
49
76
  case 'ArrowDown':
50
77
  case 'ArrowRight':
51
- targetIndex = currentIndex < radios.length - 1 ? currentIndex + 1 : 0;
78
+ targetRadio = radios[currentIndex < radios.length - 1 ? currentIndex + 1 : 0];
52
79
  break;
53
80
  default:
54
81
  return;
55
82
  }
56
- const targetRadio = radios[targetIndex];
57
- targetRadio?.focus();
58
- targetRadio?.click();
59
83
  event.preventDefault();
60
- };
61
- this._handleChange = (event) => {
62
- if (this.disabled || this.readOnly) {
63
- event.target.checked = this.checked ?? false;
64
- event.preventDefault();
84
+ // A lone enabled option would otherwise wrap onto itself and re-fire a click.
85
+ if (radios.length < 2)
65
86
  return;
66
- }
67
- const elem = event.target;
68
- this.checked = elem.checked;
69
- if (this.checked) {
70
- this._uncheckSiblings();
71
- }
72
- this._updateGroupValidation();
73
- this.dispatchSheriffEvent('change');
87
+ // In a readonly group this moves focus only — click() is a no-op there.
88
+ targetRadio?.focus();
89
+ targetRadio?.click();
74
90
  };
91
+ // Focus lands on the host, so these listen there. The guard skips the CustomEvent that
92
+ // dispatchSheriffEvent re-fires under the same name, which would otherwise recurse.
75
93
  this._handleFocus = (event) => {
94
+ if (event instanceof CustomEvent)
95
+ return;
76
96
  event.stopImmediatePropagation();
77
97
  this.dispatchSheriffEvent('focus');
78
98
  };
79
99
  this._handleBlur = (event) => {
100
+ if (event instanceof CustomEvent)
101
+ return;
80
102
  event.stopImmediatePropagation();
81
103
  this.dispatchSheriffEvent('blur');
82
104
  };
83
105
  this._handleLabelSlotChange = (event) => {
84
- this._hasSlottedLabel = event.target.assignedNodes().length > 0;
106
+ const assigned = event.target.assignedNodes();
107
+ this._hasSlottedLabel = assigned.length > 0;
108
+ this._slottedLabelText = assigned
109
+ .map((node) => node.textContent ?? '')
110
+ .join('')
111
+ .trim();
85
112
  };
86
113
  }
87
114
  /**
@@ -126,19 +153,39 @@ let SDSRadio = class SDSRadio extends SDSDelegateInteractionMixin(SDSEventDispat
126
153
  this._settingDisabledFromParent = false;
127
154
  }
128
155
  connectedCallback() {
156
+ this._rootNode = this.getRootNode();
129
157
  super.connectedCallback();
130
- this.internals.role = 'radio';
158
+ // The host is the radio in the accessibility tree; the inner input is `inert`, which
159
+ // keeps it out of that tree without making it a focusable aria-hidden element. A
160
+ // native radio group cannot cross shadow roots, so exposing the input instead makes
161
+ // every option its own set of one ("1 av 1" rather than "1 av 3").
162
+ this.setAttribute('role', 'radio');
131
163
  if (!this._initialChecked) {
132
164
  this._initialChecked = this.checked ?? false;
133
165
  }
134
166
  this.addEventListener('keydown', this._handleKeydown);
167
+ this.addEventListener('mousedown', this._handleMouseDown);
168
+ this.addEventListener('click', this._handleClick);
169
+ this.addEventListener('focus', this._handleFocus);
170
+ this.addEventListener('blur', this._handleBlur);
171
+ this._scheduleGroupSync();
135
172
  }
136
173
  disconnectedCallback() {
137
174
  super.disconnectedCallback();
138
175
  this.removeEventListener('keydown', this._handleKeydown);
176
+ this.removeEventListener('mousedown', this._handleMouseDown);
177
+ this.removeEventListener('click', this._handleClick);
178
+ this.removeEventListener('focus', this._handleFocus);
179
+ this.removeEventListener('blur', this._handleBlur);
180
+ // `this` is already detached, so this renumbers only the surviving group members.
181
+ // Kept synchronous: deferring it would leave the cached root node nulled out, and
182
+ // the group would never get its numbering or its tab stop back.
183
+ this._syncGroup(this._getGroupRadios());
184
+ this._rootNode = null;
139
185
  }
140
186
  firstUpdated(_changedProperties) {
141
187
  super.firstUpdated(_changedProperties);
188
+ // Needs `radio.control`, which only exists once the shadow root has rendered.
142
189
  this._updateGroupValidation();
143
190
  }
144
191
  updated(changedProperties) {
@@ -156,21 +203,123 @@ let SDSRadio = class SDSRadio extends SDSDelegateInteractionMixin(SDSEventDispat
156
203
  if (changedProperties.has('required') && this.control) {
157
204
  this.control.required = this.required ?? false;
158
205
  }
206
+ if (changedProperties.has('name')) {
207
+ // This radio left its previous group, so renumber what remains of that one too.
208
+ this._syncGroup(this._getGroupRadios(changedProperties.get('name')));
209
+ this._syncGroup(this.name ? this._getGroupRadios() : [this]);
210
+ }
159
211
  if (!this._disabledIsAuthorControlled && this.disabled !== this._parentRequestDisabled) {
160
212
  this._settingDisabledFromParent = true;
161
213
  this.disabled = this._parentRequestDisabled ?? false;
162
214
  this._settingDisabledFromParent = false;
163
215
  }
216
+ // After the reconciliation above, which can still flip `disabled`.
217
+ if (changedProperties.has('checked') || changedProperties.has('disabled')) {
218
+ this._updateGroupTabStops(this.name ? this._getGroupRadios() : [this]);
219
+ }
220
+ this._syncHostAria();
164
221
  }
165
- _getGroupRadios() {
166
- if (!this.name)
167
- return [this];
168
- const root = this.getRootNode();
169
- const radioGroup = Array.from(root.querySelectorAll(`sds-radio[name="${this.name}"]`));
170
- return radioGroup;
222
+ /**
223
+ * Matches on the `name` property rather than the reflected attribute, so radios created
224
+ * imperatively are found before Lit has reflected `name` back out.
225
+ */
226
+ _getGroupRadios(name = this.name, root = this._rootNode ?? this.getRootNode()) {
227
+ if (!name || !root)
228
+ return [];
229
+ return Array.from(root.querySelectorAll('sds-radio')).filter((radio) => radio.name === name);
230
+ }
231
+ /**
232
+ * Mirrors state onto the host, which is the radio in the accessibility tree.
233
+ *
234
+ * Written as attributes rather than through ElementInternals: internals ARIA is
235
+ * IDL-only, so assistive technology sees it but axe, Playwright and Testing Library —
236
+ * which all resolve role and name from attributes — do not.
237
+ */
238
+ _syncHostAria() {
239
+ this.setAttribute('aria-checked', this.checked ? 'true' : 'false');
240
+ this.setAttribute('aria-invalid', this.error ? 'true' : 'false');
241
+ // These need a literal "true"; an empty attribute value does not count as set.
242
+ if (this.disabled)
243
+ this.setAttribute('aria-disabled', 'true');
244
+ else
245
+ this.removeAttribute('aria-disabled');
246
+ if (this.required)
247
+ this.setAttribute('aria-required', 'true');
248
+ else
249
+ this.removeAttribute('aria-required');
250
+ // The label sits in the shadow root, and an id reference does not cross that
251
+ // boundary, so aria-labelledby cannot reach it. Name the host from its text instead.
252
+ const label = this._hasSlottedLabel ? this._slottedLabelText : (this.label ?? '');
253
+ if (label)
254
+ this.setAttribute('aria-label', label);
255
+ else
256
+ this.removeAttribute('aria-label');
257
+ // No attribute form can reference across the boundary either, so the help text is
258
+ // wired up with the element-reference API where that is available.
259
+ if (SDSRadio_1._supportsAriaElementReferences) {
260
+ this.internals.ariaDescribedByElements = this._helpTextElement ? [this._helpTextElement] : [];
261
+ }
262
+ }
263
+ /**
264
+ * Selection never goes through the inner input: its click is composed, so it would
265
+ * retarget to the host and every click would be seen twice from the outside.
266
+ * Like a native radio, this only fires `change` when the checkedness actually changes.
267
+ */
268
+ _select() {
269
+ if (this.disabled || this.readOnly || this.checked)
270
+ return;
271
+ this.checked = true;
272
+ // Settle the group before the event, so a listener never sees two checked radios.
273
+ this._uncheckSiblings();
274
+ this._updateGroupValidation();
275
+ this.dispatchSheriffEvent('change');
276
+ }
277
+ /**
278
+ * A radio group does not cross shadow roots, so the browser sees each radio as a set of
279
+ * one. State the position explicitly across the whole name-group instead.
280
+ */
281
+ _updateGroupPositions(members) {
282
+ members.forEach((radio, index) => {
283
+ radio.setAttribute('aria-posinset', String(index + 1));
284
+ radio.setAttribute('aria-setsize', String(members.length));
285
+ });
286
+ }
287
+ /** A radio group is one tab stop: the checked option, or the first enabled one. */
288
+ _updateGroupTabStops(members) {
289
+ const focusable = members.filter((radio) => !radio.disabled);
290
+ const tabStop = focusable.find((radio) => radio.checked) ?? focusable[0];
291
+ for (const radio of members) {
292
+ // Native radios are not focusable at all while disabled. The others keep
293
+ // tabindex="-1" so the arrow keys can still move focus to them.
294
+ if (radio.disabled)
295
+ radio.removeAttribute('tabindex');
296
+ else
297
+ radio.tabIndex = radio === tabStop ? 0 : -1;
298
+ }
299
+ }
300
+ _syncGroup(members) {
301
+ this._updateGroupPositions(members);
302
+ this._updateGroupTabStops(members);
303
+ }
304
+ /**
305
+ * Conditional rendering and reordering both run through disconnect/connect, while
306
+ * firstUpdated only ever fires once. Membership is recomputed from the microtask so the
307
+ * surrounding batch of insertions has settled — and so every member has been upgraded,
308
+ * since a non-upgraded element matches the selector but has no `name`.
309
+ */
310
+ _scheduleGroupSync() {
311
+ if (this._pendingGroupSync)
312
+ return;
313
+ this._pendingGroupSync = true;
314
+ queueMicrotask(() => {
315
+ this._pendingGroupSync = false;
316
+ if (!this.isConnected)
317
+ return;
318
+ this._syncGroup(this.name ? this._getGroupRadios() : [this]);
319
+ });
171
320
  }
172
321
  _updateGroupValidation() {
173
- const group = this._getGroupRadios();
322
+ const group = this.name ? this._getGroupRadios() : [this];
174
323
  const isAnyChecked = group.some((radio) => radio.checked);
175
324
  const isAnyRequired = group.some((radio) => radio.required);
176
325
  group.forEach((radio) => {
@@ -201,6 +350,21 @@ let SDSRadio = class SDSRadio extends SDSDelegateInteractionMixin(SDSEventDispat
201
350
  }
202
351
  }
203
352
  }
353
+ // The host is the radio, so these three bypass SDSDelegateInteractionMixin, which would
354
+ // send them on to the inner input.
355
+ focus(options) {
356
+ if (this.disabled)
357
+ return;
358
+ HTMLElement.prototype.focus.call(this, options);
359
+ }
360
+ blur() {
361
+ HTMLElement.prototype.blur.call(this);
362
+ }
363
+ click() {
364
+ if (this.disabled || this.readOnly)
365
+ return;
366
+ HTMLElement.prototype.click.call(this);
367
+ }
204
368
  get type() {
205
369
  return 'radio';
206
370
  }
@@ -239,7 +403,6 @@ let SDSRadio = class SDSRadio extends SDSDelegateInteractionMixin(SDSEventDispat
239
403
  'sds-radio__input': true,
240
404
  'sds-radio__input--error': Boolean(this.error),
241
405
  };
242
- const describedBy = this.helpText ? 'help-text' : undefined;
243
406
  return html `
244
407
  <div class="${classMap(radioClasses)}">
245
408
  <input
@@ -253,14 +416,10 @@ let SDSRadio = class SDSRadio extends SDSDelegateInteractionMixin(SDSEventDispat
253
416
  .disabled="${this.disabled ?? false}"
254
417
  ?required="${this.required}"
255
418
  ?readonly="${this.readOnly}"
256
- aria-describedby="${ifDefined(describedBy)}"
257
- aria-invalid="${this.error ? 'true' : 'false'}"
258
- @change="${this._handleChange}"
259
- @focus="${this._handleFocus}"
260
- @blur="${this._handleBlur}"
419
+ inert
261
420
  class="${classMap(inputClasses)}"
262
421
  />
263
- <label class="sds-radio__label" for="control" ?hidden="${!showLabel}">
422
+ <label class="sds-radio__label" ?hidden="${!showLabel}">
264
423
  <slot name="label" @slotchange="${this._handleLabelSlotChange}">${this.label}</slot>
265
424
  </label>
266
425
  ${this.helpText ? html `<span id="help-text" class="sds-radio__help-text">${this.helpText}</span>` : nothing}
@@ -270,6 +429,18 @@ let SDSRadio = class SDSRadio extends SDSDelegateInteractionMixin(SDSEventDispat
270
429
  };
271
430
  // Styling
272
431
  SDSRadio.styles = [styles];
432
+ /**
433
+ * The host carries `role="radio"` and must receive focus itself, so focus must not be
434
+ * delegated into the shadow root the way SDSFormControlMixin sets up by default.
435
+ */
436
+ SDSRadio.shadowRootOptions = {
437
+ ...LitElement.shadowRootOptions,
438
+ delegatesFocus: false,
439
+ };
440
+ // Safari 16.4, Chrome/Edge 135, Firefox 136. Older browsers lose the description rather
441
+ // than breaking. Guarded because this is evaluated at class-definition time, i.e. on
442
+ // import, and ElementInternals is not defined outside the browser.
443
+ SDSRadio._supportsAriaElementReferences = typeof ElementInternals !== 'undefined' && 'ariaDescribedByElements' in ElementInternals.prototype;
273
444
  __decorate([
274
445
  property({ type: Boolean, reflect: true })
275
446
  ], SDSRadio.prototype, "required", void 0);
@@ -303,10 +474,16 @@ __decorate([
303
474
  __decorate([
304
475
  query('#control')
305
476
  ], SDSRadio.prototype, "control", void 0);
477
+ __decorate([
478
+ query('#help-text')
479
+ ], SDSRadio.prototype, "_helpTextElement", void 0);
306
480
  __decorate([
307
481
  state()
308
482
  ], SDSRadio.prototype, "_hasSlottedLabel", void 0);
309
- SDSRadio = __decorate([
483
+ __decorate([
484
+ state()
485
+ ], SDSRadio.prototype, "_slottedLabelText", void 0);
486
+ SDSRadio = SDSRadio_1 = __decorate([
310
487
  guardedCustomElement('sds-radio')
311
488
  ], SDSRadio);
312
489
  export { SDSRadio };
@@ -1 +1 @@
1
- {"version":3,"file":"sds-radio.js","sourceRoot":"","sources":["../../src/sds-radio/sds-radio.ts"],"names":[],"mappings":"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","sourcesContent":["import { PropertyValues, html, nothing } from 'lit';\nimport { SDSElement } from '../utils/sds-element';\nimport { property, query, state } from 'lit/decorators.js';\nimport { ifDefined } from 'lit/directives/if-defined.js';\nimport { classMap } from 'lit/directives/class-map.js';\nimport { guardedCustomElement } from '../utils/guarded-custom-element';\nimport { styles } from './sds-radio.styles';\nimport { SDS_SIZES } from '../types';\nimport { SDSDelegateInteractionMixin, SDSEventDispatcherMixin, SDSFormControlMixin } from '../mixins';\nimport type { SDSFormControlAttributes } from '../mixins/sds-form-control-mixin';\n\ntype RadioSize = Extract<SDS_SIZES, 'lg' | 'md' | 'sm'>;\n\nexport interface SDSRadioProps extends SDSFormControlAttributes {\n\tchecked?: boolean;\n\terror?: boolean;\n\t'help-text'?: string;\n\t'hide-label'?: boolean;\n\tlabel?: string;\n\tparentRequestDisabled?: boolean;\n\trequired?: boolean;\n\tsize?: RadioSize;\n\tvalue?: string;\n}\n\n@guardedCustomElement('sds-radio')\nexport class SDSRadio extends SDSDelegateInteractionMixin(SDSEventDispatcherMixin(SDSFormControlMixin(SDSElement))) {\n\t// Styling\n\tstatic override styles = [styles];\n\n\t@property({ type: Boolean, reflect: true }) required: SDSRadioProps['required'] = false;\n\t@property({ type: String, reflect: true }) label: SDSRadioProps['label'] = '';\n\t@property({ type: Boolean, reflect: true, attribute: 'hide-label' }) hideLabel: SDSRadioProps['hide-label'] = false;\n\t@property({ type: String }) value: SDSRadioProps['value'] = 'on';\n\t@property({ type: Boolean, reflect: true }) checked: SDSRadioProps['checked'] = false;\n\t@property({ type: Boolean, reflect: true }) error: SDSRadioProps['error'] = false;\n\t@property({ type: String, reflect: true }) size: SDSRadioProps['size'] = 'md';\n\t@property({ type: String, attribute: 'help-text' }) helpText?: SDSRadioProps['help-text'];\n\n\t/**\n\t * disabled:\n\t * - If set directly (prop/attr), this radio becomes \"self-controlled\"\n\t * and ignores parentRequestDisabled.\n\t * - If not self-controlled, this follows parentRequestDisabled (group/form).\n\t */\n\t@property({ type: Boolean, reflect: true })\n\toverride get disabled(): SDSRadioProps['disabled'] {\n\t\treturn this._disabled;\n\t}\n\toverride set disabled(value: SDSRadioProps['disabled']) {\n\t\tconst newVal = value ?? false;\n\t\tconst oldVal = this._disabled;\n\n\t\tif (oldVal === newVal) return;\n\n\t\tthis._disabled = newVal;\n\t\tthis.requestUpdate('disabled', oldVal);\n\n\t\tif (!this._settingDisabledFromParent) {\n\t\t\tthis._disabledIsAuthorControlled = newVal;\n\t\t}\n\t}\n\n\t/**\n\t * parentRequestDisabled:\n\t * - Set by SDSRadioGroup to request disabled/enabled.\n\t * - Only applied if SDSRadio is NOT self-controlled.\n\t */\n\t@property({ type: Boolean, attribute: false })\n\tget parentRequestDisabled(): SDSRadioProps['parentRequestDisabled'] {\n\t\treturn this._parentRequestDisabled;\n\t}\n\tset parentRequestDisabled(value: SDSRadioProps['parentRequestDisabled']) {\n\t\tconst newVal = value ?? false;\n\t\tconst oldVal = this._parentRequestDisabled;\n\n\t\tif (oldVal === newVal) return;\n\n\t\tthis._parentRequestDisabled = newVal;\n\t\tthis.requestUpdate('parentRequestDisabled', oldVal);\n\n\t\tif (this._disabledIsAuthorControlled) return;\n\n\t\tthis._settingDisabledFromParent = true;\n\t\tthis.disabled = newVal;\n\t\tthis._settingDisabledFromParent = false;\n\t}\n\n\t@query('#control') control!: HTMLInputElement;\n\n\t@state() private _hasSlottedLabel = false;\n\n\tprivate _disabled: boolean = false;\n\tprivate _disabledIsAuthorControlled: boolean = false;\n\tprivate _settingDisabledFromParent: boolean = false;\n\tprivate _parentRequestDisabled: SDSRadioProps['parentRequestDisabled'] = false;\n\tprivate _initialChecked: boolean = false;\n\n\toverride connectedCallback() {\n\t\tsuper.connectedCallback();\n\t\tthis.internals.role = 'radio';\n\t\tif (!this._initialChecked) {\n\t\t\tthis._initialChecked = this.checked ?? false;\n\t\t}\n\t\tthis.addEventListener('keydown', this._handleKeydown);\n\t}\n\n\toverride disconnectedCallback() {\n\t\tsuper.disconnectedCallback();\n\t\tthis.removeEventListener('keydown', this._handleKeydown);\n\t}\n\n\toverride firstUpdated(_changedProperties: PropertyValues): void {\n\t\tsuper.firstUpdated(_changedProperties);\n\t\tthis._updateGroupValidation();\n\t}\n\n\toverride updated(changedProperties: Map<string | number | symbol, unknown>) {\n\t\tsuper.updated(changedProperties);\n\n\t\tif (changedProperties.has('checked')) {\n\t\t\tif (this.checked) {\n\t\t\t\tthis._uncheckSiblings();\n\t\t\t\tthis.internals.setFormValue(this.value ?? null);\n\t\t\t} else {\n\t\t\t\tthis.internals.setFormValue(null);\n\t\t\t}\n\t\t\tthis._updateGroupValidation();\n\t\t}\n\n\t\tif (changedProperties.has('required') && this.control) {\n\t\t\tthis.control.required = this.required ?? false;\n\t\t}\n\n\t\tif (!this._disabledIsAuthorControlled && this.disabled !== this._parentRequestDisabled) {\n\t\t\tthis._settingDisabledFromParent = true;\n\t\t\tthis.disabled = this._parentRequestDisabled ?? false;\n\t\t\tthis._settingDisabledFromParent = false;\n\t\t}\n\t}\n\n\tprivate _getGroupRadios(): SDSRadio[] {\n\t\tif (!this.name) return [this];\n\t\tconst root = this.getRootNode() as Document | ShadowRoot;\n\t\tconst radioGroup = Array.from(root.querySelectorAll<SDSRadio>(`sds-radio[name=\"${this.name}\"]`));\n\t\treturn radioGroup;\n\t}\n\n\tprivate _updateGroupValidation() {\n\t\tconst group: Array<SDSRadio> = this._getGroupRadios();\n\t\tconst isAnyChecked = group.some((radio) => radio.checked);\n\t\tconst isAnyRequired = group.some((radio) => radio.required);\n\t\tgroup.forEach((radio) => {\n\t\t\tif (!radio.control) return;\n\t\t\tif (isAnyRequired) {\n\t\t\t\tradio.internals.setValidity(isAnyChecked ? {} : { valueMissing: true }, isAnyChecked ? '' : radio.control.validationMessage, radio.control);\n\t\t\t} else {\n\t\t\t\tradio.internals.setValidity({});\n\t\t\t}\n\t\t});\n\t}\n\n\tprivate readonly _handleKeydown = (event: KeyboardEvent) => {\n\t\tif (!this.name || this.disabled || this.readOnly) return;\n\n\t\t// If modifier keys are in play no changes should be applied\n\t\tif (event.altKey || event.ctrlKey || event.shiftKey || event.metaKey) {\n\t\t\treturn;\n\t\t}\n\n\t\tconst root = this.getRootNode() as Document | ShadowRoot;\n\t\tconst radios = Array.from(root.querySelectorAll<SDSRadio>(`sds-radio[name=\"${this.name}\"]`));\n\t\tconst currentIndex = radios.indexOf(this);\n\n\t\tif (currentIndex === -1) return;\n\n\t\tlet targetIndex: number | null = null;\n\n\t\tswitch (event.key) {\n\t\t\tcase 'ArrowUp':\n\t\t\tcase 'ArrowLeft':\n\t\t\t\ttargetIndex = currentIndex > 0 ? currentIndex - 1 : radios.length - 1;\n\t\t\t\tbreak;\n\t\t\tcase 'ArrowDown':\n\t\t\tcase 'ArrowRight':\n\t\t\t\ttargetIndex = currentIndex < radios.length - 1 ? currentIndex + 1 : 0;\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\treturn;\n\t\t}\n\n\t\tconst targetRadio = radios[targetIndex];\n\t\ttargetRadio?.focus();\n\t\ttargetRadio?.click();\n\t\tevent.preventDefault();\n\t};\n\n\tformResetCallback() {\n\t\tthis.checked = this._initialChecked;\n\t\tthis.control.checked = this._initialChecked;\n\t\tthis.internals.setFormValue(this.checked ? this.value ?? 'on' : null);\n\t\tthis._updateGroupValidation();\n\t}\n\n\tprivate _uncheckSiblings() {\n\t\tif (!this.name) return;\n\t\tconst radios: Array<SDSRadio> = this._getGroupRadios();\n\n\t\tfor (const radio of radios) {\n\t\t\tif (radio !== this && radio.checked) {\n\t\t\t\tradio.checked = false;\n\t\t\t\tradio.internals.setFormValue(null);\n\t\t\t}\n\t\t}\n\t}\n\n\tprivate readonly _handleChange = (event: Event) => {\n\t\tif (this.disabled || this.readOnly) {\n\t\t\t(event.target as HTMLInputElement).checked = this.checked ?? false;\n\t\t\tevent.preventDefault();\n\t\t\treturn;\n\t\t}\n\n\t\tconst elem = event.target as HTMLInputElement;\n\t\tthis.checked = elem.checked;\n\t\tif (this.checked) {\n\t\t\tthis._uncheckSiblings();\n\t\t}\n\t\tthis._updateGroupValidation();\n\t\tthis.dispatchSheriffEvent('change');\n\t};\n\n\tprivate readonly _handleFocus = (event: Event) => {\n\t\tevent.stopImmediatePropagation();\n\t\tthis.dispatchSheriffEvent('focus');\n\t};\n\n\tprivate readonly _handleBlur = (event: Event) => {\n\t\tevent.stopImmediatePropagation();\n\t\tthis.dispatchSheriffEvent('blur');\n\t};\n\n\tget type(): string {\n\t\treturn 'radio';\n\t}\n\n\tget validity() {\n\t\treturn this.internals.validity;\n\t}\n\n\tget validationMessage() {\n\t\treturn this.internals.validationMessage;\n\t}\n\n\tget willValidate() {\n\t\treturn this.internals.willValidate;\n\t}\n\n\tcheckValidity(): boolean {\n\t\treturn this.internals.checkValidity();\n\t}\n\n\treportValidity(): boolean {\n\t\treturn this.internals.reportValidity();\n\t}\n\n\tsetCustomValidity(message: string): void {\n\t\tthis.internals.setValidity({ customError: !!message }, message);\n\t}\n\n\toverride formDisabledCallback(disabled: boolean): void {\n\t\tthis._settingDisabledFromParent = true;\n\t\tthis.disabled = disabled;\n\t\tthis._settingDisabledFromParent = false;\n\t\tif (this.control) this.control.disabled = disabled;\n\t}\n\n\tprivate readonly _handleLabelSlotChange = (event: Event) => {\n\t\tthis._hasSlottedLabel = (event.target as HTMLSlotElement).assignedNodes().length > 0;\n\t};\n\n\toverride render() {\n\t\tconst radioClasses = {\n\t\t\t'sds-radio': true,\n\t\t\t'sds-radio--error': Boolean(this.error),\n\t\t};\n\n\t\tconst showLabel = this._hasSlottedLabel || Boolean(this.label);\n\n\t\tconst inputClasses = {\n\t\t\t'sds-radio__input': true,\n\t\t\t'sds-radio__input--error': Boolean(this.error),\n\t\t};\n\n\t\tconst describedBy = this.helpText ? 'help-text' : undefined;\n\n\t\treturn html`\n\t\t\t<div class=\"${classMap(radioClasses)}\">\n\t\t\t\t<input\n\t\t\t\t\tid=\"control\"\n\t\t\t\t\ttype=\"radio\"\n\t\t\t\t\tname=\"${ifDefined(this.name)}\"\n\t\t\t\t\tvalue=\"${ifDefined(this.value)}\"\n\t\t\t\t\t?checked=\"${this.checked ?? false}\"\n\t\t\t\t\t.checked=\"${this.checked ?? false}\"\n\t\t\t\t\t?disabled=\"${this.disabled ?? false}\"\n\t\t\t\t\t.disabled=\"${this.disabled ?? false}\"\n\t\t\t\t\t?required=\"${this.required}\"\n\t\t\t\t\t?readonly=\"${this.readOnly}\"\n\t\t\t\t\taria-describedby=\"${ifDefined(describedBy)}\"\n\t\t\t\t\taria-invalid=\"${this.error ? 'true' : 'false'}\"\n\t\t\t\t\t@change=\"${this._handleChange}\"\n\t\t\t\t\t@focus=\"${this._handleFocus}\"\n\t\t\t\t\t@blur=\"${this._handleBlur}\"\n\t\t\t\t\tclass=\"${classMap(inputClasses)}\"\n\t\t\t\t/>\n\t\t\t\t<label class=\"sds-radio__label\" for=\"control\" ?hidden=\"${!showLabel}\">\n\t\t\t\t\t<slot name=\"label\" @slotchange=\"${this._handleLabelSlotChange}\">${this.label}</slot>\n\t\t\t\t</label>\n\t\t\t\t${this.helpText ? html`<span id=\"help-text\" class=\"sds-radio__help-text\">${this.helpText}</span>` : nothing}\n\t\t\t</div>\n\t\t`;\n\t}\n}\n\ndeclare global {\n\tinterface HTMLElementTagNameMap {\n\t\t'sds-radio': SDSRadio;\n\t}\n}\n"]}
1
+ {"version":3,"file":"sds-radio.js","sourceRoot":"","sources":["../../src/sds-radio/sds-radio.ts"],"names":[],"mappings":"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","sourcesContent":["import { LitElement, PropertyValues, html, nothing } from 'lit';\nimport { SDSElement } from '../utils/sds-element';\nimport { property, query, state } from 'lit/decorators.js';\nimport { ifDefined } from 'lit/directives/if-defined.js';\nimport { classMap } from 'lit/directives/class-map.js';\nimport { guardedCustomElement } from '../utils/guarded-custom-element';\nimport { styles } from './sds-radio.styles';\nimport { SDS_SIZES } from '../types';\nimport { SDSDelegateInteractionMixin, SDSEventDispatcherMixin, SDSFormControlMixin } from '../mixins';\nimport type { SDSFormControlAttributes } from '../mixins/sds-form-control-mixin';\n\ntype RadioSize = Extract<SDS_SIZES, 'lg' | 'md' | 'sm'>;\n\nexport interface SDSRadioProps extends SDSFormControlAttributes {\n\tchecked?: boolean;\n\terror?: boolean;\n\t'help-text'?: string;\n\t'hide-label'?: boolean;\n\tlabel?: string;\n\tparentRequestDisabled?: boolean;\n\trequired?: boolean;\n\tsize?: RadioSize;\n\tvalue?: string;\n}\n\n@guardedCustomElement('sds-radio')\nexport class SDSRadio extends SDSDelegateInteractionMixin(SDSEventDispatcherMixin(SDSFormControlMixin(SDSElement))) {\n\t// Styling\n\tstatic override styles = [styles];\n\n\t/**\n\t * The host carries `role=\"radio\"` and must receive focus itself, so focus must not be\n\t * delegated into the shadow root the way SDSFormControlMixin sets up by default.\n\t */\n\tstatic override shadowRootOptions: ShadowRootInit = {\n\t\t...LitElement.shadowRootOptions,\n\t\tdelegatesFocus: false,\n\t};\n\n\t@property({ type: Boolean, reflect: true }) required: SDSRadioProps['required'] = false;\n\t@property({ type: String, reflect: true }) label: SDSRadioProps['label'] = '';\n\t@property({ type: Boolean, reflect: true, attribute: 'hide-label' }) hideLabel: SDSRadioProps['hide-label'] = false;\n\t@property({ type: String }) value: SDSRadioProps['value'] = 'on';\n\t@property({ type: Boolean, reflect: true }) checked: SDSRadioProps['checked'] = false;\n\t@property({ type: Boolean, reflect: true }) error: SDSRadioProps['error'] = false;\n\t@property({ type: String, reflect: true }) size: SDSRadioProps['size'] = 'md';\n\t@property({ type: String, attribute: 'help-text' }) helpText?: SDSRadioProps['help-text'];\n\n\t/**\n\t * disabled:\n\t * - If set directly (prop/attr), this radio becomes \"self-controlled\"\n\t * and ignores parentRequestDisabled.\n\t * - If not self-controlled, this follows parentRequestDisabled (group/form).\n\t */\n\t@property({ type: Boolean, reflect: true })\n\toverride get disabled(): SDSRadioProps['disabled'] {\n\t\treturn this._disabled;\n\t}\n\toverride set disabled(value: SDSRadioProps['disabled']) {\n\t\tconst newVal = value ?? false;\n\t\tconst oldVal = this._disabled;\n\n\t\tif (oldVal === newVal) return;\n\n\t\tthis._disabled = newVal;\n\t\tthis.requestUpdate('disabled', oldVal);\n\n\t\tif (!this._settingDisabledFromParent) {\n\t\t\tthis._disabledIsAuthorControlled = newVal;\n\t\t}\n\t}\n\n\t/**\n\t * parentRequestDisabled:\n\t * - Set by SDSRadioGroup to request disabled/enabled.\n\t * - Only applied if SDSRadio is NOT self-controlled.\n\t */\n\t@property({ type: Boolean, attribute: false })\n\tget parentRequestDisabled(): SDSRadioProps['parentRequestDisabled'] {\n\t\treturn this._parentRequestDisabled;\n\t}\n\tset parentRequestDisabled(value: SDSRadioProps['parentRequestDisabled']) {\n\t\tconst newVal = value ?? false;\n\t\tconst oldVal = this._parentRequestDisabled;\n\n\t\tif (oldVal === newVal) return;\n\n\t\tthis._parentRequestDisabled = newVal;\n\t\tthis.requestUpdate('parentRequestDisabled', oldVal);\n\n\t\tif (this._disabledIsAuthorControlled) return;\n\n\t\tthis._settingDisabledFromParent = true;\n\t\tthis.disabled = newVal;\n\t\tthis._settingDisabledFromParent = false;\n\t}\n\n\t@query('#control') control!: HTMLInputElement;\n\t@query('#help-text') private _helpTextElement?: HTMLElement;\n\n\t@state() private _hasSlottedLabel = false;\n\t// Reactive even though it is never rendered: _syncHostAria() reads it from updated(),\n\t// so replacing one slotted label with another must schedule a pass.\n\t@state() private _slottedLabelText = '';\n\n\tprivate _rootNode: Document | ShadowRoot | null = null;\n\tprivate _disabled: boolean = false;\n\tprivate _disabledIsAuthorControlled: boolean = false;\n\tprivate _settingDisabledFromParent: boolean = false;\n\tprivate _parentRequestDisabled: SDSRadioProps['parentRequestDisabled'] = false;\n\tprivate _initialChecked: boolean = false;\n\tprivate _pendingGroupSync: boolean = false;\n\n\toverride connectedCallback() {\n\t\tthis._rootNode = this.getRootNode() as Document | ShadowRoot;\n\t\tsuper.connectedCallback();\n\t\t// The host is the radio in the accessibility tree; the inner input is `inert`, which\n\t\t// keeps it out of that tree without making it a focusable aria-hidden element. A\n\t\t// native radio group cannot cross shadow roots, so exposing the input instead makes\n\t\t// every option its own set of one (\"1 av 1\" rather than \"1 av 3\").\n\t\tthis.setAttribute('role', 'radio');\n\t\tif (!this._initialChecked) {\n\t\t\tthis._initialChecked = this.checked ?? false;\n\t\t}\n\t\tthis.addEventListener('keydown', this._handleKeydown);\n\t\tthis.addEventListener('mousedown', this._handleMouseDown);\n\t\tthis.addEventListener('click', this._handleClick);\n\t\tthis.addEventListener('focus', this._handleFocus);\n\t\tthis.addEventListener('blur', this._handleBlur);\n\t\tthis._scheduleGroupSync();\n\t}\n\n\toverride disconnectedCallback() {\n\t\tsuper.disconnectedCallback();\n\t\tthis.removeEventListener('keydown', this._handleKeydown);\n\t\tthis.removeEventListener('mousedown', this._handleMouseDown);\n\t\tthis.removeEventListener('click', this._handleClick);\n\t\tthis.removeEventListener('focus', this._handleFocus);\n\t\tthis.removeEventListener('blur', this._handleBlur);\n\t\t// `this` is already detached, so this renumbers only the surviving group members.\n\t\t// Kept synchronous: deferring it would leave the cached root node nulled out, and\n\t\t// the group would never get its numbering or its tab stop back.\n\t\tthis._syncGroup(this._getGroupRadios());\n\t\tthis._rootNode = null;\n\t}\n\n\toverride firstUpdated(_changedProperties: PropertyValues): void {\n\t\tsuper.firstUpdated(_changedProperties);\n\t\t// Needs `radio.control`, which only exists once the shadow root has rendered.\n\t\tthis._updateGroupValidation();\n\t}\n\n\toverride updated(changedProperties: Map<string | number | symbol, unknown>) {\n\t\tsuper.updated(changedProperties);\n\n\t\tif (changedProperties.has('checked')) {\n\t\t\tif (this.checked) {\n\t\t\t\tthis._uncheckSiblings();\n\t\t\t\tthis.internals.setFormValue(this.value ?? null);\n\t\t\t} else {\n\t\t\t\tthis.internals.setFormValue(null);\n\t\t\t}\n\t\t\tthis._updateGroupValidation();\n\t\t}\n\n\t\tif (changedProperties.has('required') && this.control) {\n\t\t\tthis.control.required = this.required ?? false;\n\t\t}\n\n\t\tif (changedProperties.has('name')) {\n\t\t\t// This radio left its previous group, so renumber what remains of that one too.\n\t\t\tthis._syncGroup(this._getGroupRadios(changedProperties.get('name') as string | undefined));\n\t\t\tthis._syncGroup(this.name ? this._getGroupRadios() : [this]);\n\t\t}\n\n\t\tif (!this._disabledIsAuthorControlled && this.disabled !== this._parentRequestDisabled) {\n\t\t\tthis._settingDisabledFromParent = true;\n\t\t\tthis.disabled = this._parentRequestDisabled ?? false;\n\t\t\tthis._settingDisabledFromParent = false;\n\t\t}\n\n\t\t// After the reconciliation above, which can still flip `disabled`.\n\t\tif (changedProperties.has('checked') || changedProperties.has('disabled')) {\n\t\t\tthis._updateGroupTabStops(this.name ? this._getGroupRadios() : [this]);\n\t\t}\n\n\t\tthis._syncHostAria();\n\t}\n\n\t/**\n\t * Matches on the `name` property rather than the reflected attribute, so radios created\n\t * imperatively are found before Lit has reflected `name` back out.\n\t */\n\tprivate _getGroupRadios(name = this.name, root = this._rootNode ?? (this.getRootNode() as Document | ShadowRoot)): SDSRadio[] {\n\t\tif (!name || !root) return [];\n\t\treturn Array.from(root.querySelectorAll<SDSRadio>('sds-radio')).filter((radio) => radio.name === name);\n\t}\n\n\t/**\n\t * Mirrors state onto the host, which is the radio in the accessibility tree.\n\t *\n\t * Written as attributes rather than through ElementInternals: internals ARIA is\n\t * IDL-only, so assistive technology sees it but axe, Playwright and Testing Library —\n\t * which all resolve role and name from attributes — do not.\n\t */\n\tprivate _syncHostAria() {\n\t\tthis.setAttribute('aria-checked', this.checked ? 'true' : 'false');\n\t\tthis.setAttribute('aria-invalid', this.error ? 'true' : 'false');\n\t\t// These need a literal \"true\"; an empty attribute value does not count as set.\n\t\tif (this.disabled) this.setAttribute('aria-disabled', 'true');\n\t\telse this.removeAttribute('aria-disabled');\n\t\tif (this.required) this.setAttribute('aria-required', 'true');\n\t\telse this.removeAttribute('aria-required');\n\n\t\t// The label sits in the shadow root, and an id reference does not cross that\n\t\t// boundary, so aria-labelledby cannot reach it. Name the host from its text instead.\n\t\tconst label = this._hasSlottedLabel ? this._slottedLabelText : (this.label ?? '');\n\t\tif (label) this.setAttribute('aria-label', label);\n\t\telse this.removeAttribute('aria-label');\n\n\t\t// No attribute form can reference across the boundary either, so the help text is\n\t\t// wired up with the element-reference API where that is available.\n\t\tif (SDSRadio._supportsAriaElementReferences) {\n\t\t\tthis.internals.ariaDescribedByElements = this._helpTextElement ? [this._helpTextElement] : [];\n\t\t}\n\t}\n\n\t// Safari 16.4, Chrome/Edge 135, Firefox 136. Older browsers lose the description rather\n\t// than breaking. Guarded because this is evaluated at class-definition time, i.e. on\n\t// import, and ElementInternals is not defined outside the browser.\n\tprivate static readonly _supportsAriaElementReferences =\n\t\ttypeof ElementInternals !== 'undefined' && 'ariaDescribedByElements' in ElementInternals.prototype;\n\n\t/** Not every browser focuses a tabindex host on click, and the host must hold focus. */\n\tprivate readonly _handleMouseDown = () => {\n\t\tif (this.disabled) return;\n\t\tthis.focus();\n\t};\n\n\t/**\n\t * The label is deliberately not associated with the inert input — a `for` would make\n\t * getByLabel and friends resolve to an unclickable element — so selection is driven here.\n\t */\n\tprivate readonly _handleClick = () => this._select();\n\n\t/**\n\t * Selection never goes through the inner input: its click is composed, so it would\n\t * retarget to the host and every click would be seen twice from the outside.\n\t * Like a native radio, this only fires `change` when the checkedness actually changes.\n\t */\n\tprivate _select() {\n\t\tif (this.disabled || this.readOnly || this.checked) return;\n\n\t\tthis.checked = true;\n\t\t// Settle the group before the event, so a listener never sees two checked radios.\n\t\tthis._uncheckSiblings();\n\t\tthis._updateGroupValidation();\n\t\tthis.dispatchSheriffEvent('change');\n\t}\n\n\t/**\n\t * A radio group does not cross shadow roots, so the browser sees each radio as a set of\n\t * one. State the position explicitly across the whole name-group instead.\n\t */\n\tprivate _updateGroupPositions(members: SDSRadio[]) {\n\t\tmembers.forEach((radio, index) => {\n\t\t\tradio.setAttribute('aria-posinset', String(index + 1));\n\t\t\tradio.setAttribute('aria-setsize', String(members.length));\n\t\t});\n\t}\n\n\t/** A radio group is one tab stop: the checked option, or the first enabled one. */\n\tprivate _updateGroupTabStops(members: SDSRadio[]) {\n\t\tconst focusable = members.filter((radio) => !radio.disabled);\n\t\tconst tabStop = focusable.find((radio) => radio.checked) ?? focusable[0];\n\n\t\tfor (const radio of members) {\n\t\t\t// Native radios are not focusable at all while disabled. The others keep\n\t\t\t// tabindex=\"-1\" so the arrow keys can still move focus to them.\n\t\t\tif (radio.disabled) radio.removeAttribute('tabindex');\n\t\t\telse radio.tabIndex = radio === tabStop ? 0 : -1;\n\t\t}\n\t}\n\n\tprivate _syncGroup(members: SDSRadio[]) {\n\t\tthis._updateGroupPositions(members);\n\t\tthis._updateGroupTabStops(members);\n\t}\n\n\t/**\n\t * Conditional rendering and reordering both run through disconnect/connect, while\n\t * firstUpdated only ever fires once. Membership is recomputed from the microtask so the\n\t * surrounding batch of insertions has settled — and so every member has been upgraded,\n\t * since a non-upgraded element matches the selector but has no `name`.\n\t */\n\tprivate _scheduleGroupSync() {\n\t\tif (this._pendingGroupSync) return;\n\t\tthis._pendingGroupSync = true;\n\n\t\tqueueMicrotask(() => {\n\t\t\tthis._pendingGroupSync = false;\n\t\t\tif (!this.isConnected) return;\n\t\t\tthis._syncGroup(this.name ? this._getGroupRadios() : [this]);\n\t\t});\n\t}\n\n\tprivate _updateGroupValidation() {\n\t\tconst group: Array<SDSRadio> = this.name ? this._getGroupRadios() : [this];\n\t\tconst isAnyChecked = group.some((radio) => radio.checked);\n\t\tconst isAnyRequired = group.some((radio) => radio.required);\n\t\tgroup.forEach((radio) => {\n\t\t\tif (!radio.control) return;\n\t\t\tif (isAnyRequired) {\n\t\t\t\tradio.internals.setValidity(isAnyChecked ? {} : { valueMissing: true }, isAnyChecked ? '' : radio.control.validationMessage, radio.control);\n\t\t\t} else {\n\t\t\t\tradio.internals.setValidity({});\n\t\t\t}\n\t\t});\n\t}\n\n\t// `readOnly` is deliberately not an early return: the group is a single tab stop, so\n\t// blocking the arrow keys would leave every option but the tab stop unreachable.\n\tprivate readonly _handleKeydown = (event: KeyboardEvent) => {\n\t\tif (this.disabled) return;\n\n\t\t// If modifier keys are in play no changes should be applied\n\t\tif (event.altKey || event.ctrlKey || event.shiftKey || event.metaKey) {\n\t\t\treturn;\n\t\t}\n\n\t\t// The host holds focus now, so Space no longer reaches the native input.\n\t\tif (event.key === ' ') {\n\t\t\tevent.preventDefault();\n\t\t\tthis.click();\n\t\t\treturn;\n\t\t}\n\n\t\tif (!this.name) return;\n\n\t\t// Native radios skip disabled options rather than stranding focus on them.\n\t\tconst radios = this._getGroupRadios().filter((radio) => !radio.disabled);\n\t\tconst currentIndex = radios.indexOf(this);\n\n\t\tif (currentIndex === -1) return;\n\n\t\tlet targetRadio: SDSRadio | undefined;\n\n\t\tswitch (event.key) {\n\t\t\tcase 'ArrowUp':\n\t\t\tcase 'ArrowLeft':\n\t\t\t\ttargetRadio = radios[currentIndex > 0 ? currentIndex - 1 : radios.length - 1];\n\t\t\t\tbreak;\n\t\t\tcase 'ArrowDown':\n\t\t\tcase 'ArrowRight':\n\t\t\t\ttargetRadio = radios[currentIndex < radios.length - 1 ? currentIndex + 1 : 0];\n\t\t\t\tbreak;\n\t\t\tdefault:\n\t\t\t\treturn;\n\t\t}\n\n\t\tevent.preventDefault();\n\n\t\t// A lone enabled option would otherwise wrap onto itself and re-fire a click.\n\t\tif (radios.length < 2) return;\n\n\t\t// In a readonly group this moves focus only — click() is a no-op there.\n\t\ttargetRadio?.focus();\n\t\ttargetRadio?.click();\n\t};\n\n\tformResetCallback() {\n\t\tthis.checked = this._initialChecked;\n\t\tthis.control.checked = this._initialChecked;\n\t\tthis.internals.setFormValue(this.checked ? this.value ?? 'on' : null);\n\t\tthis._updateGroupValidation();\n\t}\n\n\tprivate _uncheckSiblings() {\n\t\tif (!this.name) return;\n\t\tconst radios: Array<SDSRadio> = this._getGroupRadios();\n\n\t\tfor (const radio of radios) {\n\t\t\tif (radio !== this && radio.checked) {\n\t\t\t\tradio.checked = false;\n\t\t\t\tradio.internals.setFormValue(null);\n\t\t\t}\n\t\t}\n\t}\n\n\t// Focus lands on the host, so these listen there. The guard skips the CustomEvent that\n\t// dispatchSheriffEvent re-fires under the same name, which would otherwise recurse.\n\tprivate readonly _handleFocus = (event: Event) => {\n\t\tif (event instanceof CustomEvent) return;\n\t\tevent.stopImmediatePropagation();\n\t\tthis.dispatchSheriffEvent('focus');\n\t};\n\n\tprivate readonly _handleBlur = (event: Event) => {\n\t\tif (event instanceof CustomEvent) return;\n\t\tevent.stopImmediatePropagation();\n\t\tthis.dispatchSheriffEvent('blur');\n\t};\n\n\t// The host is the radio, so these three bypass SDSDelegateInteractionMixin, which would\n\t// send them on to the inner input.\n\toverride focus(options?: FocusOptions): void {\n\t\tif (this.disabled) return;\n\t\tHTMLElement.prototype.focus.call(this, options);\n\t}\n\n\toverride blur(): void {\n\t\tHTMLElement.prototype.blur.call(this);\n\t}\n\n\toverride click(): void {\n\t\tif (this.disabled || this.readOnly) return;\n\t\tHTMLElement.prototype.click.call(this);\n\t}\n\n\tget type(): string {\n\t\treturn 'radio';\n\t}\n\n\tget validity() {\n\t\treturn this.internals.validity;\n\t}\n\n\tget validationMessage() {\n\t\treturn this.internals.validationMessage;\n\t}\n\n\tget willValidate() {\n\t\treturn this.internals.willValidate;\n\t}\n\n\tcheckValidity(): boolean {\n\t\treturn this.internals.checkValidity();\n\t}\n\n\treportValidity(): boolean {\n\t\treturn this.internals.reportValidity();\n\t}\n\n\tsetCustomValidity(message: string): void {\n\t\tthis.internals.setValidity({ customError: !!message }, message);\n\t}\n\n\toverride formDisabledCallback(disabled: boolean): void {\n\t\tthis._settingDisabledFromParent = true;\n\t\tthis.disabled = disabled;\n\t\tthis._settingDisabledFromParent = false;\n\t\tif (this.control) this.control.disabled = disabled;\n\t}\n\n\tprivate readonly _handleLabelSlotChange = (event: Event) => {\n\t\tconst assigned = (event.target as HTMLSlotElement).assignedNodes();\n\t\tthis._hasSlottedLabel = assigned.length > 0;\n\t\tthis._slottedLabelText = assigned\n\t\t\t.map((node) => node.textContent ?? '')\n\t\t\t.join('')\n\t\t\t.trim();\n\t};\n\n\toverride render() {\n\t\tconst radioClasses = {\n\t\t\t'sds-radio': true,\n\t\t\t'sds-radio--error': Boolean(this.error),\n\t\t};\n\n\t\tconst showLabel = this._hasSlottedLabel || Boolean(this.label);\n\n\t\tconst inputClasses = {\n\t\t\t'sds-radio__input': true,\n\t\t\t'sds-radio__input--error': Boolean(this.error),\n\t\t};\n\n\t\treturn html`\n\t\t\t<div class=\"${classMap(radioClasses)}\">\n\t\t\t\t<input\n\t\t\t\t\tid=\"control\"\n\t\t\t\t\ttype=\"radio\"\n\t\t\t\t\tname=\"${ifDefined(this.name)}\"\n\t\t\t\t\tvalue=\"${ifDefined(this.value)}\"\n\t\t\t\t\t?checked=\"${this.checked ?? false}\"\n\t\t\t\t\t.checked=\"${this.checked ?? false}\"\n\t\t\t\t\t?disabled=\"${this.disabled ?? false}\"\n\t\t\t\t\t.disabled=\"${this.disabled ?? false}\"\n\t\t\t\t\t?required=\"${this.required}\"\n\t\t\t\t\t?readonly=\"${this.readOnly}\"\n\t\t\t\t\tinert\n\t\t\t\t\tclass=\"${classMap(inputClasses)}\"\n\t\t\t\t/>\n\t\t\t\t<label class=\"sds-radio__label\" ?hidden=\"${!showLabel}\">\n\t\t\t\t\t<slot name=\"label\" @slotchange=\"${this._handleLabelSlotChange}\">${this.label}</slot>\n\t\t\t\t</label>\n\t\t\t\t${this.helpText ? html`<span id=\"help-text\" class=\"sds-radio__help-text\">${this.helpText}</span>` : nothing}\n\t\t\t</div>\n\t\t`;\n\t}\n}\n\ndeclare global {\n\tinterface HTMLElementTagNameMap {\n\t\t'sds-radio': SDSRadio;\n\t}\n}\n"]}
@@ -40,6 +40,7 @@ export const styles = css `
40
40
 
41
41
  .sds-radio {
42
42
  display: grid;
43
+ cursor: pointer;
43
44
  font-family: var(--_sds-radio-font-family);
44
45
  gap: var(--_sds-radio-block-gap) var(--_sds-radio-inline-gap);
45
46
  grid-template-areas: var(--_sds-radio-grid-template-areas);
@@ -51,13 +52,22 @@ export const styles = css `
51
52
  pointer-events: none;
52
53
  opacity: var(--_sds-radio-disabled-opacity);
53
54
  }
55
+ }
54
56
 
55
- &:has(:focus-visible) {
56
- box-shadow: 0 0 0 var(--_sds-radio-focus-spacing) var(--_sds-radio-focus-color-inner);
57
- outline: var(--_sds-radio-focus-outline-size) solid var(--_sds-radio-focus-color-outer);
58
- outline-offset: var(--_sds-radio-focus-spacing);
59
- border-radius: var(--_sds-radio-focus-radius);
60
- }
57
+ :host([readonly]) .sds-radio {
58
+ cursor: default;
59
+ }
60
+
61
+ /* The host carries role="radio" and takes focus, so the ring keys off it. */
62
+ :host(:focus-visible) {
63
+ outline: none;
64
+ }
65
+
66
+ :host(:focus-visible) .sds-radio {
67
+ box-shadow: 0 0 0 var(--_sds-radio-focus-spacing) var(--_sds-radio-focus-color-inner);
68
+ outline: var(--_sds-radio-focus-outline-size) solid var(--_sds-radio-focus-color-outer);
69
+ outline-offset: var(--_sds-radio-focus-spacing);
70
+ border-radius: var(--_sds-radio-focus-radius);
61
71
  }
62
72
 
63
73
  .sds-radio--error {
@@ -128,30 +138,26 @@ export const styles = css `
128
138
  }
129
139
  }
130
140
 
131
- &:hover {
141
+ /*
142
+ * The input is inert so it stays out of the accessibility tree, which also excludes
143
+ * it from hit testing — it never matches :hover or :active itself. Both are driven
144
+ * from the host instead, so hovering the label highlights the control too, the same
145
+ * way clicking the label already selects it.
146
+ */
147
+ :host(:hover) &:not([readonly]) {
132
148
  --_sds-radio-input-background-color: var(--sds-radio-input-background-color, var(--sds-color-surface-default, var(--sds-color-neutral-surface-default)));
133
149
  --_sds-radio-input-border-color: var(--sds-radio-input-border-color, var(--sds-color-action-hover, var(--sds-color-main-action-hover)));
150
+ }
134
151
 
135
- &[checked] {
136
- --_sds-radio-input-background-color: var(--sds-radio-input-background-color, var(--sds-color-action-hover, var(--sds-color-main-action-hover)));
137
- --_sds-radio-input-border-color: var(--sds-radio-input-border-color, var(--sds-color-action-hover, var(--sds-color-main-action-hover)));
138
- --_sds-radio-input-dot-color: var(--sds-radio-input-dot-color, var(--sds-color-surface-default, var(--sds-color-neutral-surface-default)));
139
- }
152
+ :host(:hover) &[checked]:not([readonly]) {
153
+ --_sds-radio-input-background-color: var(--sds-radio-input-background-color, var(--sds-color-action-hover, var(--sds-color-main-action-hover)));
154
+ --_sds-radio-input-border-color: var(--sds-radio-input-border-color, var(--sds-color-action-hover, var(--sds-color-main-action-hover)));
155
+ --_sds-radio-input-dot-color: var(--sds-radio-input-dot-color, var(--sds-color-surface-default, var(--sds-color-neutral-surface-default)));
140
156
  }
141
157
 
142
- &:active:not([readonly], [checked]) {
158
+ :host(:active) &:not([readonly], [checked]) {
143
159
  --_sds-radio-input-background-color: var(--sds-radio-input-background-color, var(--sds-color-surface-default, var(--sds-color-neutral-surface-default)));
144
160
  --_sds-radio-input-border-color: var(--sds-radio-input-border-color, var(--sds-color-action-active, var(--sds-color-main-action-active)));
145
-
146
- &[checked] {
147
- --_sds-radio-input-background-color: var(--sds-radio-input-background-color, var(--sds-color-action-active, var(--sds-color-main-action-active)));
148
- --_sds-radio-input-border-color: var(--sds-radio-input-border-color, var(--sds-color-action-active, var(--sds-color-main-action-active)));
149
- --_sds-radio-input-dot-color: var(--sds-radio-input-dot-color, var(--sds-color-surface-default, var(--sds-color-neutral-surface-default)));
150
- }
151
- }
152
-
153
- &:focus-visible {
154
- outline: none;
155
161
  }
156
162
 
157
163
  &.sds-radio__input--error {
@@ -163,26 +169,20 @@ export const styles = css `
163
169
  --_sds-radio-input-dot-color: var(--sds-radio-input-dot-color, var(--sds-color-alert-danger-action-contrast-default));
164
170
  }
165
171
 
166
- &:hover {
172
+ :host(:hover) &:not([readonly]) {
167
173
  --_sds-radio-input-background-color: var(--sds-radio-input-background-color, var(--sds-color-surface-default, var(--sds-color-neutral-surface-default)));
168
174
  --_sds-radio-input-border-color: var(--sds-radio-input-border-color, var(--sds-color-alert-danger-action-hover));
175
+ }
169
176
 
170
- &[checked] {
171
- --_sds-radio-input-background-color: var(--sds-radio-input-background-color, var(--sds-color-alert-danger-action-hover));
172
- --_sds-radio-input-border-color: var(--sds-radio-input-border-color, var(--sds-color-alert-danger-action-hover));
173
- --_sds-radio-input-dot-color: var(--sds-radio-input-dot-color, var(--sds-color-surface-default, var(--sds-color-neutral-surface-default)));
174
- }
177
+ :host(:hover) &[checked]:not([readonly]) {
178
+ --_sds-radio-input-background-color: var(--sds-radio-input-background-color, var(--sds-color-alert-danger-action-hover));
179
+ --_sds-radio-input-border-color: var(--sds-radio-input-border-color, var(--sds-color-alert-danger-action-hover));
180
+ --_sds-radio-input-dot-color: var(--sds-radio-input-dot-color, var(--sds-color-surface-default, var(--sds-color-neutral-surface-default)));
175
181
  }
176
182
 
177
- &:active:not([readonly], [checked]) {
183
+ :host(:active) &:not([readonly], [checked]) {
178
184
  --_sds-radio-input-background-color: var(--sds-radio-input-background-color, var(--sds-color-surface-default, var(--sds-color-neutral-surface-default)));
179
185
  --_sds-radio-input-border-color: var(--sds-radio-input-border-color, var(--sds-color-alert-danger-action-active));
180
-
181
- &[checked] {
182
- --_sds-radio-input-background-color: var(--sds-radio-input-background-color, var(--sds-color-alert-danger-action-active));
183
- --_sds-radio-input-border-color: var(--sds-radio-input-border-color, var(--sds-color-alert-danger-action-active));
184
- --_sds-radio-input-dot-color: var(--sds-radio-input-dot-color, var(--sds-color-surface-default, var(--sds-color-neutral-surface-default)));
185
- }
186
186
  }
187
187
  }
188
188
  }