@aurodesignsystem-dev/auro-formkit 0.0.0-pr1608.0 → 0.0.0-pr1608.2

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 (51) hide show
  1. package/components/checkbox/demo/accessibility.md +15 -4
  2. package/components/checkbox/demo/customize.min.js +40 -12
  3. package/components/checkbox/demo/getting-started.min.js +40 -12
  4. package/components/checkbox/demo/index.min.js +40 -12
  5. package/components/checkbox/dist/auro-checkbox-group.d.ts +19 -0
  6. package/components/checkbox/dist/index.js +40 -12
  7. package/components/checkbox/dist/registered.js +40 -12
  8. package/components/combobox/demo/customize.min.js +46 -4
  9. package/components/combobox/demo/getting-started.min.js +46 -4
  10. package/components/combobox/demo/index.min.js +46 -4
  11. package/components/combobox/dist/index.js +46 -4
  12. package/components/combobox/dist/registered.js +46 -4
  13. package/components/counter/demo/customize.min.js +339 -23
  14. package/components/counter/demo/getting-started.min.js +339 -23
  15. package/components/counter/demo/index.min.js +339 -23
  16. package/components/counter/dist/counterGroupKeyboardStrategy.d.ts +1 -0
  17. package/components/counter/dist/index.js +339 -23
  18. package/components/counter/dist/registered.js +339 -23
  19. package/components/datepicker/demo/customize.min.js +46 -4
  20. package/components/datepicker/demo/getting-started.min.js +46 -4
  21. package/components/datepicker/demo/index.min.js +46 -4
  22. package/components/datepicker/dist/index.js +46 -4
  23. package/components/datepicker/dist/registered.js +46 -4
  24. package/components/dropdown/demo/customize.min.js +44 -2
  25. package/components/dropdown/demo/getting-started.min.js +45 -3
  26. package/components/dropdown/demo/index.min.js +44 -2
  27. package/components/dropdown/dist/index.js +44 -2
  28. package/components/dropdown/dist/registered.js +44 -2
  29. package/components/form/demo/customize.min.js +556 -61
  30. package/components/form/demo/getting-started.min.js +556 -61
  31. package/components/form/demo/index.min.js +556 -61
  32. package/components/form/demo/registerDemoDeps.min.js +556 -61
  33. package/components/input/demo/customize.min.js +1 -1
  34. package/components/input/demo/getting-started.min.js +1 -1
  35. package/components/input/demo/index.min.js +1 -1
  36. package/components/input/dist/index.js +1 -1
  37. package/components/input/dist/registered.js +1 -1
  38. package/components/radio/demo/accessibility.md +15 -4
  39. package/components/radio/demo/customize.min.js +39 -14
  40. package/components/radio/demo/getting-started.min.js +39 -14
  41. package/components/radio/demo/index.min.js +39 -14
  42. package/components/radio/dist/auro-radio-group.d.ts +18 -0
  43. package/components/radio/dist/index.js +39 -14
  44. package/components/radio/dist/registered.js +39 -14
  45. package/components/select/demo/customize.min.js +45 -3
  46. package/components/select/demo/getting-started.min.js +45 -3
  47. package/components/select/demo/index.min.js +45 -3
  48. package/components/select/dist/index.js +45 -3
  49. package/components/select/dist/registered.js +45 -3
  50. package/custom-elements.json +1814 -1768
  51. package/package.json +3 -3
@@ -8,12 +8,13 @@ For keyboard interaction details, see the <auro-hyperlink href="keyboard-behavio
8
8
 
9
9
  <auro-header level="2" id="ariaRolesAndAttributes">ARIA Roles and Attributes</auro-header>
10
10
  <auro-header level="3" id="checkboxGroup">Checkbox Group</auro-header>
11
- The `<auro-checkbox-group>` element uses a `<fieldset>` with a `<legend>` internally, providing native grouping semantics:
11
+ The `<auro-checkbox-group>` element uses a `<fieldset>` with a `<legend>` internally, providing native grouping semantics. These attributes are applied to that shadow-DOM `<fieldset>`, **not** to the `<auro-checkbox-group>` host element:
12
12
 
13
13
  | Attribute | Value | Description |
14
14
  |---|---|---|
15
- | `role` | `group` (implicit via `fieldset`) | Groups related checkboxes together. |
16
- | `aria-invalid` | `true` / `false` | Reflects whether the group is currently in an invalid state. |
15
+ | `role` | `group` (implicit via `fieldset`) | Groups related checkboxes together. There is no ARIA `checkboxgroup` role, so the `<fieldset>`'s implicit `group` role is used as-is. |
16
+ | `aria-invalid` | `true` | Present only while the group is in an invalid state. The attribute is **omitted entirely** when the group is valid — it is never set to `false`. |
17
+ | `aria-describedby` | id reference | Points at the `id` of the group's help-text/error element, so assistive technology can associate the message with the group on demand rather than relying only on the one-time live-region announcement. |
17
18
 
18
19
  <auro-header level="3" id="checkboxElement">Checkbox</auro-header>
19
20
  Each `<auro-checkbox>` renders a native `<input type="checkbox">` inside its shadow DOM:
@@ -23,12 +24,22 @@ Each `<auro-checkbox>` renders a native `<input type="checkbox">` inside its sha
23
24
  | `type` | `checkbox` | Native checkbox input type. |
24
25
  | `aria-checked` | `true` / `false` | Reflects the checked state of the checkbox. |
25
26
  | `aria-disabled` | `true` / `false` | Indicates whether the checkbox is disabled. |
27
+ | `aria-invalid` | `true` | Mirrored onto each checkbox from the group while the group is invalid, and removed when it becomes valid. Omitted rather than set to `false`. |
28
+
29
+ <auro-header level="4" id="invalidStatePlacement">Why the invalid state appears twice</auro-header>
30
+ While the group is invalid, `aria-invalid` is set on both the `<fieldset>` and every individual `<auro-checkbox>`. This is intentional: some assistive-technology and browser combinations announce a container's invalid state only when focus first enters the group, so mirroring the state onto each checkbox keeps it conveyed as focus moves through the options.
31
+
32
+ The `checkbox` role is in `aria-invalid`'s supported-role list in every ARIA version, so the per-checkbox placement is unambiguous. The group-level placement is worth one note: `aria-invalid` is a global attribute in ARIA 1.1, applicable to any role including `group`, but ARIA 1.2 deprecates that global use in favor of a supported-role list that does not include `group`. Keeping it on the `<fieldset>` is a deliberate choice — it is not a *prohibited* attribute for `group`, current axe-core resolves it as global and reports no violation, and it gives the group a real invalid signal that would otherwise be lost. This is covered by an automated axe assertion in the component's test suite so that a future change in tooling surfaces here rather than in a consumer's audit.
33
+
34
+ <auro-header level="4" id="attributePlacementNote">Attribute placement</auro-header>
35
+ `aria-invalid` is applied to the internal `<fieldset>`, not to the `<auro-checkbox-group>` host element. Do not write CSS selectors or test assertions against `auro-checkbox-group[aria-invalid]`; query the internal fieldset or read the `validity` property instead.
26
36
 
27
37
  <auro-header level="2" id="screenReaderAnnouncements">Screen Reader Announcements</auro-header>
28
38
  - **Focus** — When focus moves to a checkbox, the screen reader announces the checkbox label, its checked/unchecked state, and role ("checkbox").
29
39
  - **State change** — Toggling the checkbox announces the new state ("checked" or "unchecked").
30
40
  - **Group context** — The legend text provides group context when navigating between groups.
31
- - **Error** — When validation fails, the error message is announced to screen reader users.
41
+ - **Error** — When validation fails, the error message is announced immediately via the help text's `role="alert"` live region, and stays discoverable afterward through the group's `aria-describedby` association.
42
+ - **Invalid state** — While the group is invalid, entering it or moving between its checkboxes conveys the invalid state.
32
43
 
33
44
  <auro-header level="2" id="accessibleLabels">Accessible Labels</auro-header>
34
45
  - The `legend` slot content provides the accessible group label via the native `<legend>` element.
@@ -1300,7 +1300,7 @@ class AuroHelpText extends i$2 {
1300
1300
  }
1301
1301
  }
1302
1302
 
1303
- var formkitVersion = '202609021913';
1303
+ var formkitVersion = '202609030018';
1304
1304
 
1305
1305
  // Copyright (c) 2026 Alaska Airlines. All rights reserved. Licensed under the Apache-2.0 license
1306
1306
  // See LICENSE in the project root for license information.
@@ -1633,6 +1633,42 @@ class AuroCheckboxGroup extends i$2 {
1633
1633
  this.handlePreselectedItems();
1634
1634
 
1635
1635
  this.validate();
1636
+ this.syncCheckboxValidity();
1637
+ }
1638
+
1639
+ /**
1640
+ * Whether the group is currently in an invalid state.
1641
+ * `validity` — not `error` — is the authoritative source: `validate()` resolves the
1642
+ * `error` attribute to `validity = 'customError'`, so `error` is already covered here.
1643
+ * Single definition of "invalid" for the whole component, consumed by `render()` and
1644
+ * `syncCheckboxValidity()` so the fieldset and its children can never disagree.
1645
+ * @private
1646
+ * @returns {boolean}
1647
+ */
1648
+ get isInvalid() {
1649
+ return Boolean(this.validity && this.validity !== 'valid');
1650
+ }
1651
+
1652
+ /**
1653
+ * Method for mirroring the group's invalid state onto each checkbox.
1654
+ * Has to be re-applied from `handleItems()` as well, because a slot change can happen
1655
+ * without `validity` itself changing — a checkbox slotted into an already-invalid
1656
+ * group would otherwise be missed.
1657
+ * @private
1658
+ * @returns {void}
1659
+ */
1660
+ syncCheckboxValidity() {
1661
+ const invalid = this.isInvalid;
1662
+
1663
+ this.checkboxes.forEach((el) => {
1664
+ if (invalid) {
1665
+ el.setAttribute('error', true);
1666
+ el.setAttribute('aria-invalid', 'true');
1667
+ } else {
1668
+ el.removeAttribute('error');
1669
+ el.removeAttribute('aria-invalid');
1670
+ }
1671
+ });
1636
1672
  }
1637
1673
 
1638
1674
  /**
@@ -1664,15 +1700,7 @@ class AuroCheckboxGroup extends i$2 {
1664
1700
  }
1665
1701
 
1666
1702
  if (changedProperties.has('validity')) {
1667
- this.checkboxes.forEach((el) => {
1668
- if (this.validity && this.validity !== 'valid') {
1669
- el.setAttribute('error', true);
1670
- el.setAttribute('aria-invalid', 'true');
1671
- } else {
1672
- el.removeAttribute('error');
1673
- el.removeAttribute('aria-invalid');
1674
- }
1675
- });
1703
+ this.syncCheckboxValidity();
1676
1704
  }
1677
1705
 
1678
1706
  if (changedProperties.has('required')) {
@@ -1716,7 +1744,7 @@ class AuroCheckboxGroup extends i$2 {
1716
1744
  return u`
1717
1745
  <fieldset
1718
1746
  class="${e(groupClasses)}"
1719
- aria-invalid="${o$1(this.validity && this.validity !== 'valid' ? 'true' : undefined)}"
1747
+ aria-invalid="${o$1(this.isInvalid ? 'true' : undefined)}"
1720
1748
  aria-describedby="${this.uniqueId}"
1721
1749
  >
1722
1750
  <legend>
@@ -1726,7 +1754,7 @@ class AuroCheckboxGroup extends i$2 {
1726
1754
  <slot @slotchange=${this.handleItems}></slot>
1727
1755
  </fieldset>
1728
1756
 
1729
- ${!this.validity || this.validity === undefined || this.validity === 'valid'
1757
+ ${!this.isInvalid
1730
1758
  ? u`
1731
1759
  <${this.helpTextTag} id="${this.uniqueId}" part="helpText" appearance="${this.onDark ? 'inverse' : this.appearance}">
1732
1760
  <slot name="helpText"></slot>
@@ -1300,7 +1300,7 @@ class AuroHelpText extends i$2 {
1300
1300
  }
1301
1301
  }
1302
1302
 
1303
- var formkitVersion = '202609021913';
1303
+ var formkitVersion = '202609030018';
1304
1304
 
1305
1305
  // Copyright (c) 2026 Alaska Airlines. All rights reserved. Licensed under the Apache-2.0 license
1306
1306
  // See LICENSE in the project root for license information.
@@ -1633,6 +1633,42 @@ class AuroCheckboxGroup extends i$2 {
1633
1633
  this.handlePreselectedItems();
1634
1634
 
1635
1635
  this.validate();
1636
+ this.syncCheckboxValidity();
1637
+ }
1638
+
1639
+ /**
1640
+ * Whether the group is currently in an invalid state.
1641
+ * `validity` — not `error` — is the authoritative source: `validate()` resolves the
1642
+ * `error` attribute to `validity = 'customError'`, so `error` is already covered here.
1643
+ * Single definition of "invalid" for the whole component, consumed by `render()` and
1644
+ * `syncCheckboxValidity()` so the fieldset and its children can never disagree.
1645
+ * @private
1646
+ * @returns {boolean}
1647
+ */
1648
+ get isInvalid() {
1649
+ return Boolean(this.validity && this.validity !== 'valid');
1650
+ }
1651
+
1652
+ /**
1653
+ * Method for mirroring the group's invalid state onto each checkbox.
1654
+ * Has to be re-applied from `handleItems()` as well, because a slot change can happen
1655
+ * without `validity` itself changing — a checkbox slotted into an already-invalid
1656
+ * group would otherwise be missed.
1657
+ * @private
1658
+ * @returns {void}
1659
+ */
1660
+ syncCheckboxValidity() {
1661
+ const invalid = this.isInvalid;
1662
+
1663
+ this.checkboxes.forEach((el) => {
1664
+ if (invalid) {
1665
+ el.setAttribute('error', true);
1666
+ el.setAttribute('aria-invalid', 'true');
1667
+ } else {
1668
+ el.removeAttribute('error');
1669
+ el.removeAttribute('aria-invalid');
1670
+ }
1671
+ });
1636
1672
  }
1637
1673
 
1638
1674
  /**
@@ -1664,15 +1700,7 @@ class AuroCheckboxGroup extends i$2 {
1664
1700
  }
1665
1701
 
1666
1702
  if (changedProperties.has('validity')) {
1667
- this.checkboxes.forEach((el) => {
1668
- if (this.validity && this.validity !== 'valid') {
1669
- el.setAttribute('error', true);
1670
- el.setAttribute('aria-invalid', 'true');
1671
- } else {
1672
- el.removeAttribute('error');
1673
- el.removeAttribute('aria-invalid');
1674
- }
1675
- });
1703
+ this.syncCheckboxValidity();
1676
1704
  }
1677
1705
 
1678
1706
  if (changedProperties.has('required')) {
@@ -1716,7 +1744,7 @@ class AuroCheckboxGroup extends i$2 {
1716
1744
  return u`
1717
1745
  <fieldset
1718
1746
  class="${e(groupClasses)}"
1719
- aria-invalid="${o$1(this.validity && this.validity !== 'valid' ? 'true' : undefined)}"
1747
+ aria-invalid="${o$1(this.isInvalid ? 'true' : undefined)}"
1720
1748
  aria-describedby="${this.uniqueId}"
1721
1749
  >
1722
1750
  <legend>
@@ -1726,7 +1754,7 @@ class AuroCheckboxGroup extends i$2 {
1726
1754
  <slot @slotchange=${this.handleItems}></slot>
1727
1755
  </fieldset>
1728
1756
 
1729
- ${!this.validity || this.validity === undefined || this.validity === 'valid'
1757
+ ${!this.isInvalid
1730
1758
  ? u`
1731
1759
  <${this.helpTextTag} id="${this.uniqueId}" part="helpText" appearance="${this.onDark ? 'inverse' : this.appearance}">
1732
1760
  <slot name="helpText"></slot>
@@ -1300,7 +1300,7 @@ class AuroHelpText extends i$2 {
1300
1300
  }
1301
1301
  }
1302
1302
 
1303
- var formkitVersion = '202609021913';
1303
+ var formkitVersion = '202609030018';
1304
1304
 
1305
1305
  // Copyright (c) 2026 Alaska Airlines. All rights reserved. Licensed under the Apache-2.0 license
1306
1306
  // See LICENSE in the project root for license information.
@@ -1633,6 +1633,42 @@ class AuroCheckboxGroup extends i$2 {
1633
1633
  this.handlePreselectedItems();
1634
1634
 
1635
1635
  this.validate();
1636
+ this.syncCheckboxValidity();
1637
+ }
1638
+
1639
+ /**
1640
+ * Whether the group is currently in an invalid state.
1641
+ * `validity` — not `error` — is the authoritative source: `validate()` resolves the
1642
+ * `error` attribute to `validity = 'customError'`, so `error` is already covered here.
1643
+ * Single definition of "invalid" for the whole component, consumed by `render()` and
1644
+ * `syncCheckboxValidity()` so the fieldset and its children can never disagree.
1645
+ * @private
1646
+ * @returns {boolean}
1647
+ */
1648
+ get isInvalid() {
1649
+ return Boolean(this.validity && this.validity !== 'valid');
1650
+ }
1651
+
1652
+ /**
1653
+ * Method for mirroring the group's invalid state onto each checkbox.
1654
+ * Has to be re-applied from `handleItems()` as well, because a slot change can happen
1655
+ * without `validity` itself changing — a checkbox slotted into an already-invalid
1656
+ * group would otherwise be missed.
1657
+ * @private
1658
+ * @returns {void}
1659
+ */
1660
+ syncCheckboxValidity() {
1661
+ const invalid = this.isInvalid;
1662
+
1663
+ this.checkboxes.forEach((el) => {
1664
+ if (invalid) {
1665
+ el.setAttribute('error', true);
1666
+ el.setAttribute('aria-invalid', 'true');
1667
+ } else {
1668
+ el.removeAttribute('error');
1669
+ el.removeAttribute('aria-invalid');
1670
+ }
1671
+ });
1636
1672
  }
1637
1673
 
1638
1674
  /**
@@ -1664,15 +1700,7 @@ class AuroCheckboxGroup extends i$2 {
1664
1700
  }
1665
1701
 
1666
1702
  if (changedProperties.has('validity')) {
1667
- this.checkboxes.forEach((el) => {
1668
- if (this.validity && this.validity !== 'valid') {
1669
- el.setAttribute('error', true);
1670
- el.setAttribute('aria-invalid', 'true');
1671
- } else {
1672
- el.removeAttribute('error');
1673
- el.removeAttribute('aria-invalid');
1674
- }
1675
- });
1703
+ this.syncCheckboxValidity();
1676
1704
  }
1677
1705
 
1678
1706
  if (changedProperties.has('required')) {
@@ -1716,7 +1744,7 @@ class AuroCheckboxGroup extends i$2 {
1716
1744
  return u`
1717
1745
  <fieldset
1718
1746
  class="${e(groupClasses)}"
1719
- aria-invalid="${o$1(this.validity && this.validity !== 'valid' ? 'true' : undefined)}"
1747
+ aria-invalid="${o$1(this.isInvalid ? 'true' : undefined)}"
1720
1748
  aria-describedby="${this.uniqueId}"
1721
1749
  >
1722
1750
  <legend>
@@ -1726,7 +1754,7 @@ class AuroCheckboxGroup extends i$2 {
1726
1754
  <slot @slotchange=${this.handleItems}></slot>
1727
1755
  </fieldset>
1728
1756
 
1729
- ${!this.validity || this.validity === undefined || this.validity === 'valid'
1757
+ ${!this.isInvalid
1730
1758
  ? u`
1731
1759
  <${this.helpTextTag} id="${this.uniqueId}" part="helpText" appearance="${this.onDark ? 'inverse' : this.appearance}">
1732
1760
  <slot name="helpText"></slot>
@@ -168,6 +168,25 @@ export class AuroCheckboxGroup extends LitElement {
168
168
  */
169
169
  private handleItems;
170
170
  checkboxes: Element[] | undefined;
171
+ /**
172
+ * Whether the group is currently in an invalid state.
173
+ * `validity` — not `error` — is the authoritative source: `validate()` resolves the
174
+ * `error` attribute to `validity = 'customError'`, so `error` is already covered here.
175
+ * Single definition of "invalid" for the whole component, consumed by `render()` and
176
+ * `syncCheckboxValidity()` so the fieldset and its children can never disagree.
177
+ * @private
178
+ * @returns {boolean}
179
+ */
180
+ private get isInvalid();
181
+ /**
182
+ * Method for mirroring the group's invalid state onto each checkbox.
183
+ * Has to be re-applied from `handleItems()` as well, because a slot change can happen
184
+ * without `validity` itself changing — a checkbox slotted into an already-invalid
185
+ * group would otherwise be missed.
186
+ * @private
187
+ * @returns {void}
188
+ */
189
+ private syncCheckboxValidity;
171
190
  /**
172
191
  * Resets component to initial state.
173
192
  * @returns {void}
@@ -1253,7 +1253,7 @@ class AuroHelpText extends LitElement {
1253
1253
  }
1254
1254
  }
1255
1255
 
1256
- var formkitVersion = '202609021913';
1256
+ var formkitVersion = '202609030018';
1257
1257
 
1258
1258
  // Copyright (c) 2026 Alaska Airlines. All rights reserved. Licensed under the Apache-2.0 license
1259
1259
  // See LICENSE in the project root for license information.
@@ -1586,6 +1586,42 @@ class AuroCheckboxGroup extends LitElement {
1586
1586
  this.handlePreselectedItems();
1587
1587
 
1588
1588
  this.validate();
1589
+ this.syncCheckboxValidity();
1590
+ }
1591
+
1592
+ /**
1593
+ * Whether the group is currently in an invalid state.
1594
+ * `validity` — not `error` — is the authoritative source: `validate()` resolves the
1595
+ * `error` attribute to `validity = 'customError'`, so `error` is already covered here.
1596
+ * Single definition of "invalid" for the whole component, consumed by `render()` and
1597
+ * `syncCheckboxValidity()` so the fieldset and its children can never disagree.
1598
+ * @private
1599
+ * @returns {boolean}
1600
+ */
1601
+ get isInvalid() {
1602
+ return Boolean(this.validity && this.validity !== 'valid');
1603
+ }
1604
+
1605
+ /**
1606
+ * Method for mirroring the group's invalid state onto each checkbox.
1607
+ * Has to be re-applied from `handleItems()` as well, because a slot change can happen
1608
+ * without `validity` itself changing — a checkbox slotted into an already-invalid
1609
+ * group would otherwise be missed.
1610
+ * @private
1611
+ * @returns {void}
1612
+ */
1613
+ syncCheckboxValidity() {
1614
+ const invalid = this.isInvalid;
1615
+
1616
+ this.checkboxes.forEach((el) => {
1617
+ if (invalid) {
1618
+ el.setAttribute('error', true);
1619
+ el.setAttribute('aria-invalid', 'true');
1620
+ } else {
1621
+ el.removeAttribute('error');
1622
+ el.removeAttribute('aria-invalid');
1623
+ }
1624
+ });
1589
1625
  }
1590
1626
 
1591
1627
  /**
@@ -1617,15 +1653,7 @@ class AuroCheckboxGroup extends LitElement {
1617
1653
  }
1618
1654
 
1619
1655
  if (changedProperties.has('validity')) {
1620
- this.checkboxes.forEach((el) => {
1621
- if (this.validity && this.validity !== 'valid') {
1622
- el.setAttribute('error', true);
1623
- el.setAttribute('aria-invalid', 'true');
1624
- } else {
1625
- el.removeAttribute('error');
1626
- el.removeAttribute('aria-invalid');
1627
- }
1628
- });
1656
+ this.syncCheckboxValidity();
1629
1657
  }
1630
1658
 
1631
1659
  if (changedProperties.has('required')) {
@@ -1669,7 +1697,7 @@ class AuroCheckboxGroup extends LitElement {
1669
1697
  return html$1`
1670
1698
  <fieldset
1671
1699
  class="${classMap(groupClasses)}"
1672
- aria-invalid="${ifDefined(this.validity && this.validity !== 'valid' ? 'true' : undefined)}"
1700
+ aria-invalid="${ifDefined(this.isInvalid ? 'true' : undefined)}"
1673
1701
  aria-describedby="${this.uniqueId}"
1674
1702
  >
1675
1703
  <legend>
@@ -1679,7 +1707,7 @@ class AuroCheckboxGroup extends LitElement {
1679
1707
  <slot @slotchange=${this.handleItems}></slot>
1680
1708
  </fieldset>
1681
1709
 
1682
- ${!this.validity || this.validity === undefined || this.validity === 'valid'
1710
+ ${!this.isInvalid
1683
1711
  ? html$1`
1684
1712
  <${this.helpTextTag} id="${this.uniqueId}" part="helpText" appearance="${this.onDark ? 'inverse' : this.appearance}">
1685
1713
  <slot name="helpText"></slot>
@@ -1253,7 +1253,7 @@ class AuroHelpText extends LitElement {
1253
1253
  }
1254
1254
  }
1255
1255
 
1256
- var formkitVersion = '202609021913';
1256
+ var formkitVersion = '202609030018';
1257
1257
 
1258
1258
  // Copyright (c) 2026 Alaska Airlines. All rights reserved. Licensed under the Apache-2.0 license
1259
1259
  // See LICENSE in the project root for license information.
@@ -1586,6 +1586,42 @@ class AuroCheckboxGroup extends LitElement {
1586
1586
  this.handlePreselectedItems();
1587
1587
 
1588
1588
  this.validate();
1589
+ this.syncCheckboxValidity();
1590
+ }
1591
+
1592
+ /**
1593
+ * Whether the group is currently in an invalid state.
1594
+ * `validity` — not `error` — is the authoritative source: `validate()` resolves the
1595
+ * `error` attribute to `validity = 'customError'`, so `error` is already covered here.
1596
+ * Single definition of "invalid" for the whole component, consumed by `render()` and
1597
+ * `syncCheckboxValidity()` so the fieldset and its children can never disagree.
1598
+ * @private
1599
+ * @returns {boolean}
1600
+ */
1601
+ get isInvalid() {
1602
+ return Boolean(this.validity && this.validity !== 'valid');
1603
+ }
1604
+
1605
+ /**
1606
+ * Method for mirroring the group's invalid state onto each checkbox.
1607
+ * Has to be re-applied from `handleItems()` as well, because a slot change can happen
1608
+ * without `validity` itself changing — a checkbox slotted into an already-invalid
1609
+ * group would otherwise be missed.
1610
+ * @private
1611
+ * @returns {void}
1612
+ */
1613
+ syncCheckboxValidity() {
1614
+ const invalid = this.isInvalid;
1615
+
1616
+ this.checkboxes.forEach((el) => {
1617
+ if (invalid) {
1618
+ el.setAttribute('error', true);
1619
+ el.setAttribute('aria-invalid', 'true');
1620
+ } else {
1621
+ el.removeAttribute('error');
1622
+ el.removeAttribute('aria-invalid');
1623
+ }
1624
+ });
1589
1625
  }
1590
1626
 
1591
1627
  /**
@@ -1617,15 +1653,7 @@ class AuroCheckboxGroup extends LitElement {
1617
1653
  }
1618
1654
 
1619
1655
  if (changedProperties.has('validity')) {
1620
- this.checkboxes.forEach((el) => {
1621
- if (this.validity && this.validity !== 'valid') {
1622
- el.setAttribute('error', true);
1623
- el.setAttribute('aria-invalid', 'true');
1624
- } else {
1625
- el.removeAttribute('error');
1626
- el.removeAttribute('aria-invalid');
1627
- }
1628
- });
1656
+ this.syncCheckboxValidity();
1629
1657
  }
1630
1658
 
1631
1659
  if (changedProperties.has('required')) {
@@ -1669,7 +1697,7 @@ class AuroCheckboxGroup extends LitElement {
1669
1697
  return html$1`
1670
1698
  <fieldset
1671
1699
  class="${classMap(groupClasses)}"
1672
- aria-invalid="${ifDefined(this.validity && this.validity !== 'valid' ? 'true' : undefined)}"
1700
+ aria-invalid="${ifDefined(this.isInvalid ? 'true' : undefined)}"
1673
1701
  aria-describedby="${this.uniqueId}"
1674
1702
  >
1675
1703
  <legend>
@@ -1679,7 +1707,7 @@ class AuroCheckboxGroup extends LitElement {
1679
1707
  <slot @slotchange=${this.handleItems}></slot>
1680
1708
  </fieldset>
1681
1709
 
1682
- ${!this.validity || this.validity === undefined || this.validity === 'valid'
1710
+ ${!this.isInvalid
1683
1711
  ? html$1`
1684
1712
  <${this.helpTextTag} id="${this.uniqueId}" part="helpText" appearance="${this.onDark ? 'inverse' : this.appearance}">
1685
1713
  <slot name="helpText"></slot>
@@ -3003,6 +3003,48 @@ const computePosition = (reference, floating, options) => {
3003
3003
  });
3004
3004
  };
3005
3005
 
3006
+ /**
3007
+ * Generates a v4 UUID with a three-tier fallback for insecure contexts.
3008
+ *
3009
+ * Tier 1 (secure contexts): crypto.randomUUID() — native, fully random.
3010
+ * Tier 2 (insecure contexts): crypto.getRandomValues() — available on all
3011
+ * modern browsers regardless of secure-context status.
3012
+ * Tier 3 (last resort, no crypto API): new Date().getTime() — lower entropy,
3013
+ * but sufficient for element IDs where collision risk is negligible.
3014
+ *
3015
+ * See: https://w3c.github.io/webcrypto/#dom-crypto-randomuuid (secure-context restriction)
3016
+ */
3017
+ function generateUUID() {
3018
+ let uuid;
3019
+
3020
+ if (
3021
+ typeof crypto !== "undefined" &&
3022
+ typeof crypto.randomUUID === "function"
3023
+ ) {
3024
+ uuid = crypto.randomUUID();
3025
+ } else if (
3026
+ typeof crypto !== "undefined" &&
3027
+ typeof crypto.getRandomValues === "function"
3028
+ ) {
3029
+ const bytes = new Uint8Array(16);
3030
+ crypto.getRandomValues(bytes);
3031
+ bytes[6] = (bytes[6] & 0x0f) | 0x40;
3032
+ bytes[8] = (bytes[8] & 0x3f) | 0x80;
3033
+ const hex = Array.from(bytes).map((b) => b.toString(16).padStart(2, "0"));
3034
+ uuid = `${hex.slice(0, 4).join("")}-${hex.slice(4, 6).join("")}-${hex.slice(6, 8).join("")}-${hex.slice(8, 10).join("")}-${hex.slice(10).join("")}`;
3035
+ } else {
3036
+ let d = new Date().getTime();
3037
+ uuid = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
3038
+ const r = (d % 16) | 0;
3039
+ d = (d - r) / 16 || new Date().getTime();
3040
+ return (c === "x" ? r : (r & 0x3) | 0x8).toString(16);
3041
+ });
3042
+ }
3043
+
3044
+ // CSS selectors require IDs starting with a letter; replace a leading digit with 'a'.
3045
+ return /^[0-9]/.test(uuid) ? `a${uuid.slice(1)}` : uuid;
3046
+ }
3047
+
3006
3048
  /* eslint-disable line-comment-position, no-inline-comments */
3007
3049
 
3008
3050
 
@@ -4021,7 +4063,7 @@ class AuroFloatingUI {
4021
4063
 
4022
4064
  this.id = element.getAttribute("id");
4023
4065
  if (!this.id) {
4024
- this.id = window.crypto.randomUUID();
4066
+ this.id = generateUUID();
4025
4067
  element.setAttribute("id", this.id);
4026
4068
  }
4027
4069
 
@@ -5066,7 +5108,7 @@ let AuroHelpText$2 = class AuroHelpText extends i$3 {
5066
5108
  }
5067
5109
  };
5068
5110
 
5069
- var formkitVersion$2 = '202609021913';
5111
+ var formkitVersion$2 = '202609030018';
5070
5112
 
5071
5113
  /**
5072
5114
  * AuroElement is the shared base class for layout-aware Auro form components.
@@ -18935,7 +18977,7 @@ let AuroHelpText$1 = class AuroHelpText extends i$3 {
18935
18977
  }
18936
18978
  };
18937
18979
 
18938
- var formkitVersion$1 = '202609021913';
18980
+ var formkitVersion$1 = '202609030018';
18939
18981
 
18940
18982
  // Copyright (c) 2025 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
18941
18983
  // See LICENSE in the project root for license information.
@@ -20127,7 +20169,7 @@ class AuroBibtemplate extends i$3 {
20127
20169
  }
20128
20170
  }
20129
20171
 
20130
- var formkitVersion = '202609021913';
20172
+ var formkitVersion = '202609030018';
20131
20173
 
20132
20174
  var styleCss$3 = i$6`.util_displayInline{display:inline}.util_displayInlineBlock{display:inline-block}.util_displayBlock{display:block}.util_displayFlex{display:flex}.util_displayHidden{display:none}.util_displayHiddenVisually{position:absolute;overflow:hidden;clip:rect(1px, 1px, 1px, 1px);width:1px;height:1px;padding:0;border:0}:host{display:block;text-align:left}:host [auro-dropdown]{--ds-auro-dropdown-trigger-background-color: transparent}:host #inputInBib::part(wrapper){box-shadow:none}:host #inputInBib::part(accent-left){display:none}:host([layout*=classic]) [auro-input]{width:100%}:host([layout*=classic]) [auro-input]::part(helpText){display:none}:host([layout*=classic]) #slotHolder{display:none}`;
20133
20175
 
@@ -3003,6 +3003,48 @@ const computePosition = (reference, floating, options) => {
3003
3003
  });
3004
3004
  };
3005
3005
 
3006
+ /**
3007
+ * Generates a v4 UUID with a three-tier fallback for insecure contexts.
3008
+ *
3009
+ * Tier 1 (secure contexts): crypto.randomUUID() — native, fully random.
3010
+ * Tier 2 (insecure contexts): crypto.getRandomValues() — available on all
3011
+ * modern browsers regardless of secure-context status.
3012
+ * Tier 3 (last resort, no crypto API): new Date().getTime() — lower entropy,
3013
+ * but sufficient for element IDs where collision risk is negligible.
3014
+ *
3015
+ * See: https://w3c.github.io/webcrypto/#dom-crypto-randomuuid (secure-context restriction)
3016
+ */
3017
+ function generateUUID() {
3018
+ let uuid;
3019
+
3020
+ if (
3021
+ typeof crypto !== "undefined" &&
3022
+ typeof crypto.randomUUID === "function"
3023
+ ) {
3024
+ uuid = crypto.randomUUID();
3025
+ } else if (
3026
+ typeof crypto !== "undefined" &&
3027
+ typeof crypto.getRandomValues === "function"
3028
+ ) {
3029
+ const bytes = new Uint8Array(16);
3030
+ crypto.getRandomValues(bytes);
3031
+ bytes[6] = (bytes[6] & 0x0f) | 0x40;
3032
+ bytes[8] = (bytes[8] & 0x3f) | 0x80;
3033
+ const hex = Array.from(bytes).map((b) => b.toString(16).padStart(2, "0"));
3034
+ uuid = `${hex.slice(0, 4).join("")}-${hex.slice(4, 6).join("")}-${hex.slice(6, 8).join("")}-${hex.slice(8, 10).join("")}-${hex.slice(10).join("")}`;
3035
+ } else {
3036
+ let d = new Date().getTime();
3037
+ uuid = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, (c) => {
3038
+ const r = (d % 16) | 0;
3039
+ d = (d - r) / 16 || new Date().getTime();
3040
+ return (c === "x" ? r : (r & 0x3) | 0x8).toString(16);
3041
+ });
3042
+ }
3043
+
3044
+ // CSS selectors require IDs starting with a letter; replace a leading digit with 'a'.
3045
+ return /^[0-9]/.test(uuid) ? `a${uuid.slice(1)}` : uuid;
3046
+ }
3047
+
3006
3048
  /* eslint-disable line-comment-position, no-inline-comments */
3007
3049
 
3008
3050
 
@@ -4021,7 +4063,7 @@ class AuroFloatingUI {
4021
4063
 
4022
4064
  this.id = element.getAttribute("id");
4023
4065
  if (!this.id) {
4024
- this.id = window.crypto.randomUUID();
4066
+ this.id = generateUUID();
4025
4067
  element.setAttribute("id", this.id);
4026
4068
  }
4027
4069
 
@@ -5066,7 +5108,7 @@ let AuroHelpText$2 = class AuroHelpText extends i$3 {
5066
5108
  }
5067
5109
  };
5068
5110
 
5069
- var formkitVersion$2 = '202609021913';
5111
+ var formkitVersion$2 = '202609030018';
5070
5112
 
5071
5113
  /**
5072
5114
  * AuroElement is the shared base class for layout-aware Auro form components.
@@ -18935,7 +18977,7 @@ let AuroHelpText$1 = class AuroHelpText extends i$3 {
18935
18977
  }
18936
18978
  };
18937
18979
 
18938
- var formkitVersion$1 = '202609021913';
18980
+ var formkitVersion$1 = '202609030018';
18939
18981
 
18940
18982
  // Copyright (c) 2025 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
18941
18983
  // See LICENSE in the project root for license information.
@@ -20127,7 +20169,7 @@ class AuroBibtemplate extends i$3 {
20127
20169
  }
20128
20170
  }
20129
20171
 
20130
- var formkitVersion = '202609021913';
20172
+ var formkitVersion = '202609030018';
20131
20173
 
20132
20174
  var styleCss$3 = i$6`.util_displayInline{display:inline}.util_displayInlineBlock{display:inline-block}.util_displayBlock{display:block}.util_displayFlex{display:flex}.util_displayHidden{display:none}.util_displayHiddenVisually{position:absolute;overflow:hidden;clip:rect(1px, 1px, 1px, 1px);width:1px;height:1px;padding:0;border:0}:host{display:block;text-align:left}:host [auro-dropdown]{--ds-auro-dropdown-trigger-background-color: transparent}:host #inputInBib::part(wrapper){box-shadow:none}:host #inputInBib::part(accent-left){display:none}:host([layout*=classic]) [auro-input]{width:100%}:host([layout*=classic]) [auro-input]::part(helpText){display:none}:host([layout*=classic]) #slotHolder{display:none}`;
20133
20175