@aurodesignsystem-dev/auro-formkit 0.0.0-pr1540.0 → 0.0.0-pr1540.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 (82) hide show
  1. package/components/checkbox/demo/accessibility.md +1 -1
  2. package/components/checkbox/demo/customize.min.js +1 -1
  3. package/components/checkbox/demo/getting-started.min.js +1 -1
  4. package/components/checkbox/demo/index.min.js +1 -1
  5. package/components/checkbox/dist/index.js +1 -1
  6. package/components/checkbox/dist/registered.js +1 -1
  7. package/components/combobox/demo/accessibility.md +1 -1
  8. package/components/combobox/demo/api.md +2 -2
  9. package/components/combobox/demo/customize.md +54 -2
  10. package/components/combobox/demo/customize.min.js +421 -240
  11. package/components/combobox/demo/getting-started.min.js +421 -240
  12. package/components/combobox/demo/index.md +1 -0
  13. package/components/combobox/demo/index.min.js +421 -240
  14. package/components/combobox/demo/keyboard-behavior.md +1 -4
  15. package/components/combobox/dist/auro-combobox.d.ts +4 -1
  16. package/components/combobox/dist/index.js +334 -222
  17. package/components/combobox/dist/registered.js +334 -222
  18. package/components/counter/demo/customize.min.js +59 -222
  19. package/components/counter/demo/index.min.js +59 -222
  20. package/components/counter/dist/auro-counter.d.ts +0 -8
  21. package/components/counter/dist/index.js +59 -222
  22. package/components/counter/dist/registered.js +59 -222
  23. package/components/datepicker/demo/accessibility.md +1 -1
  24. package/components/datepicker/demo/customize.md +30 -1
  25. package/components/datepicker/demo/customize.min.js +84 -220
  26. package/components/datepicker/demo/getting-started.md +118 -2
  27. package/components/datepicker/demo/index.min.js +84 -220
  28. package/components/datepicker/dist/index.js +84 -220
  29. package/components/datepicker/dist/registered.js +84 -220
  30. package/components/dropdown/demo/customize.html +3 -0
  31. package/components/dropdown/demo/customize.min.js +55 -206
  32. package/components/dropdown/demo/getting-started.min.js +44 -205
  33. package/components/dropdown/demo/index.min.js +44 -205
  34. package/components/dropdown/dist/index.js +44 -205
  35. package/components/dropdown/dist/registered.js +44 -205
  36. package/components/form/demo/customize.min.js +670 -945
  37. package/components/form/demo/getting-started.min.js +670 -945
  38. package/components/form/demo/index.min.js +670 -945
  39. package/components/form/demo/registerDemoDeps.min.js +670 -945
  40. package/components/input/demo/accessibility.md +1 -1
  41. package/components/input/demo/customize.min.js +1 -1
  42. package/components/input/demo/getting-started.min.js +1 -1
  43. package/components/input/demo/index.min.js +1 -1
  44. package/components/input/dist/index.js +1 -1
  45. package/components/input/dist/registered.js +1 -1
  46. package/components/menu/demo/accessibility.md +9 -4
  47. package/components/menu/demo/api.md +26 -19
  48. package/components/menu/demo/css-only.md +26 -19
  49. package/components/menu/demo/customize.md +307 -47
  50. package/components/menu/demo/design.md +1 -1
  51. package/components/menu/demo/getting-started.md +144 -7
  52. package/components/menu/demo/index.min.js +214 -19
  53. package/components/menu/demo/keyboard-behavior.md +83 -4
  54. package/components/menu/demo/voiceover.md +21 -14
  55. package/components/menu/demo/why-menu.md +8 -9
  56. package/components/menu/dist/auro-menu-utils.d.ts +19 -0
  57. package/components/menu/dist/auro-menu.d.ts +4 -8
  58. package/components/menu/dist/auro-menuoption.d.ts +12 -0
  59. package/components/menu/dist/index.js +87 -18
  60. package/components/menu/dist/registered.js +87 -18
  61. package/components/radio/demo/accessibility.md +1 -1
  62. package/components/radio/demo/customize.min.js +1 -1
  63. package/components/radio/demo/getting-started.min.js +1 -1
  64. package/components/radio/demo/index.min.js +1 -1
  65. package/components/radio/dist/index.js +1 -1
  66. package/components/radio/dist/registered.js +1 -1
  67. package/components/select/demo/accessibility.md +6 -1
  68. package/components/select/demo/api.md +2 -2
  69. package/components/select/demo/customize.md +6 -3
  70. package/components/select/demo/customize.min.js +139 -227
  71. package/components/select/demo/design.md +10 -10
  72. package/components/select/demo/getting-started.md +1 -1
  73. package/components/select/demo/getting-started.min.js +139 -227
  74. package/components/select/demo/index.md +2 -2
  75. package/components/select/demo/index.min.js +139 -227
  76. package/components/select/demo/keyboard-behavior.md +53 -58
  77. package/components/select/demo/voiceover.md +28 -15
  78. package/components/select/dist/auro-select.d.ts +6 -2
  79. package/components/select/dist/index.js +52 -209
  80. package/components/select/dist/registered.js +52 -209
  81. package/custom-elements.json +1611 -1552
  82. package/package.json +2 -2
@@ -12338,7 +12338,7 @@ let AuroHelpText$8 = class AuroHelpText extends i$2 {
12338
12338
  }
12339
12339
  };
12340
12340
 
12341
- var formkitVersion$8 = '202607072023';
12341
+ var formkitVersion$8 = '202607102214';
12342
12342
 
12343
12343
  // Copyright (c) 2025 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
12344
12344
  // See LICENSE in the project root for license information.
@@ -26735,7 +26735,7 @@ let AuroBibtemplate$3 = class AuroBibtemplate extends i$2 {
26735
26735
  }
26736
26736
  };
26737
26737
 
26738
- var formkitVersion$2$1 = '202607072023';
26738
+ var formkitVersion$2$1 = '202607102214';
26739
26739
 
26740
26740
  let l$1$2 = class l{generateElementName(t,e){let o=t;return o+="-",o+=e.replace(/[.]/g,"_"),o}generateTag(o,s,a){const r=this.generateElementName(o,s),i=i$5`${s$5(r)}`;return customElements.get(r)||customElements.define(r,class extends a{}),i}};let d$1$2 = class d{registerComponent(t,e){customElements.get(t)||customElements.define(t,class extends e{});}closestElement(t,e=this,o=(e,s=e&&e.closest(t))=>e&&e!==document&&e!==window?s||o(e.getRootNode().host):null){return o(e)}handleComponentTagRename(t,e){const o=e.toLowerCase();t.tagName.toLowerCase()!==o&&t.setAttribute(o,true);}elementMatch(t,e){const o=e.toLowerCase();return t.tagName.toLowerCase()===o||t.hasAttribute(o)}getSlotText(t,e){const o=t.shadowRoot?.querySelector(`slot[name="${e}"]`),s=(o?.assignedNodes({flatten:true})||[]).map(t=>t.textContent?.trim()).join(" ").trim();return s||null}};let h$1$2 = class h{registerComponent(t,e){customElements.get(t)||customElements.define(t,class extends e{});}closestElement(t,e=this,o=(e,s=e&&e.closest(t))=>e&&e!==document&&e!==window?s||o(e.getRootNode().host):null){return o(e)}handleComponentTagRename(t,e){const o=e.toLowerCase();t.tagName.toLowerCase()!==o&&t.setAttribute(o,true);}elementMatch(t,e){const o=e.toLowerCase();return t.tagName.toLowerCase()===o||t.hasAttribute(o)}};var c$1$3=i$4`:host{color:var(--ds-auro-loader-color)}:host>span{background-color:var(--ds-auro-loader-background-color);border-color:var(--ds-auro-loader-border-color)}:host([onlight]),:host([appearance=brand]){--ds-auro-loader-color: var(--ds-basic-color-brand-primary, #01426a)}:host([ondark]),:host([appearance=inverse]){--ds-auro-loader-color: var(--ds-basic-color-texticon-inverse, #ffffff)}:host([orbit])>span{--ds-auro-loader-background-color: transparent}:host([orbit])>span:nth-child(1){--ds-auro-loader-border-color: currentcolor;opacity:.25}:host([orbit])>span:nth-child(2){--ds-auro-loader-border-color: currentcolor;border-right-color:transparent;border-bottom-color:transparent;border-left-color:transparent}
26741
26741
  `,u$4$2=i$4`.body-default{font-size:var(--wcss-body-default-font-size, 1rem);line-height:var(--wcss-body-default-line-height, 1.5rem)}.body-default,.body-lg{font-family:var(--wcss-body-family, "AS Circular"),system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;font-weight:var(--wcss-body-weight, 450);letter-spacing:var(--wcss-body-letter-spacing, 0)}.body-lg{font-size:var(--wcss-body-lg-font-size, 1.125rem);line-height:var(--wcss-body-lg-line-height, 1.625rem)}.body-sm{font-size:var(--wcss-body-sm-font-size, .875rem);line-height:var(--wcss-body-sm-line-height, 1.25rem)}.body-sm,.body-xs{font-family:var(--wcss-body-family, "AS Circular"),system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;font-weight:var(--wcss-body-weight, 450);letter-spacing:var(--wcss-body-letter-spacing, 0)}.body-xs{font-size:var(--wcss-body-xs-font-size, .75rem);line-height:var(--wcss-body-xs-line-height, 1rem)}.body-2xs{font-family:var(--wcss-body-family, "AS Circular"),system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;font-size:var(--wcss-body-2xs-font-size, .625rem);font-weight:var(--wcss-body-weight, 450);letter-spacing:var(--wcss-body-letter-spacing, 0);line-height:var(--wcss-body-2xs-line-height, .875rem)}.display-2xl{font-family:var(--wcss-display-2xl-family, "AS Circular"),var(--wcss-display-2xl-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-display-2xl-font-size, clamp(3.5rem, 6vw, 5.375rem));font-weight:var(--wcss-display-2xl-weight, 300);letter-spacing:var(--wcss-display-2xl-letter-spacing, 0);line-height:var(--wcss-display-2xl-line-height, 1.3)}.display-xl{font-family:var(--wcss-display-xl-family, "AS Circular"),var(--wcss-display-xl-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-display-xl-font-size, clamp(3rem, 5.3333333333vw, 4.5rem));font-weight:var(--wcss-display-xl-weight, 300);letter-spacing:var(--wcss-display-xl-letter-spacing, 0);line-height:var(--wcss-display-xl-line-height, 1.3)}.display-lg{font-family:var(--wcss-display-lg-family, "AS Circular"),var(--wcss-display-lg-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-display-lg-font-size, clamp(2.75rem, 4.6666666667vw, 4rem));font-weight:var(--wcss-display-lg-weight, 300);letter-spacing:var(--wcss-display-lg-letter-spacing, 0);line-height:var(--wcss-display-lg-line-height, 1.3)}.display-md{font-family:var(--wcss-display-md-family, "AS Circular"),var(--wcss-display-md-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-display-md-font-size, clamp(2.5rem, 4vw, 3.5rem));font-weight:var(--wcss-display-md-weight, 300);letter-spacing:var(--wcss-display-md-letter-spacing, 0);line-height:var(--wcss-display-md-line-height, 1.3)}.display-sm{font-family:var(--wcss-display-sm-family, "AS Circular"),var(--wcss-display-sm-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-display-sm-font-size, clamp(2rem, 3.6666666667vw, 3rem));font-weight:var(--wcss-display-sm-weight, 300);letter-spacing:var(--wcss-display-sm-letter-spacing, 0);line-height:var(--wcss-display-sm-line-height, 1.3)}.display-xs{font-family:var(--wcss-display-xs-family, "AS Circular"),var(--wcss-display-xs-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-display-xs-font-size, clamp(1.75rem, 3vw, 2.375rem));font-weight:var(--wcss-display-xs-weight, 300);letter-spacing:var(--wcss-display-xs-letter-spacing, 0);line-height:var(--wcss-display-xs-line-height, 1.3)}.heading-xl{font-family:var(--wcss-heading-xl-family, "AS Circular"),var(--wcss-heading-xl-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-heading-xl-font-size, clamp(2rem, 3vw, 2.5rem));font-weight:var(--wcss-heading-xl-weight, 300);letter-spacing:var(--wcss-heading-xl-letter-spacing, 0);line-height:var(--wcss-heading-xl-line-height, 1.3)}.heading-lg{font-family:var(--wcss-heading-lg-family, "AS Circular"),var(--wcss-heading-lg-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-heading-lg-font-size, clamp(1.75rem, 2.6666666667vw, 2.25rem));font-weight:var(--wcss-heading-lg-weight, 300);letter-spacing:var(--wcss-heading-lg-letter-spacing, 0);line-height:var(--wcss-heading-lg-line-height, 1.3)}.heading-md{font-family:var(--wcss-heading-md-family, "AS Circular"),var(--wcss-heading-md-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-heading-md-font-size, clamp(1.625rem, 2.3333333333vw, 1.75rem));font-weight:var(--wcss-heading-md-weight, 300);letter-spacing:var(--wcss-heading-md-letter-spacing, 0);line-height:var(--wcss-heading-md-line-height, 1.3)}.heading-sm{font-family:var(--wcss-heading-sm-family, "AS Circular"),var(--wcss-heading-sm-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-heading-sm-font-size, clamp(1.375rem, 2vw, 1.5rem));font-weight:var(--wcss-heading-sm-weight, 300);letter-spacing:var(--wcss-heading-sm-letter-spacing, 0);line-height:var(--wcss-heading-sm-line-height, 1.3)}.heading-xs{font-family:var(--wcss-heading-xs-family, "AS Circular"),var(--wcss-heading-xs-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-heading-xs-font-size, clamp(1.25rem, 1.6666666667vw, 1.25rem));font-weight:var(--wcss-heading-xs-weight, 450);letter-spacing:var(--wcss-heading-xs-letter-spacing, 0);line-height:var(--wcss-heading-xs-line-height, 1.3)}.heading-2xs{font-family:var(--wcss-heading-2xs-family, "AS Circular"),var(--wcss-heading-2xs-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-heading-2xs-font-size, clamp(1.125rem, 1.5vw, 1.125rem));font-weight:var(--wcss-heading-2xs-weight, 450);letter-spacing:var(--wcss-heading-2xs-letter-spacing, 0);line-height:var(--wcss-heading-2xs-line-height, 1.3)}.accent-2xl{font-family:var(--wcss-accent-2xl-family, "Good OT"),var(--wcss-accent-2xl-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-accent-2xl-font-size, clamp(2rem, 3.1666666667vw, 2.375rem));font-weight:var(--wcss-accent-2xl-weight, 450);letter-spacing:var(--wcss-accent-2xl-letter-spacing, .05em);line-height:var(--wcss-accent-2xl-line-height, 1)}.accent-2xl,.accent-xl{text-transform:uppercase}.accent-xl{font-family:var(--wcss-accent-xl-family, "Good OT"),var(--wcss-accent-xl-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-accent-xl-font-size, clamp(1.625rem, 2.3333333333vw, 2rem));font-weight:var(--wcss-accent-xl-weight, 450);letter-spacing:var(--wcss-accent-xl-letter-spacing, .05em);line-height:var(--wcss-accent-xl-line-height, 1.3)}.accent-lg{font-family:var(--wcss-accent-lg-family, "Good OT"),var(--wcss-accent-lg-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-accent-lg-font-size, clamp(1.5rem, 2.1666666667vw, 1.75rem));font-weight:var(--wcss-accent-lg-weight, 450);letter-spacing:var(--wcss-accent-lg-letter-spacing, .05em);line-height:var(--wcss-accent-lg-line-height, 1.3)}.accent-lg,.accent-md{text-transform:uppercase}.accent-md{font-family:var(--wcss-accent-md-family, "Good OT"),var(--wcss-accent-md-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-accent-md-font-size, clamp(1.375rem, 1.8333333333vw, 1.5rem));font-weight:var(--wcss-accent-md-weight, 500);letter-spacing:var(--wcss-accent-md-letter-spacing, .05em);line-height:var(--wcss-accent-md-line-height, 1.3)}.accent-sm{font-family:var(--wcss-accent-sm-family, "Good OT"),var(--wcss-accent-sm-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-accent-sm-font-size, clamp(1.125rem, 1.5vw, 1.25rem));font-weight:var(--wcss-accent-sm-weight, 500);letter-spacing:var(--wcss-accent-sm-letter-spacing, .05em);line-height:var(--wcss-accent-sm-line-height, 1.3)}.accent-sm,.accent-xs{text-transform:uppercase}.accent-xs{font-family:var(--wcss-accent-xs-family, "Good OT"),var(--wcss-accent-xs-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-accent-xs-font-size, clamp(1rem, 1.3333333333vw, 1rem));font-weight:var(--wcss-accent-xs-weight, 500);letter-spacing:var(--wcss-accent-xs-letter-spacing, .1em);line-height:var(--wcss-accent-xs-line-height, 1.3)}.accent-2xs{font-family:var(--wcss-accent-2xs-family, "Good OT"),var(--wcss-accent-2xs-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-accent-2xs-font-size, clamp(.875rem, 1.1666666667vw, .875rem));font-weight:var(--wcss-accent-2xs-weight, 450);letter-spacing:var(--wcss-accent-2xs-letter-spacing, .1em);line-height:var(--wcss-accent-2xs-line-height, 1.3);text-transform:uppercase}:focus:not(:focus-visible){outline:3px solid transparent}:host,:host>span{position:relative}:host{width:2rem;height:2rem;display:inline-block;font-size:0}:host>span{position:absolute;display:inline-block;float:none;top:0;left:0;width:2rem;height:2rem;border-radius:100%;border-style:solid;border-width:0;box-sizing:border-box}:host([xs]),:host([xs])>span{width:1.2rem;height:1.2rem}:host([sm]),:host([sm])>span{width:3rem;height:3rem}:host([md]),:host([md])>span{width:5rem;height:5rem}:host([lg]),:host([lg])>span{width:8rem;height:8rem}:host{--margin: .375rem;--margin-xs: .2rem;--margin-sm: .5rem;--margin-md: .75rem;--margin-lg: 1rem}:host([pulse]),:host([pulse])>span{position:relative}:host([pulse]){width:calc(3rem + var(--margin) * 6);height:calc(1rem + var(--margin) * 2)}:host([pulse])>span{width:1rem;height:1rem;margin:var(--margin);animation:pulse 1.5s ease infinite}:host([pulse][xs]){width:calc(1.95rem + var(--margin-xs) * 6);height:calc(.65rem + var(--margin-xs) * 2)}:host([pulse][xs])>span{margin:var(--margin-xs);width:.65rem;height:.65rem}:host([pulse][sm]){width:calc(6rem + var(--margin-sm) * 6);height:calc(2rem + var(--margin-sm) * 2)}:host([pulse][sm])>span{margin:var(--margin-sm);width:2rem;height:2rem}:host([pulse][md]){width:calc(9rem + var(--margin-md) * 6);height:calc(3rem + var(--margin-md) * 2)}:host([pulse][md])>span{margin:var(--margin-md);width:3rem;height:3rem}:host([pulse][lg]){width:calc(15rem + var(--margin-lg) * 6);height:calc(5rem + var(--margin-lg) * 2)}:host([pulse][lg])>span{margin:var(--margin-lg);width:5rem;height:5rem}:host([pulse])>span:nth-child(1){animation-delay:-.4s}:host([pulse])>span:nth-child(2){animation-delay:-.2s}:host([pulse])>span:nth-child(3){animation-delay:0ms}@keyframes pulse{0%,to{opacity:.1;transform:scale(.9)}50%{opacity:1;transform:scale(1.1)}}:host([orbit]),:host([orbit])>span{opacity:1}:host([orbit])>span{border-width:5px}:host([orbit])>span:nth-child(2){animation:orbit 2s linear infinite}:host([orbit][sm])>span{border-width:8px}:host([orbit][md])>span{border-width:13px}:host([orbit][lg])>span{border-width:21px}@keyframes orbit{0%{transform:rotate(0)}to{transform:rotate(360deg)}}:host([ringworm])>svg{animation:rotate 2s linear infinite;height:100%;width:100%;stroke:currentcolor;stroke-width:8}:host([ringworm]) .path{stroke-dashoffset:0;animation:ringworm 1.5s ease-in-out infinite;stroke-linecap:round}@keyframes rotate{to{transform:rotate(360deg)}}@keyframes ringworm{0%{stroke-dasharray:1,200;stroke-dashoffset:0}50%{stroke-dasharray:89,200;stroke-dashoffset:-35px}to{stroke-dasharray:89,200;stroke-dashoffset:-124px}}:host([laser]){position:static;width:100%;display:block;height:0;overflow:hidden;font-size:unset}:host([laser])>span{position:fixed;width:100%;height:.25rem;border-radius:0;z-index:100}:host([laser])>span:nth-child(1){border-color:currentcolor;opacity:.25}:host([laser])>span:nth-child(2){border-color:currentcolor;animation:laser 2s linear infinite;opacity:1;width:50%}:host([laser][sm])>span:nth-child(2){width:20%}:host([laser][md])>span:nth-child(2){width:30%}:host([laser][lg])>span:nth-child(2){width:50%;animation-duration:1.5s}:host([laser][xl])>span:nth-child(2){width:80%;animation-duration:1.5s}@keyframes laser{0%{left:-100%}to{left:110%}}:host>.no-animation{display:none}@media (prefers-reduced-motion: reduce){:host{display:flex;align-items:center;justify-content:center}:host>span{opacity:1}:host>.loader{display:none}:host>svg{display:none}:host>.no-animation{display:block}}
@@ -31012,12 +31012,40 @@ let AuroFloatingUI$3 = class AuroFloatingUI {
31012
31012
  return;
31013
31013
  }
31014
31014
 
31015
+ // Chrome-specific: during popover top-layer promotion after a click on a
31016
+ // slotted focusable, :focus-within can briefly evaluate false while the
31017
+ // active element is still structurally inside the trigger/bib. Fall back
31018
+ // to a shadow-piercing ancestry walk from the deep active element before
31019
+ // treating this as a real focus loss.
31020
+ try {
31021
+ let active = document.activeElement;
31022
+ while (active && active.shadowRoot && active.shadowRoot.activeElement) {
31023
+ active = active.shadowRoot.activeElement;
31024
+ }
31025
+ const targets = [element, element.trigger, element.bib].filter(Boolean);
31026
+ let node = active;
31027
+ while (node) {
31028
+ if (targets.includes(node)) {
31029
+ return;
31030
+ }
31031
+ node =
31032
+ node.parentElement ||
31033
+ (node.getRootNode && node.getRootNode().host) ||
31034
+ null;
31035
+ }
31036
+ } catch (e) {
31037
+ // Defensive: fall through to the existing close path if traversal fails.
31038
+ }
31039
+
31015
31040
  // if fullscreen bib is in fullscreen mode, do not close
31016
31041
  if (element.bib.hasAttribute("isfullscreen")) {
31017
31042
  return;
31018
31043
  }
31019
31044
 
31020
- this.hideBib("keydown");
31045
+ // eventType "focusloss" distinguishes a Tab/click-driven close from an
31046
+ // Escape keydown close. Consumers use this to decide whether to restore
31047
+ // focus to the trigger (Escape) or let it advance naturally (Tab).
31048
+ this.hideBib("focusloss");
31021
31049
  }
31022
31050
 
31023
31051
  setupHideHandlers() {
@@ -31506,7 +31534,7 @@ let AuroFloatingUI$3 = class AuroFloatingUI {
31506
31534
  };
31507
31535
 
31508
31536
  // Selectors for focusable elements
31509
- const FOCUSABLE_SELECTORS$3 = [
31537
+ const FOCUSABLE_SELECTORS$4 = [
31510
31538
  "a[href]",
31511
31539
  "button:not([disabled])",
31512
31540
  "textarea:not([disabled])",
@@ -31520,7 +31548,7 @@ const FOCUSABLE_SELECTORS$3 = [
31520
31548
  ];
31521
31549
 
31522
31550
  // List of custom components that are known to be focusable
31523
- const FOCUSABLE_COMPONENTS$3 = [
31551
+ const FOCUSABLE_COMPONENTS$4 = [
31524
31552
  "auro-checkbox",
31525
31553
  "auro-radio",
31526
31554
  "auro-dropdown",
@@ -31542,12 +31570,12 @@ const FOCUSABLE_COMPONENTS$3 = [
31542
31570
  * @param {HTMLElement} element The element to check for focusability.
31543
31571
  * @returns {boolean} True if the element is a focusable custom component, false otherwise.
31544
31572
  */
31545
- function isFocusableComponent$3(element) {
31573
+ function isFocusableComponent$4(element) {
31546
31574
  const componentName = element.tagName.toLowerCase();
31547
31575
 
31548
31576
  // Guard Clause: Element is a focusable component
31549
31577
  if (
31550
- !FOCUSABLE_COMPONENTS$3.some(
31578
+ !FOCUSABLE_COMPONENTS$4.some(
31551
31579
  (name) => element.hasAttribute(name) || componentName === name,
31552
31580
  )
31553
31581
  )
@@ -31571,7 +31599,7 @@ function isFocusableComponent$3(element) {
31571
31599
  * @param {HTMLElement} element The element whose tabindex to read.
31572
31600
  * @returns {?number} The numeric tabindex or null if missing/invalid.
31573
31601
  */
31574
- function getNumericTabIndex$3(element) {
31602
+ function getNumericTabIndex$4(element) {
31575
31603
  const raw = element.getAttribute("tabindex");
31576
31604
  if (raw == null) return null;
31577
31605
 
@@ -31587,7 +31615,7 @@ function getNumericTabIndex$3(element) {
31587
31615
  * @param {HTMLElement} container The container to search within
31588
31616
  * @returns {Array<HTMLElement>} An array of focusable elements within the container.
31589
31617
  */
31590
- function getFocusableElements$3(container) {
31618
+ function getFocusableElements$4(container) {
31591
31619
  // Get elements in DOM order by walking the tree
31592
31620
  const orderedFocusableElements = [];
31593
31621
 
@@ -31596,7 +31624,7 @@ function getFocusableElements$3(container) {
31596
31624
  // Check if current element is focusable
31597
31625
  if (root.nodeType === Node.ELEMENT_NODE) {
31598
31626
  // Check if this is a custom component that is focusable
31599
- const isComponentFocusable = isFocusableComponent$3(root);
31627
+ const isComponentFocusable = isFocusableComponent$4(root);
31600
31628
 
31601
31629
  if (isComponentFocusable) {
31602
31630
  // Add the component itself as a focusable element and don't traverse its shadow DOM
@@ -31605,7 +31633,7 @@ function getFocusableElements$3(container) {
31605
31633
  }
31606
31634
 
31607
31635
  // Check if the element itself matches any selector
31608
- for (const selector of FOCUSABLE_SELECTORS$3) {
31636
+ for (const selector of FOCUSABLE_SELECTORS$4) {
31609
31637
  if (root.matches?.(selector)) {
31610
31638
  orderedFocusableElements.push(root);
31611
31639
  break; // Once we know it's focusable, no need to check other selectors
@@ -31659,20 +31687,20 @@ function getFocusableElements$3(container) {
31659
31687
 
31660
31688
  // First extract elements with valid positive tabindex
31661
31689
  const elementsWithTabindex = uniqueElements.filter((el) => {
31662
- const tabindex = getNumericTabIndex$3(el);
31690
+ const tabindex = getNumericTabIndex$4(el);
31663
31691
  return tabindex !== null && tabindex > 0;
31664
31692
  });
31665
31693
 
31666
31694
  // Sort these elements by their tabindex value
31667
31695
  elementsWithTabindex.sort((a, b) => {
31668
- const aIndex = getNumericTabIndex$3(a) ?? 0;
31669
- const bIndex = getNumericTabIndex$3(b) ?? 0;
31696
+ const aIndex = getNumericTabIndex$4(a) ?? 0;
31697
+ const bIndex = getNumericTabIndex$4(b) ?? 0;
31670
31698
  return aIndex - bIndex;
31671
31699
  });
31672
31700
 
31673
31701
  // Elements without tabindex (preserving their original order)
31674
31702
  const elementsWithoutTabindex = uniqueElements.filter((el) => {
31675
- const tabindex = getNumericTabIndex$3(el);
31703
+ const tabindex = getNumericTabIndex$4(el);
31676
31704
 
31677
31705
  // Elements without tabindex or with tabindex of 0 stay in DOM order
31678
31706
  return tabindex === null || tabindex === 0;
@@ -31687,199 +31715,6 @@ function getFocusableElements$3(container) {
31687
31715
  return tabIndexedUniqueElements;
31688
31716
  }
31689
31717
 
31690
- /**
31691
- * FocusTrap manages keyboard focus within a specified container element, ensuring that focus does not leave the container when tabbing.
31692
- * It is commonly used for modal dialogs or overlays to improve accessibility by trapping focus within interactive UI components.
31693
- */
31694
- let FocusTrap$3 = class FocusTrap {
31695
- /**
31696
- * Creates a new FocusTrap instance for the given container element.
31697
- * Initializes event listeners and prepares the container for focus management.
31698
- *
31699
- * @param {HTMLElement} container The DOM element to trap focus within.
31700
- * @param {boolean} [controlTabOrder=false] If true enables manual control of the tab order by the FocusTrap.
31701
- * @throws {Error} If the provided container is not a valid HTMLElement.
31702
- */
31703
- constructor(container, controlTabOrder = false) {
31704
- if (!container || !(container instanceof HTMLElement)) {
31705
- throw new Error("FocusTrap requires a valid HTMLElement.");
31706
- }
31707
-
31708
- this.container = container;
31709
- this.tabDirection = "forward"; // or 'backward';
31710
- this.controlTabOrder = controlTabOrder;
31711
-
31712
- this._init();
31713
- }
31714
-
31715
- /**
31716
- * Initializes the focus trap by setting up event listeners and attributes on the container.
31717
- * Prepares the container for focus management, including support for shadow DOM and inert attributes.
31718
- *
31719
- * @private
31720
- */
31721
- _init() {
31722
- // Add inert attribute to prevent focusing programmatically as well (if supported)
31723
- if ("inert" in HTMLElement.prototype) {
31724
- this.container.inert = false; // Ensure the container isn't inert
31725
- this.container.setAttribute("data-focus-trap-container", true); // Mark for identification
31726
- }
31727
-
31728
- // Track tab direction
31729
- this.container.addEventListener("keydown", this._onKeydown);
31730
- }
31731
-
31732
- /**
31733
- * Gets an array of currently active (focused) elements in the document and shadow DOM.
31734
- * @returns {Array<HTMLElement>} An array of focusable elements within the container.
31735
- * @private
31736
- */
31737
- _getActiveElements() {
31738
- // Get the active element(s) in the document and shadow root
31739
- // This will include the active element in the shadow DOM if it exists
31740
- // Active element may be inside the shadow DOM depending on delegatesFocus, so we need to check both
31741
- let { activeElement } = document;
31742
- const actives = [activeElement];
31743
- while (activeElement?.shadowRoot?.activeElement) {
31744
- actives.push(activeElement.shadowRoot.activeElement);
31745
- activeElement = activeElement.shadowRoot.activeElement;
31746
- }
31747
- return actives;
31748
- }
31749
-
31750
- /**
31751
- * Gets the next focus index based on the current index and focusable elements.
31752
- * @param {number} currentIndex The current index of the focused element.
31753
- * @param {Array<HTMLElement>} focusables The array of focusable elements.
31754
- * @returns {number|null} The next focus index or null if not determined.
31755
- */
31756
- _getNextFocusIndex(currentIndex, focusables, actives) {
31757
- if (this.controlTabOrder) {
31758
- // Calculate the new index based on the current index and tab direction
31759
- let newFocusIndex =
31760
- currentIndex + (this.tabDirection === "forward" ? 1 : -1);
31761
-
31762
- // Wrap-around logic
31763
- if (newFocusIndex < 0) newFocusIndex = focusables.length - 1;
31764
- if (newFocusIndex >= focusables.length) newFocusIndex = 0;
31765
-
31766
- // Early return with the new index
31767
- return newFocusIndex;
31768
- }
31769
-
31770
- // Determine if we need to wrap
31771
- const atFirst =
31772
- actives.includes(focusables[0]) || actives.includes(this.container);
31773
- const atLast = actives.includes(focusables[focusables.length - 1]);
31774
-
31775
- // Only wrap if at the ends
31776
- if (this.tabDirection === "backward" && atFirst) {
31777
- return focusables.length - 1;
31778
- }
31779
-
31780
- if (this.tabDirection === "forward" && atLast) {
31781
- return 0;
31782
- }
31783
-
31784
- // No wrap, so don't change focus, return early
31785
- return null;
31786
- }
31787
-
31788
- /**
31789
- * Handles the Tab key press event to manage focus within the container.
31790
- * @param {KeyboardEvent} e The keyboard event triggered by the user.
31791
- * @returns {void}
31792
- */
31793
- _handleTabKey(e) {
31794
- // Update the focusable elements
31795
- const focusables = this._getFocusableElements();
31796
-
31797
- // If there are no focusable elements, exit
31798
- if (!focusables.length) return;
31799
-
31800
- // Set the tab direction based on the key pressed
31801
- this.tabDirection = e.shiftKey ? "backward" : "forward";
31802
-
31803
- // Get the active elements that are currently focused
31804
- const actives = this._getActiveElements();
31805
-
31806
- // If we're at either end of the focusable elements, wrap around to the other end
31807
- let focusIndex = focusables.findIndex((el) => actives.includes(el));
31808
-
31809
- // Fallback if we have no focused element
31810
- if (focusIndex === -1) focusIndex = 0;
31811
-
31812
- // Get the next focus index based on the current focus index, tab direction, and controlTabOrder setting
31813
- // Is null if no new focus index is determined
31814
- const newFocusIndex = this._getNextFocusIndex(
31815
- focusIndex,
31816
- focusables,
31817
- actives,
31818
- );
31819
-
31820
- // If we have a new focus index, set focus to that element
31821
- if (newFocusIndex !== null) {
31822
- e.preventDefault();
31823
- focusables[newFocusIndex].focus();
31824
- }
31825
- }
31826
-
31827
- /**
31828
- * Catches the keydown event
31829
- * @param {KeyboardEvent} e The keyboard event triggered by user interaction.
31830
- * @private
31831
- */
31832
- _onKeydown = (e) => {
31833
- // Handle tab
31834
- if (e.key === "Tab") this._handleTabKey(e);
31835
- };
31836
-
31837
- /**
31838
- * Retrieves all focusable elements within the container in DOM order, including those in shadow DOM and slots.
31839
- * Returns a unique, ordered array of elements that can receive focus.
31840
- *
31841
- * @returns {Array<HTMLElement>} An array of focusable elements within the container.
31842
- * @private
31843
- */
31844
- _getFocusableElements() {
31845
- // Use the imported utility function to get focusable elements
31846
- const elements = getFocusableElements$3(this.container);
31847
-
31848
- // Return the elements found
31849
- return elements;
31850
- }
31851
-
31852
- /**
31853
- * Moves focus to the first focusable element within the container.
31854
- * Useful for setting initial focus when activating the focus trap.
31855
- */
31856
- focusFirstElement() {
31857
- const focusables = this._getFocusableElements();
31858
- if (focusables.length) focusables[0].focus();
31859
- }
31860
-
31861
- /**
31862
- * Moves focus to the last focusable element within the container.
31863
- * Useful for setting focus when deactivating or cycling focus in reverse.
31864
- */
31865
- focusLastElement() {
31866
- const focusables = this._getFocusableElements();
31867
- if (focusables.length) focusables[focusables.length - 1].focus();
31868
- }
31869
-
31870
- /**
31871
- * Removes event listeners and attributes added by the focus trap.
31872
- * Call this method to clean up when the focus trap is no longer needed.
31873
- */
31874
- disconnect() {
31875
- if (this.container.hasAttribute("data-focus-trap-container")) {
31876
- this.container.removeAttribute("data-focus-trap-container");
31877
- }
31878
-
31879
- this.container.removeEventListener("keydown", this._onKeydown);
31880
- }
31881
- };
31882
-
31883
31718
  // Copyright (c) Alaska Air. All right reserved. Licensed under the Apache-2.0 license
31884
31719
  // See LICENSE in the project root for license information.
31885
31720
 
@@ -32377,7 +32212,7 @@ let AuroDropdownBib$3 = class AuroDropdownBib extends i$2 {
32377
32212
  classes[`shape-${this.shape}`] = true;
32378
32213
 
32379
32214
  return u$d`
32380
- <dialog class="${e$2(classes)}" part="bibContainer" role="${o$4(this.dialogRole)}" aria-labelledby="${o$4(this.dialogLabel ? 'dialogLabel' : undefined)}">
32215
+ <dialog tabindex="-1" class="${e$2(classes)}" part="bibContainer" role="${o$4(this.dialogRole)}" aria-labelledby="${o$4(this.dialogLabel ? 'dialogLabel' : undefined)}">
32381
32216
  ${this.dialogLabel ? u$d`<span id="dialogLabel" class="util_displayHiddenVisually">${this.dialogLabel}</span>` : ''}
32382
32217
  <slot></slot>
32383
32218
  <span id="srAnnouncement" class="util_displayHiddenVisually" aria-live="polite" role="status"></span>
@@ -32628,7 +32463,7 @@ let AuroHelpText$2$1 = class AuroHelpText extends i$2 {
32628
32463
  }
32629
32464
  };
32630
32465
 
32631
- var formkitVersion$1$3 = '202607072023';
32466
+ var formkitVersion$1$3 = '202607102214';
32632
32467
 
32633
32468
  let AuroElement$2$2 = class AuroElement extends i$2 {
32634
32469
  static get properties() {
@@ -32919,7 +32754,7 @@ let AuroDropdown$3 = class AuroDropdown extends AuroElement$2$2 {
32919
32754
  */
32920
32755
  focus() {
32921
32756
  if (this.isPopoverVisible && this.bibContent) {
32922
- const focusables = getFocusableElements$3(this.bibContent);
32757
+ const focusables = getFocusableElements$4(this.bibContent);
32923
32758
  if (focusables.length > 0) {
32924
32759
  focusables[0].focus();
32925
32760
  }
@@ -33382,7 +33217,10 @@ let AuroDropdown$3 = class AuroDropdown extends AuroElement$2$2 {
33382
33217
  }
33383
33218
 
33384
33219
 
33385
- if (!this.isPopoverVisible) {
33220
+ // On Tab-driven close (eventType "focusloss"), let focus advance naturally
33221
+ // — restoring to the trigger would trap the user on this dropdown, forcing
33222
+ // an extra Tab to move on. Escape and outside-click still restore.
33223
+ if (!this.isPopoverVisible && eventType !== "focusloss") {
33386
33224
  // wait til the bib gets fully closed and rendered
33387
33225
  setTimeout(() => {
33388
33226
  // Skip if the bib re-opened, or if focus moved intentionally outside the dropdown (not to body).
@@ -33537,7 +33375,7 @@ let AuroDropdown$3 = class AuroDropdown extends AuroElement$2$2 {
33537
33375
  }
33538
33376
 
33539
33377
  // Collect focusable elements from the bib content.
33540
- const focusables = getFocusableElements$3(this.bibContent);
33378
+ const focusables = getFocusableElements$4(this.bibContent);
33541
33379
 
33542
33380
  // Fallback: try from slotted content directly
33543
33381
  if (!focusables.length) {
@@ -33546,7 +33384,7 @@ let AuroDropdown$3 = class AuroDropdown extends AuroElement$2$2 {
33546
33384
 
33547
33385
  for (const node of assignedNodes) {
33548
33386
  if (node.nodeType === Node.ELEMENT_NODE) {
33549
- focusables.push(...getFocusableElements$3(node));
33387
+ focusables.push(...getFocusableElements$4(node));
33550
33388
  }
33551
33389
  }
33552
33390
  }
@@ -33606,21 +33444,22 @@ let AuroDropdown$3 = class AuroDropdown extends AuroElement$2$2 {
33606
33444
 
33607
33445
  // Move initial focus into the bib content, matching FocusTrap behavior
33608
33446
  requestAnimationFrame(() => {
33609
- const focusables = getFocusableElements$3(this.bibContent);
33447
+ const focusables = getFocusableElements$4(this.bibContent);
33610
33448
  if (focusables.length) {
33611
33449
  focusables[0].focus();
33612
33450
  }
33613
33451
  });
33614
33452
  } else {
33615
- // Normal desktop: use FocusTrap on the bib element.
33616
- // Defer focusFirstElement to the next frame because the popover
33617
- // is positioned asynchronously by Floating UI — calling focus()
33618
- // synchronously here would target elements with zero dimensions
33619
- // and the focus call would be silently ignored.
33620
- this.focusTrap = new FocusTrap$3(this.bibContent);
33453
+ // Normal desktop (non-modal): move initial focus into the bib but
33454
+ // don't trap Tab. Tab should exit the bib and let the floater's
33455
+ // handleFocusLoss close it, matching native <select>/<details>
33456
+ // behavior. Deferred one frame because Floating UI positions the
33457
+ // popover asynchronously a synchronous focus() would target
33458
+ // zero-dimension elements and be silently ignored.
33621
33459
  requestAnimationFrame(() => {
33622
- if (this.focusTrap) {
33623
- this.focusTrap.focusFirstElement();
33460
+ const focusables = getFocusableElements$4(this.bibContent);
33461
+ if (focusables.length) {
33462
+ focusables[0].focus();
33624
33463
  }
33625
33464
  });
33626
33465
  }
@@ -33836,7 +33675,7 @@ let AuroDropdown$3 = class AuroDropdown extends AuroElement$2$2 {
33836
33675
  if (triggerContentNodes) {
33837
33676
 
33838
33677
  // See if any of them are focusable elements
33839
- this.triggerContentFocusable = triggerContentNodes.some((node) => getFocusableElements$3(node).length > 0);
33678
+ this.triggerContentFocusable = triggerContentNodes.some((node) => getFocusableElements$4(node).length > 0);
33840
33679
 
33841
33680
  // If any of them are focusable elements
33842
33681
  if (this.triggerContentFocusable) {
@@ -46246,7 +46085,7 @@ let AuroHelpText$1$3 = class AuroHelpText extends i$2 {
46246
46085
  }
46247
46086
  };
46248
46087
 
46249
- var formkitVersion$7 = '202607072023';
46088
+ var formkitVersion$7 = '202607102214';
46250
46089
 
46251
46090
  // Copyright (c) 2025 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
46252
46091
  // See LICENSE in the project root for license information.
@@ -48792,11 +48631,14 @@ class AuroDatePicker extends AuroElement$5 {
48792
48631
  // what centralDate renders, causing all cells to have tabindex="-1".
48793
48632
  this.calendar.activeCellDate = null;
48794
48633
 
48795
- // Show the month containing the selected date (or today) instead of
48796
- // whichever month the user last navigated to. Route through
48797
- // updateCentralDate so centralDate stays first-of-month.
48798
- // Respect consumer-provided centralDate/calendarStartDate if no value is set.
48799
- if (this.valueObject) {
48634
+ // On open, reset the visible month to a predictable source rather than
48635
+ // whichever month the user last navigated to. Route through updateCentralDate
48636
+ // so centralDate stays first-of-month.
48637
+ // Priority: calendarFocusDate (when valid) -> value (when set) -> today (when neither is set).
48638
+ // Respect consumer-provided centralDate/calendarStartDate/minDate when neither calendarFocusDate nor value is set.
48639
+ if (this.calendarFocusDate && dateFormatter$1.isValidDate(this.calendarFocusDate)) {
48640
+ this.calendarRenderUtil.updateCentralDate(this, this.calendarFocusDateObject);
48641
+ } else if (this.valueObject) {
48800
48642
  this.calendarRenderUtil.updateCentralDate(this, this.value);
48801
48643
  } else if (!this.centralDate && !this.calendarStartDate && !this.minDate) {
48802
48644
  this.calendarRenderUtil.updateCentralDate(this, new Date());
@@ -49337,10 +49179,6 @@ class AuroDatePicker extends AuroElement$5 {
49337
49179
  }
49338
49180
  }
49339
49181
 
49340
- if (changedProperties.has('calendarFocusDate')) {
49341
- this.handleFocusDateChange();
49342
- }
49343
-
49344
49182
  if (changedProperties.has('calendarStartDate')) {
49345
49183
  this.calendar.setAttribute('calendarStartDate', this.calendarStartDate || '');
49346
49184
  }
@@ -49463,6 +49301,13 @@ class AuroDatePicker extends AuroElement$5 {
49463
49301
  this.setHasValue();
49464
49302
  }
49465
49303
 
49304
+ // Run focus-date handling AFTER value/valueEnd so that when a consumer sets
49305
+ // calendarFocusDate together with value, the focus date wins for the visible
49306
+ // month instead of being overwritten by the value branch's updateCentralDate.
49307
+ if (changedProperties.has('calendarFocusDate')) {
49308
+ this.handleFocusDateChange();
49309
+ }
49310
+
49466
49311
  if (changedProperties.has('error')) {
49467
49312
  // Error attribute is passed down to the last input in the list to control the error state
49468
49313
  // This is done to prevent error icon from displaying on both inputs in range support
@@ -49571,9 +49416,28 @@ class AuroDatePicker extends AuroElement$5 {
49571
49416
  * @returns {void}
49572
49417
  */
49573
49418
  handleClick(event) {
49574
-
49575
- // Get the initial target of the click event
49576
- const [initTarget] = event.composedPath();
49419
+ const path = event.composedPath();
49420
+ const [initTarget] = path;
49421
+ const pathIncludesBib = path.includes(this.dropdown?.bibContent);
49422
+ const triggerIsInert = this.dropdown?.trigger?.inert;
49423
+
49424
+ // When desktopModal is open, the datepicker marks the dropdown's #trigger
49425
+ // element inert to keep AT and Tab off the input. Inert also blocks pointer
49426
+ // events, so a click on the visible trigger area passes through to the
49427
+ // wrapper <div> that sits alongside #trigger in the dropdown's shadow root.
49428
+ // composedPath() then no longer contains #trigger, and the floater's
49429
+ // window-level click-outside handler treats the click as an outside click
49430
+ // and closes the bib. Suppress that misdetection here: if the click lands
49431
+ // inside the trigger's bounds and outside the bib, stop propagation before
49432
+ // it reaches the window listener.
49433
+ if (this.dropdown?.isPopoverVisible && triggerIsInert && !pathIncludesBib) {
49434
+ const triggerRect = this.dropdown.trigger?.getBoundingClientRect();
49435
+ if (triggerRect &&
49436
+ event.clientX >= triggerRect.left && event.clientX <= triggerRect.right &&
49437
+ event.clientY >= triggerRect.top && event.clientY <= triggerRect.bottom) {
49438
+ event.stopPropagation();
49439
+ }
49440
+ }
49577
49441
 
49578
49442
  // Determine if the current layout requires special handling
49579
49443
  const layoutRequiresHandling = ['snowflake'].includes(this.layout);
@@ -49582,7 +49446,7 @@ class AuroDatePicker extends AuroElement$5 {
49582
49446
  const targetIsInput = initTarget.tagName === 'INPUT';
49583
49447
  const isFocusAlreadyOnInput = this.inputList.includes(this.shadowRoot.activeElement);
49584
49448
 
49585
- if (layoutRequiresHandling && !targetIsInput && !isFocusAlreadyOnInput && !event.composedPath().includes(this.dropdown.bibContent)) {
49449
+ if (layoutRequiresHandling && !targetIsInput && !isFocusAlreadyOnInput && !pathIncludesBib) {
49586
49450
  // Focus the first input
49587
49451
  this.inputList[0].focus();
49588
49452
  }
@@ -51162,7 +51026,7 @@ let AuroHelpText$1$2 = class AuroHelpText extends i$2 {
51162
51026
  }
51163
51027
  };
51164
51028
 
51165
- var formkitVersion$1$2 = '202607072023';
51029
+ var formkitVersion$1$2 = '202607102214';
51166
51030
 
51167
51031
  // Copyright (c) 2026 Alaska Airlines. All rights reserved. Licensed under the Apache-2.0 license
51168
51032
  // See LICENSE in the project root for license information.
@@ -51503,21 +51367,6 @@ class AuroCounter extends i$2 {
51503
51367
  }
51504
51368
  }
51505
51369
 
51506
- /**
51507
- * Handles the slotchange event for the description slot.
51508
- * Updates ariaDescribedByElements on the spinbutton.
51509
- *
51510
- * @param {Event} event - The slotchange event.
51511
- * @private
51512
- */
51513
- onDescriptionSlotChange(event) {
51514
- const spinbutton = this.shadowRoot.querySelector('[role="spinbutton"]');
51515
- if (spinbutton) {
51516
- const assigned = event.target.assignedElements();
51517
- spinbutton.ariaDescribedByElements = assigned.length > 0 ? assigned : [];
51518
- }
51519
- }
51520
-
51521
51370
  updated(changedProperties) {
51522
51371
  if (changedProperties.has("value")) {
51523
51372
  this.validate();
@@ -51573,7 +51422,7 @@ class AuroCounter extends i$2 {
51573
51422
  <label class="label">
51574
51423
  <slot @slotchange="${this.onDefaultSlotChange}"></slot>
51575
51424
  </label>
51576
- <slot name="description" class="body-xs" @slotchange="${this.onDescriptionSlotChange}"></slot>
51425
+ <slot name="description" class="body-xs"></slot>
51577
51426
  </div>
51578
51427
  <div
51579
51428
  part="counterControl"
@@ -53874,12 +53723,40 @@ let AuroFloatingUI$2 = class AuroFloatingUI {
53874
53723
  return;
53875
53724
  }
53876
53725
 
53726
+ // Chrome-specific: during popover top-layer promotion after a click on a
53727
+ // slotted focusable, :focus-within can briefly evaluate false while the
53728
+ // active element is still structurally inside the trigger/bib. Fall back
53729
+ // to a shadow-piercing ancestry walk from the deep active element before
53730
+ // treating this as a real focus loss.
53731
+ try {
53732
+ let active = document.activeElement;
53733
+ while (active && active.shadowRoot && active.shadowRoot.activeElement) {
53734
+ active = active.shadowRoot.activeElement;
53735
+ }
53736
+ const targets = [element, element.trigger, element.bib].filter(Boolean);
53737
+ let node = active;
53738
+ while (node) {
53739
+ if (targets.includes(node)) {
53740
+ return;
53741
+ }
53742
+ node =
53743
+ node.parentElement ||
53744
+ (node.getRootNode && node.getRootNode().host) ||
53745
+ null;
53746
+ }
53747
+ } catch (e) {
53748
+ // Defensive: fall through to the existing close path if traversal fails.
53749
+ }
53750
+
53877
53751
  // if fullscreen bib is in fullscreen mode, do not close
53878
53752
  if (element.bib.hasAttribute("isfullscreen")) {
53879
53753
  return;
53880
53754
  }
53881
53755
 
53882
- this.hideBib("keydown");
53756
+ // eventType "focusloss" distinguishes a Tab/click-driven close from an
53757
+ // Escape keydown close. Consumers use this to decide whether to restore
53758
+ // focus to the trigger (Escape) or let it advance naturally (Tab).
53759
+ this.hideBib("focusloss");
53883
53760
  }
53884
53761
 
53885
53762
  setupHideHandlers() {
@@ -54368,7 +54245,7 @@ let AuroFloatingUI$2 = class AuroFloatingUI {
54368
54245
  };
54369
54246
 
54370
54247
  // Selectors for focusable elements
54371
- const FOCUSABLE_SELECTORS$2 = [
54248
+ const FOCUSABLE_SELECTORS$3 = [
54372
54249
  "a[href]",
54373
54250
  "button:not([disabled])",
54374
54251
  "textarea:not([disabled])",
@@ -54382,7 +54259,7 @@ const FOCUSABLE_SELECTORS$2 = [
54382
54259
  ];
54383
54260
 
54384
54261
  // List of custom components that are known to be focusable
54385
- const FOCUSABLE_COMPONENTS$2 = [
54262
+ const FOCUSABLE_COMPONENTS$3 = [
54386
54263
  "auro-checkbox",
54387
54264
  "auro-radio",
54388
54265
  "auro-dropdown",
@@ -54404,12 +54281,12 @@ const FOCUSABLE_COMPONENTS$2 = [
54404
54281
  * @param {HTMLElement} element The element to check for focusability.
54405
54282
  * @returns {boolean} True if the element is a focusable custom component, false otherwise.
54406
54283
  */
54407
- function isFocusableComponent$2(element) {
54284
+ function isFocusableComponent$3(element) {
54408
54285
  const componentName = element.tagName.toLowerCase();
54409
54286
 
54410
54287
  // Guard Clause: Element is a focusable component
54411
54288
  if (
54412
- !FOCUSABLE_COMPONENTS$2.some(
54289
+ !FOCUSABLE_COMPONENTS$3.some(
54413
54290
  (name) => element.hasAttribute(name) || componentName === name,
54414
54291
  )
54415
54292
  )
@@ -54433,7 +54310,7 @@ function isFocusableComponent$2(element) {
54433
54310
  * @param {HTMLElement} element The element whose tabindex to read.
54434
54311
  * @returns {?number} The numeric tabindex or null if missing/invalid.
54435
54312
  */
54436
- function getNumericTabIndex$2(element) {
54313
+ function getNumericTabIndex$3(element) {
54437
54314
  const raw = element.getAttribute("tabindex");
54438
54315
  if (raw == null) return null;
54439
54316
 
@@ -54449,7 +54326,7 @@ function getNumericTabIndex$2(element) {
54449
54326
  * @param {HTMLElement} container The container to search within
54450
54327
  * @returns {Array<HTMLElement>} An array of focusable elements within the container.
54451
54328
  */
54452
- function getFocusableElements$2(container) {
54329
+ function getFocusableElements$3(container) {
54453
54330
  // Get elements in DOM order by walking the tree
54454
54331
  const orderedFocusableElements = [];
54455
54332
 
@@ -54458,7 +54335,7 @@ function getFocusableElements$2(container) {
54458
54335
  // Check if current element is focusable
54459
54336
  if (root.nodeType === Node.ELEMENT_NODE) {
54460
54337
  // Check if this is a custom component that is focusable
54461
- const isComponentFocusable = isFocusableComponent$2(root);
54338
+ const isComponentFocusable = isFocusableComponent$3(root);
54462
54339
 
54463
54340
  if (isComponentFocusable) {
54464
54341
  // Add the component itself as a focusable element and don't traverse its shadow DOM
@@ -54467,7 +54344,7 @@ function getFocusableElements$2(container) {
54467
54344
  }
54468
54345
 
54469
54346
  // Check if the element itself matches any selector
54470
- for (const selector of FOCUSABLE_SELECTORS$2) {
54347
+ for (const selector of FOCUSABLE_SELECTORS$3) {
54471
54348
  if (root.matches?.(selector)) {
54472
54349
  orderedFocusableElements.push(root);
54473
54350
  break; // Once we know it's focusable, no need to check other selectors
@@ -54521,20 +54398,20 @@ function getFocusableElements$2(container) {
54521
54398
 
54522
54399
  // First extract elements with valid positive tabindex
54523
54400
  const elementsWithTabindex = uniqueElements.filter((el) => {
54524
- const tabindex = getNumericTabIndex$2(el);
54401
+ const tabindex = getNumericTabIndex$3(el);
54525
54402
  return tabindex !== null && tabindex > 0;
54526
54403
  });
54527
54404
 
54528
54405
  // Sort these elements by their tabindex value
54529
54406
  elementsWithTabindex.sort((a, b) => {
54530
- const aIndex = getNumericTabIndex$2(a) ?? 0;
54531
- const bIndex = getNumericTabIndex$2(b) ?? 0;
54407
+ const aIndex = getNumericTabIndex$3(a) ?? 0;
54408
+ const bIndex = getNumericTabIndex$3(b) ?? 0;
54532
54409
  return aIndex - bIndex;
54533
54410
  });
54534
54411
 
54535
54412
  // Elements without tabindex (preserving their original order)
54536
54413
  const elementsWithoutTabindex = uniqueElements.filter((el) => {
54537
- const tabindex = getNumericTabIndex$2(el);
54414
+ const tabindex = getNumericTabIndex$3(el);
54538
54415
 
54539
54416
  // Elements without tabindex or with tabindex of 0 stay in DOM order
54540
54417
  return tabindex === null || tabindex === 0;
@@ -54549,199 +54426,6 @@ function getFocusableElements$2(container) {
54549
54426
  return tabIndexedUniqueElements;
54550
54427
  }
54551
54428
 
54552
- /**
54553
- * FocusTrap manages keyboard focus within a specified container element, ensuring that focus does not leave the container when tabbing.
54554
- * It is commonly used for modal dialogs or overlays to improve accessibility by trapping focus within interactive UI components.
54555
- */
54556
- let FocusTrap$2 = class FocusTrap {
54557
- /**
54558
- * Creates a new FocusTrap instance for the given container element.
54559
- * Initializes event listeners and prepares the container for focus management.
54560
- *
54561
- * @param {HTMLElement} container The DOM element to trap focus within.
54562
- * @param {boolean} [controlTabOrder=false] If true enables manual control of the tab order by the FocusTrap.
54563
- * @throws {Error} If the provided container is not a valid HTMLElement.
54564
- */
54565
- constructor(container, controlTabOrder = false) {
54566
- if (!container || !(container instanceof HTMLElement)) {
54567
- throw new Error("FocusTrap requires a valid HTMLElement.");
54568
- }
54569
-
54570
- this.container = container;
54571
- this.tabDirection = "forward"; // or 'backward';
54572
- this.controlTabOrder = controlTabOrder;
54573
-
54574
- this._init();
54575
- }
54576
-
54577
- /**
54578
- * Initializes the focus trap by setting up event listeners and attributes on the container.
54579
- * Prepares the container for focus management, including support for shadow DOM and inert attributes.
54580
- *
54581
- * @private
54582
- */
54583
- _init() {
54584
- // Add inert attribute to prevent focusing programmatically as well (if supported)
54585
- if ("inert" in HTMLElement.prototype) {
54586
- this.container.inert = false; // Ensure the container isn't inert
54587
- this.container.setAttribute("data-focus-trap-container", true); // Mark for identification
54588
- }
54589
-
54590
- // Track tab direction
54591
- this.container.addEventListener("keydown", this._onKeydown);
54592
- }
54593
-
54594
- /**
54595
- * Gets an array of currently active (focused) elements in the document and shadow DOM.
54596
- * @returns {Array<HTMLElement>} An array of focusable elements within the container.
54597
- * @private
54598
- */
54599
- _getActiveElements() {
54600
- // Get the active element(s) in the document and shadow root
54601
- // This will include the active element in the shadow DOM if it exists
54602
- // Active element may be inside the shadow DOM depending on delegatesFocus, so we need to check both
54603
- let { activeElement } = document;
54604
- const actives = [activeElement];
54605
- while (activeElement?.shadowRoot?.activeElement) {
54606
- actives.push(activeElement.shadowRoot.activeElement);
54607
- activeElement = activeElement.shadowRoot.activeElement;
54608
- }
54609
- return actives;
54610
- }
54611
-
54612
- /**
54613
- * Gets the next focus index based on the current index and focusable elements.
54614
- * @param {number} currentIndex The current index of the focused element.
54615
- * @param {Array<HTMLElement>} focusables The array of focusable elements.
54616
- * @returns {number|null} The next focus index or null if not determined.
54617
- */
54618
- _getNextFocusIndex(currentIndex, focusables, actives) {
54619
- if (this.controlTabOrder) {
54620
- // Calculate the new index based on the current index and tab direction
54621
- let newFocusIndex =
54622
- currentIndex + (this.tabDirection === "forward" ? 1 : -1);
54623
-
54624
- // Wrap-around logic
54625
- if (newFocusIndex < 0) newFocusIndex = focusables.length - 1;
54626
- if (newFocusIndex >= focusables.length) newFocusIndex = 0;
54627
-
54628
- // Early return with the new index
54629
- return newFocusIndex;
54630
- }
54631
-
54632
- // Determine if we need to wrap
54633
- const atFirst =
54634
- actives.includes(focusables[0]) || actives.includes(this.container);
54635
- const atLast = actives.includes(focusables[focusables.length - 1]);
54636
-
54637
- // Only wrap if at the ends
54638
- if (this.tabDirection === "backward" && atFirst) {
54639
- return focusables.length - 1;
54640
- }
54641
-
54642
- if (this.tabDirection === "forward" && atLast) {
54643
- return 0;
54644
- }
54645
-
54646
- // No wrap, so don't change focus, return early
54647
- return null;
54648
- }
54649
-
54650
- /**
54651
- * Handles the Tab key press event to manage focus within the container.
54652
- * @param {KeyboardEvent} e The keyboard event triggered by the user.
54653
- * @returns {void}
54654
- */
54655
- _handleTabKey(e) {
54656
- // Update the focusable elements
54657
- const focusables = this._getFocusableElements();
54658
-
54659
- // If there are no focusable elements, exit
54660
- if (!focusables.length) return;
54661
-
54662
- // Set the tab direction based on the key pressed
54663
- this.tabDirection = e.shiftKey ? "backward" : "forward";
54664
-
54665
- // Get the active elements that are currently focused
54666
- const actives = this._getActiveElements();
54667
-
54668
- // If we're at either end of the focusable elements, wrap around to the other end
54669
- let focusIndex = focusables.findIndex((el) => actives.includes(el));
54670
-
54671
- // Fallback if we have no focused element
54672
- if (focusIndex === -1) focusIndex = 0;
54673
-
54674
- // Get the next focus index based on the current focus index, tab direction, and controlTabOrder setting
54675
- // Is null if no new focus index is determined
54676
- const newFocusIndex = this._getNextFocusIndex(
54677
- focusIndex,
54678
- focusables,
54679
- actives,
54680
- );
54681
-
54682
- // If we have a new focus index, set focus to that element
54683
- if (newFocusIndex !== null) {
54684
- e.preventDefault();
54685
- focusables[newFocusIndex].focus();
54686
- }
54687
- }
54688
-
54689
- /**
54690
- * Catches the keydown event
54691
- * @param {KeyboardEvent} e The keyboard event triggered by user interaction.
54692
- * @private
54693
- */
54694
- _onKeydown = (e) => {
54695
- // Handle tab
54696
- if (e.key === "Tab") this._handleTabKey(e);
54697
- };
54698
-
54699
- /**
54700
- * Retrieves all focusable elements within the container in DOM order, including those in shadow DOM and slots.
54701
- * Returns a unique, ordered array of elements that can receive focus.
54702
- *
54703
- * @returns {Array<HTMLElement>} An array of focusable elements within the container.
54704
- * @private
54705
- */
54706
- _getFocusableElements() {
54707
- // Use the imported utility function to get focusable elements
54708
- const elements = getFocusableElements$2(this.container);
54709
-
54710
- // Return the elements found
54711
- return elements;
54712
- }
54713
-
54714
- /**
54715
- * Moves focus to the first focusable element within the container.
54716
- * Useful for setting initial focus when activating the focus trap.
54717
- */
54718
- focusFirstElement() {
54719
- const focusables = this._getFocusableElements();
54720
- if (focusables.length) focusables[0].focus();
54721
- }
54722
-
54723
- /**
54724
- * Moves focus to the last focusable element within the container.
54725
- * Useful for setting focus when deactivating or cycling focus in reverse.
54726
- */
54727
- focusLastElement() {
54728
- const focusables = this._getFocusableElements();
54729
- if (focusables.length) focusables[focusables.length - 1].focus();
54730
- }
54731
-
54732
- /**
54733
- * Removes event listeners and attributes added by the focus trap.
54734
- * Call this method to clean up when the focus trap is no longer needed.
54735
- */
54736
- disconnect() {
54737
- if (this.container.hasAttribute("data-focus-trap-container")) {
54738
- this.container.removeAttribute("data-focus-trap-container");
54739
- }
54740
-
54741
- this.container.removeEventListener("keydown", this._onKeydown);
54742
- }
54743
- };
54744
-
54745
54429
  // Copyright (c) Alaska Air. All right reserved. Licensed under the Apache-2.0 license
54746
54430
  // See LICENSE in the project root for license information.
54747
54431
 
@@ -55239,7 +54923,7 @@ let AuroDropdownBib$2 = class AuroDropdownBib extends i$2 {
55239
54923
  classes[`shape-${this.shape}`] = true;
55240
54924
 
55241
54925
  return u$d`
55242
- <dialog class="${e$2(classes)}" part="bibContainer" role="${o$4(this.dialogRole)}" aria-labelledby="${o$4(this.dialogLabel ? 'dialogLabel' : undefined)}">
54926
+ <dialog tabindex="-1" class="${e$2(classes)}" part="bibContainer" role="${o$4(this.dialogRole)}" aria-labelledby="${o$4(this.dialogLabel ? 'dialogLabel' : undefined)}">
55243
54927
  ${this.dialogLabel ? u$d`<span id="dialogLabel" class="util_displayHiddenVisually">${this.dialogLabel}</span>` : ''}
55244
54928
  <slot></slot>
55245
54929
  <span id="srAnnouncement" class="util_displayHiddenVisually" aria-live="polite" role="status"></span>
@@ -55490,7 +55174,7 @@ let AuroHelpText$6 = class AuroHelpText extends i$2 {
55490
55174
  }
55491
55175
  };
55492
55176
 
55493
- var formkitVersion$6 = '202607072023';
55177
+ var formkitVersion$6 = '202607102214';
55494
55178
 
55495
55179
  let AuroElement$1$2 = class AuroElement extends i$2 {
55496
55180
  static get properties() {
@@ -55781,7 +55465,7 @@ let AuroDropdown$2 = class AuroDropdown extends AuroElement$1$2 {
55781
55465
  */
55782
55466
  focus() {
55783
55467
  if (this.isPopoverVisible && this.bibContent) {
55784
- const focusables = getFocusableElements$2(this.bibContent);
55468
+ const focusables = getFocusableElements$3(this.bibContent);
55785
55469
  if (focusables.length > 0) {
55786
55470
  focusables[0].focus();
55787
55471
  }
@@ -56244,7 +55928,10 @@ let AuroDropdown$2 = class AuroDropdown extends AuroElement$1$2 {
56244
55928
  }
56245
55929
 
56246
55930
 
56247
- if (!this.isPopoverVisible) {
55931
+ // On Tab-driven close (eventType "focusloss"), let focus advance naturally
55932
+ // — restoring to the trigger would trap the user on this dropdown, forcing
55933
+ // an extra Tab to move on. Escape and outside-click still restore.
55934
+ if (!this.isPopoverVisible && eventType !== "focusloss") {
56248
55935
  // wait til the bib gets fully closed and rendered
56249
55936
  setTimeout(() => {
56250
55937
  // Skip if the bib re-opened, or if focus moved intentionally outside the dropdown (not to body).
@@ -56399,7 +56086,7 @@ let AuroDropdown$2 = class AuroDropdown extends AuroElement$1$2 {
56399
56086
  }
56400
56087
 
56401
56088
  // Collect focusable elements from the bib content.
56402
- const focusables = getFocusableElements$2(this.bibContent);
56089
+ const focusables = getFocusableElements$3(this.bibContent);
56403
56090
 
56404
56091
  // Fallback: try from slotted content directly
56405
56092
  if (!focusables.length) {
@@ -56408,7 +56095,7 @@ let AuroDropdown$2 = class AuroDropdown extends AuroElement$1$2 {
56408
56095
 
56409
56096
  for (const node of assignedNodes) {
56410
56097
  if (node.nodeType === Node.ELEMENT_NODE) {
56411
- focusables.push(...getFocusableElements$2(node));
56098
+ focusables.push(...getFocusableElements$3(node));
56412
56099
  }
56413
56100
  }
56414
56101
  }
@@ -56468,21 +56155,22 @@ let AuroDropdown$2 = class AuroDropdown extends AuroElement$1$2 {
56468
56155
 
56469
56156
  // Move initial focus into the bib content, matching FocusTrap behavior
56470
56157
  requestAnimationFrame(() => {
56471
- const focusables = getFocusableElements$2(this.bibContent);
56158
+ const focusables = getFocusableElements$3(this.bibContent);
56472
56159
  if (focusables.length) {
56473
56160
  focusables[0].focus();
56474
56161
  }
56475
56162
  });
56476
56163
  } else {
56477
- // Normal desktop: use FocusTrap on the bib element.
56478
- // Defer focusFirstElement to the next frame because the popover
56479
- // is positioned asynchronously by Floating UI — calling focus()
56480
- // synchronously here would target elements with zero dimensions
56481
- // and the focus call would be silently ignored.
56482
- this.focusTrap = new FocusTrap$2(this.bibContent);
56164
+ // Normal desktop (non-modal): move initial focus into the bib but
56165
+ // don't trap Tab. Tab should exit the bib and let the floater's
56166
+ // handleFocusLoss close it, matching native <select>/<details>
56167
+ // behavior. Deferred one frame because Floating UI positions the
56168
+ // popover asynchronously a synchronous focus() would target
56169
+ // zero-dimension elements and be silently ignored.
56483
56170
  requestAnimationFrame(() => {
56484
- if (this.focusTrap) {
56485
- this.focusTrap.focusFirstElement();
56171
+ const focusables = getFocusableElements$3(this.bibContent);
56172
+ if (focusables.length) {
56173
+ focusables[0].focus();
56486
56174
  }
56487
56175
  });
56488
56176
  }
@@ -56698,7 +56386,7 @@ let AuroDropdown$2 = class AuroDropdown extends AuroElement$1$2 {
56698
56386
  if (triggerContentNodes) {
56699
56387
 
56700
56388
  // See if any of them are focusable elements
56701
- this.triggerContentFocusable = triggerContentNodes.some((node) => getFocusableElements$2(node).length > 0);
56389
+ this.triggerContentFocusable = triggerContentNodes.some((node) => getFocusableElements$3(node).length > 0);
56702
56390
 
56703
56391
  // If any of them are focusable elements
56704
56392
  if (this.triggerContentFocusable) {
@@ -58080,6 +57768,19 @@ class AuroCounterGroup extends AuroElement$4 {
58080
57768
 
58081
57769
  if (this.isDropdown) {
58082
57770
  applyKeyboardStrategy$1$2(this, counterGroupKeyboardStrategy);
57771
+
57772
+ // noHideOnThisFocusLoss=true on the dropdown prevents handleFocusLoss from
57773
+ // closing the bib when focus moves out via Tab. Close explicitly via focusout:
57774
+ // if relatedTarget is outside the counter-group's light DOM, focus has left.
57775
+ this.addEventListener('focusout', (event) => {
57776
+ if (!this.dropdown?.isPopoverVisible || this.dropdown?.isBibFullscreen) {
57777
+ return;
57778
+ }
57779
+ if (event.relatedTarget && this.contains(event.relatedTarget)) {
57780
+ return;
57781
+ }
57782
+ this.hideBib();
57783
+ });
58083
57784
  }
58084
57785
  }
58085
57786
 
@@ -59470,7 +59171,7 @@ let AuroHelpText$5 = class AuroHelpText extends i$2 {
59470
59171
  }
59471
59172
  };
59472
59173
 
59473
- var formkitVersion$5 = '202607072023';
59174
+ var formkitVersion$5 = '202607102214';
59474
59175
 
59475
59176
  // Copyright (c) Alaska Air. All right reserved. Licensed under the Apache-2.0 license
59476
59177
  // See LICENSE in the project root for license information.
@@ -61235,7 +60936,7 @@ let AuroHelpText$4 = class AuroHelpText extends i$2 {
61235
60936
  }
61236
60937
  };
61237
60938
 
61238
- var formkitVersion$4 = '202607072023';
60939
+ var formkitVersion$4 = '202607102214';
61239
60940
 
61240
60941
  // Copyright (c) 2026 Alaska Airlines. All rights reserved. Licensed under the Apache-2.0 license
61241
60942
  // See LICENSE in the project root for license information.
@@ -62426,6 +62127,188 @@ function navigateArrow$1(component, direction, options = {}) {
62426
62127
  }
62427
62128
  }
62428
62129
 
62130
+ // Selectors for focusable elements
62131
+ const FOCUSABLE_SELECTORS$1 = [
62132
+ "a[href]",
62133
+ "button:not([disabled])",
62134
+ "textarea:not([disabled])",
62135
+ "input:not([disabled])",
62136
+ "select:not([disabled])",
62137
+ '[role="tab"]:not([disabled])',
62138
+ '[role="link"]:not([disabled])',
62139
+ '[role="button"]:not([disabled])',
62140
+ '[tabindex]:not([tabindex="-1"])',
62141
+ '[contenteditable]:not([contenteditable="false"])',
62142
+ ];
62143
+
62144
+ // List of custom components that are known to be focusable
62145
+ const FOCUSABLE_COMPONENTS$1 = [
62146
+ "auro-checkbox",
62147
+ "auro-radio",
62148
+ "auro-dropdown",
62149
+ "auro-button",
62150
+ "auro-combobox",
62151
+ "auro-input",
62152
+ "auro-counter",
62153
+ // 'auro-menu', // Auro menu is not focusable by default, it uses a different interaction model
62154
+ "auro-select",
62155
+ "auro-datepicker",
62156
+ "auro-hyperlink",
62157
+ "auro-accordion",
62158
+ ];
62159
+
62160
+ /**
62161
+ * Determines if a given element is a custom focusable component.
62162
+ * Returns true if the element matches a known focusable component and is not disabled.
62163
+ *
62164
+ * @param {HTMLElement} element The element to check for focusability.
62165
+ * @returns {boolean} True if the element is a focusable custom component, false otherwise.
62166
+ */
62167
+ function isFocusableComponent$1(element) {
62168
+ const componentName = element.tagName.toLowerCase();
62169
+
62170
+ // Guard Clause: Element is a focusable component
62171
+ if (
62172
+ !FOCUSABLE_COMPONENTS$1.some(
62173
+ (name) => element.hasAttribute(name) || componentName === name,
62174
+ )
62175
+ )
62176
+ return false;
62177
+
62178
+ // Guard Clause: Element is not disabled
62179
+ if (element.hasAttribute("disabled")) return false;
62180
+
62181
+ // Guard Clause: The element is a hyperlink and has no href attribute
62182
+ if (componentName.match("hyperlink") && !element.hasAttribute("href"))
62183
+ return false;
62184
+
62185
+ // If all guard clauses pass, the element is a focusable component
62186
+ return true;
62187
+ }
62188
+
62189
+ /**
62190
+ * Safely get a numeric tabindex for an element.
62191
+ * Returns a number if the tabindex is a valid integer, otherwise null.
62192
+ *
62193
+ * @param {HTMLElement} element The element whose tabindex to read.
62194
+ * @returns {?number} The numeric tabindex or null if missing/invalid.
62195
+ */
62196
+ function getNumericTabIndex$1(element) {
62197
+ const raw = element.getAttribute("tabindex");
62198
+ if (raw == null) return null;
62199
+
62200
+ const value = Number.parseInt(raw, 10);
62201
+ return Number.isNaN(value) ? null : value;
62202
+ }
62203
+
62204
+ /**
62205
+ * Retrieves all focusable elements within the container in DOM order, including those in shadow DOM and slots.
62206
+ * Returns a unique, ordered array of elements that can receive focus.
62207
+ * Also sorts elements with tabindex first, preserving their order.
62208
+ *
62209
+ * @param {HTMLElement} container The container to search within
62210
+ * @returns {Array<HTMLElement>} An array of focusable elements within the container.
62211
+ */
62212
+ function getFocusableElements$1(container) {
62213
+ // Get elements in DOM order by walking the tree
62214
+ const orderedFocusableElements = [];
62215
+
62216
+ // Define a recursive function to collect focusable elements in DOM order
62217
+ const collectFocusableElements = (root) => {
62218
+ // Check if current element is focusable
62219
+ if (root.nodeType === Node.ELEMENT_NODE) {
62220
+ // Check if this is a custom component that is focusable
62221
+ const isComponentFocusable = isFocusableComponent$1(root);
62222
+
62223
+ if (isComponentFocusable) {
62224
+ // Add the component itself as a focusable element and don't traverse its shadow DOM
62225
+ orderedFocusableElements.push(root);
62226
+ return; // Skip traversing inside this component
62227
+ }
62228
+
62229
+ // Check if the element itself matches any selector
62230
+ for (const selector of FOCUSABLE_SELECTORS$1) {
62231
+ if (root.matches?.(selector)) {
62232
+ orderedFocusableElements.push(root);
62233
+ break; // Once we know it's focusable, no need to check other selectors
62234
+ }
62235
+ }
62236
+
62237
+ // Process shadow DOM only for non-Auro components
62238
+ if (root.shadowRoot) {
62239
+ // Process shadow DOM children in order
62240
+ if (root.shadowRoot.children) {
62241
+ Array.from(root.shadowRoot.children).forEach((child) => {
62242
+ collectFocusableElements(child);
62243
+ });
62244
+ }
62245
+ }
62246
+
62247
+ // Process slots and their assigned nodes in order
62248
+ if (root.tagName === "SLOT") {
62249
+ const assignedNodes = root.assignedNodes({ flatten: true });
62250
+ for (const node of assignedNodes) {
62251
+ collectFocusableElements(node);
62252
+ }
62253
+ } else {
62254
+ // Process light DOM children in order
62255
+ if (root.children) {
62256
+ Array.from(root.children).forEach((child) => {
62257
+ collectFocusableElements(child);
62258
+ });
62259
+ }
62260
+ }
62261
+ }
62262
+ };
62263
+
62264
+ // Start the traversal from the container
62265
+ collectFocusableElements(container);
62266
+
62267
+ // Remove duplicates that might have been collected through different paths
62268
+ // while preserving order
62269
+ const uniqueElements = [];
62270
+ const seen = new Set();
62271
+
62272
+ for (const element of orderedFocusableElements) {
62273
+ if (!seen.has(element)) {
62274
+ seen.add(element);
62275
+ uniqueElements.push(element);
62276
+ }
62277
+ }
62278
+
62279
+ // Move tab-indexed elements to the front while preserving their order
62280
+ // This ensures that elements with tabindex are prioritized in the focus order
62281
+
62282
+ // First extract elements with valid positive tabindex
62283
+ const elementsWithTabindex = uniqueElements.filter((el) => {
62284
+ const tabindex = getNumericTabIndex$1(el);
62285
+ return tabindex !== null && tabindex > 0;
62286
+ });
62287
+
62288
+ // Sort these elements by their tabindex value
62289
+ elementsWithTabindex.sort((a, b) => {
62290
+ const aIndex = getNumericTabIndex$1(a) ?? 0;
62291
+ const bIndex = getNumericTabIndex$1(b) ?? 0;
62292
+ return aIndex - bIndex;
62293
+ });
62294
+
62295
+ // Elements without tabindex (preserving their original order)
62296
+ const elementsWithoutTabindex = uniqueElements.filter((el) => {
62297
+ const tabindex = getNumericTabIndex$1(el);
62298
+
62299
+ // Elements without tabindex or with tabindex of 0 stay in DOM order
62300
+ return tabindex === null || tabindex === 0;
62301
+ });
62302
+
62303
+ // Combine both arrays with tabindex elements first
62304
+ const tabIndexedUniqueElements = [
62305
+ ...elementsWithTabindex,
62306
+ ...elementsWithoutTabindex,
62307
+ ];
62308
+
62309
+ return tabIndexedUniqueElements;
62310
+ }
62311
+
62429
62312
  /* eslint-disable no-underscore-dangle */
62430
62313
 
62431
62314
  /**
@@ -62471,6 +62354,82 @@ function reconcileMenuIndex(menu) {
62471
62354
  }
62472
62355
  }
62473
62356
 
62357
+ /**
62358
+ * Commit the highlighted option and close the bib.
62359
+ * @param {Element} component - The auro-combobox host element.
62360
+ */
62361
+ function selectAndClose(component) {
62362
+ reconcileMenuIndex(component.menu);
62363
+ component.menu.makeSelection();
62364
+ component.hideBib();
62365
+ }
62366
+
62367
+ /**
62368
+ * Whether `el` is currently visible enough to receive focus. Prefers the
62369
+ * browser's `checkVisibility()` (Chrome/Safari; Firefox behind a flag until
62370
+ * recently); otherwise combines a display/visibility check with an
62371
+ * ancestor-hidden probe that keeps position:fixed elements visible.
62372
+ * @param {Element} el - The element to test.
62373
+ * @returns {boolean}
62374
+ */
62375
+ function isVisibleForFocus(el) {
62376
+ if (typeof el.checkVisibility === 'function') {
62377
+ return el.checkVisibility();
62378
+ }
62379
+ const style = el.ownerDocument.defaultView.getComputedStyle(el);
62380
+ if (style.display === 'none' || style.visibility === 'hidden') {
62381
+ return false;
62382
+ }
62383
+ return el.offsetParent !== null || style.position === 'fixed';
62384
+ }
62385
+
62386
+ /**
62387
+ * Return the tab stop that comes before `component` in page tab order,
62388
+ * skipping any hidden entries the walker doesn't filter itself.
62389
+ * @param {Element} component - The auro-combobox host element.
62390
+ * @returns {Element|null}
62391
+ */
62392
+ function getPreviousTabStop(component) {
62393
+ const tabStops = getFocusableElements$1(component.ownerDocument.body);
62394
+ const componentIndex = tabStops.indexOf(component);
62395
+ for (let index = componentIndex - 1; index >= 0; index -= 1) {
62396
+ if (isVisibleForFocus(tabStops[index])) {
62397
+ return tabStops[index];
62398
+ }
62399
+ }
62400
+ return null;
62401
+ }
62402
+
62403
+ /**
62404
+ * Commit the highlighted option, close the bib, and move focus to the tab
62405
+ * stop before the combobox — the Shift+Tab exit path (AB#1592239).
62406
+ * Returns true when this function moved focus and the caller should
62407
+ * preventDefault; false when no previous tab stop was found and the browser's
62408
+ * native traversal should run.
62409
+ * @param {Element} component - The auro-combobox host element.
62410
+ * @returns {boolean}
62411
+ */
62412
+ function selectAndExitBackward(component) {
62413
+ const previousTabStop = getPreviousTabStop(component);
62414
+
62415
+ // Opts this selection out of setClearBtnFocus so the focus move below
62416
+ // isn't clobbered. Consumed by auro-combobox's selection listener; also
62417
+ // cleared via microtask in case makeSelection is a no-op and the listener
62418
+ // never fires (microtasks run before the next user event, so this can't
62419
+ // leak into an unrelated selection).
62420
+ component._suppressClearBtnFocusOnSelection = true;
62421
+ selectAndClose(component);
62422
+ queueMicrotask(() => {
62423
+ component._suppressClearBtnFocusOnSelection = false;
62424
+ });
62425
+
62426
+ if (!previousTabStop) {
62427
+ return false;
62428
+ }
62429
+ doubleRaf$1(() => previousTabStop.focus());
62430
+ return true;
62431
+ }
62432
+
62474
62433
  const comboboxKeyboardStrategy = {
62475
62434
  ArrowDown(component, evt, ctx) {
62476
62435
  // If the clear button has focus, let the browser handle ArrowDown normally.
@@ -62570,18 +62529,17 @@ const comboboxKeyboardStrategy = {
62570
62529
 
62571
62530
  Tab(component, evt, ctx) {
62572
62531
  if (ctx.isExpanded && !isClearBtnFocused(ctx)) {
62573
- // When the clear button is focused, Tab events do not bubble out of
62574
- // its shadow DOM, so this handler only fires when the clear button
62575
- // is NOT focused. In that case, select the active option and close.
62576
- reconcileMenuIndex(component.menu);
62577
- component.menu.makeSelection();
62578
- component.hideBib();
62532
+ if (evt.shiftKey) {
62533
+ if (selectAndExitBackward(component)) {
62534
+ evt.preventDefault();
62535
+ }
62536
+ return;
62537
+ }
62538
+
62539
+ selectAndClose(component);
62579
62540
 
62580
- // In fullscreen modal mode, closing the dialog does not
62581
- // automatically restores focus to the input. In the tab case,
62582
- // Explicitly move focus to the trigger's clear button so the
62583
- // user can continues tabbing through the page normally.
62584
- if (ctx.isModal && !evt.shiftKey) {
62541
+ if (ctx.isModal) {
62542
+ // Fullscreen close does not automatically restore focus to the input.
62585
62543
  component.setClearBtnFocus();
62586
62544
  }
62587
62545
  }
@@ -64840,12 +64798,40 @@ let AuroFloatingUI$1 = class AuroFloatingUI {
64840
64798
  return;
64841
64799
  }
64842
64800
 
64801
+ // Chrome-specific: during popover top-layer promotion after a click on a
64802
+ // slotted focusable, :focus-within can briefly evaluate false while the
64803
+ // active element is still structurally inside the trigger/bib. Fall back
64804
+ // to a shadow-piercing ancestry walk from the deep active element before
64805
+ // treating this as a real focus loss.
64806
+ try {
64807
+ let active = document.activeElement;
64808
+ while (active && active.shadowRoot && active.shadowRoot.activeElement) {
64809
+ active = active.shadowRoot.activeElement;
64810
+ }
64811
+ const targets = [element, element.trigger, element.bib].filter(Boolean);
64812
+ let node = active;
64813
+ while (node) {
64814
+ if (targets.includes(node)) {
64815
+ return;
64816
+ }
64817
+ node =
64818
+ node.parentElement ||
64819
+ (node.getRootNode && node.getRootNode().host) ||
64820
+ null;
64821
+ }
64822
+ } catch (e) {
64823
+ // Defensive: fall through to the existing close path if traversal fails.
64824
+ }
64825
+
64843
64826
  // if fullscreen bib is in fullscreen mode, do not close
64844
64827
  if (element.bib.hasAttribute("isfullscreen")) {
64845
64828
  return;
64846
64829
  }
64847
64830
 
64848
- this.hideBib("keydown");
64831
+ // eventType "focusloss" distinguishes a Tab/click-driven close from an
64832
+ // Escape keydown close. Consumers use this to decide whether to restore
64833
+ // focus to the trigger (Escape) or let it advance naturally (Tab).
64834
+ this.hideBib("focusloss");
64849
64835
  }
64850
64836
 
64851
64837
  setupHideHandlers() {
@@ -65334,7 +65320,7 @@ let AuroFloatingUI$1 = class AuroFloatingUI {
65334
65320
  };
65335
65321
 
65336
65322
  // Selectors for focusable elements
65337
- const FOCUSABLE_SELECTORS$1 = [
65323
+ const FOCUSABLE_SELECTORS$2 = [
65338
65324
  "a[href]",
65339
65325
  "button:not([disabled])",
65340
65326
  "textarea:not([disabled])",
@@ -65348,7 +65334,7 @@ const FOCUSABLE_SELECTORS$1 = [
65348
65334
  ];
65349
65335
 
65350
65336
  // List of custom components that are known to be focusable
65351
- const FOCUSABLE_COMPONENTS$1 = [
65337
+ const FOCUSABLE_COMPONENTS$2 = [
65352
65338
  "auro-checkbox",
65353
65339
  "auro-radio",
65354
65340
  "auro-dropdown",
@@ -65370,12 +65356,12 @@ const FOCUSABLE_COMPONENTS$1 = [
65370
65356
  * @param {HTMLElement} element The element to check for focusability.
65371
65357
  * @returns {boolean} True if the element is a focusable custom component, false otherwise.
65372
65358
  */
65373
- function isFocusableComponent$1(element) {
65359
+ function isFocusableComponent$2(element) {
65374
65360
  const componentName = element.tagName.toLowerCase();
65375
65361
 
65376
65362
  // Guard Clause: Element is a focusable component
65377
65363
  if (
65378
- !FOCUSABLE_COMPONENTS$1.some(
65364
+ !FOCUSABLE_COMPONENTS$2.some(
65379
65365
  (name) => element.hasAttribute(name) || componentName === name,
65380
65366
  )
65381
65367
  )
@@ -65399,7 +65385,7 @@ function isFocusableComponent$1(element) {
65399
65385
  * @param {HTMLElement} element The element whose tabindex to read.
65400
65386
  * @returns {?number} The numeric tabindex or null if missing/invalid.
65401
65387
  */
65402
- function getNumericTabIndex$1(element) {
65388
+ function getNumericTabIndex$2(element) {
65403
65389
  const raw = element.getAttribute("tabindex");
65404
65390
  if (raw == null) return null;
65405
65391
 
@@ -65415,7 +65401,7 @@ function getNumericTabIndex$1(element) {
65415
65401
  * @param {HTMLElement} container The container to search within
65416
65402
  * @returns {Array<HTMLElement>} An array of focusable elements within the container.
65417
65403
  */
65418
- function getFocusableElements$1(container) {
65404
+ function getFocusableElements$2(container) {
65419
65405
  // Get elements in DOM order by walking the tree
65420
65406
  const orderedFocusableElements = [];
65421
65407
 
@@ -65424,7 +65410,7 @@ function getFocusableElements$1(container) {
65424
65410
  // Check if current element is focusable
65425
65411
  if (root.nodeType === Node.ELEMENT_NODE) {
65426
65412
  // Check if this is a custom component that is focusable
65427
- const isComponentFocusable = isFocusableComponent$1(root);
65413
+ const isComponentFocusable = isFocusableComponent$2(root);
65428
65414
 
65429
65415
  if (isComponentFocusable) {
65430
65416
  // Add the component itself as a focusable element and don't traverse its shadow DOM
@@ -65433,7 +65419,7 @@ function getFocusableElements$1(container) {
65433
65419
  }
65434
65420
 
65435
65421
  // Check if the element itself matches any selector
65436
- for (const selector of FOCUSABLE_SELECTORS$1) {
65422
+ for (const selector of FOCUSABLE_SELECTORS$2) {
65437
65423
  if (root.matches?.(selector)) {
65438
65424
  orderedFocusableElements.push(root);
65439
65425
  break; // Once we know it's focusable, no need to check other selectors
@@ -65487,20 +65473,20 @@ function getFocusableElements$1(container) {
65487
65473
 
65488
65474
  // First extract elements with valid positive tabindex
65489
65475
  const elementsWithTabindex = uniqueElements.filter((el) => {
65490
- const tabindex = getNumericTabIndex$1(el);
65476
+ const tabindex = getNumericTabIndex$2(el);
65491
65477
  return tabindex !== null && tabindex > 0;
65492
65478
  });
65493
65479
 
65494
65480
  // Sort these elements by their tabindex value
65495
65481
  elementsWithTabindex.sort((a, b) => {
65496
- const aIndex = getNumericTabIndex$1(a) ?? 0;
65497
- const bIndex = getNumericTabIndex$1(b) ?? 0;
65482
+ const aIndex = getNumericTabIndex$2(a) ?? 0;
65483
+ const bIndex = getNumericTabIndex$2(b) ?? 0;
65498
65484
  return aIndex - bIndex;
65499
65485
  });
65500
65486
 
65501
65487
  // Elements without tabindex (preserving their original order)
65502
65488
  const elementsWithoutTabindex = uniqueElements.filter((el) => {
65503
- const tabindex = getNumericTabIndex$1(el);
65489
+ const tabindex = getNumericTabIndex$2(el);
65504
65490
 
65505
65491
  // Elements without tabindex or with tabindex of 0 stay in DOM order
65506
65492
  return tabindex === null || tabindex === 0;
@@ -65515,199 +65501,6 @@ function getFocusableElements$1(container) {
65515
65501
  return tabIndexedUniqueElements;
65516
65502
  }
65517
65503
 
65518
- /**
65519
- * FocusTrap manages keyboard focus within a specified container element, ensuring that focus does not leave the container when tabbing.
65520
- * It is commonly used for modal dialogs or overlays to improve accessibility by trapping focus within interactive UI components.
65521
- */
65522
- let FocusTrap$1 = class FocusTrap {
65523
- /**
65524
- * Creates a new FocusTrap instance for the given container element.
65525
- * Initializes event listeners and prepares the container for focus management.
65526
- *
65527
- * @param {HTMLElement} container The DOM element to trap focus within.
65528
- * @param {boolean} [controlTabOrder=false] If true enables manual control of the tab order by the FocusTrap.
65529
- * @throws {Error} If the provided container is not a valid HTMLElement.
65530
- */
65531
- constructor(container, controlTabOrder = false) {
65532
- if (!container || !(container instanceof HTMLElement)) {
65533
- throw new Error("FocusTrap requires a valid HTMLElement.");
65534
- }
65535
-
65536
- this.container = container;
65537
- this.tabDirection = "forward"; // or 'backward';
65538
- this.controlTabOrder = controlTabOrder;
65539
-
65540
- this._init();
65541
- }
65542
-
65543
- /**
65544
- * Initializes the focus trap by setting up event listeners and attributes on the container.
65545
- * Prepares the container for focus management, including support for shadow DOM and inert attributes.
65546
- *
65547
- * @private
65548
- */
65549
- _init() {
65550
- // Add inert attribute to prevent focusing programmatically as well (if supported)
65551
- if ("inert" in HTMLElement.prototype) {
65552
- this.container.inert = false; // Ensure the container isn't inert
65553
- this.container.setAttribute("data-focus-trap-container", true); // Mark for identification
65554
- }
65555
-
65556
- // Track tab direction
65557
- this.container.addEventListener("keydown", this._onKeydown);
65558
- }
65559
-
65560
- /**
65561
- * Gets an array of currently active (focused) elements in the document and shadow DOM.
65562
- * @returns {Array<HTMLElement>} An array of focusable elements within the container.
65563
- * @private
65564
- */
65565
- _getActiveElements() {
65566
- // Get the active element(s) in the document and shadow root
65567
- // This will include the active element in the shadow DOM if it exists
65568
- // Active element may be inside the shadow DOM depending on delegatesFocus, so we need to check both
65569
- let { activeElement } = document;
65570
- const actives = [activeElement];
65571
- while (activeElement?.shadowRoot?.activeElement) {
65572
- actives.push(activeElement.shadowRoot.activeElement);
65573
- activeElement = activeElement.shadowRoot.activeElement;
65574
- }
65575
- return actives;
65576
- }
65577
-
65578
- /**
65579
- * Gets the next focus index based on the current index and focusable elements.
65580
- * @param {number} currentIndex The current index of the focused element.
65581
- * @param {Array<HTMLElement>} focusables The array of focusable elements.
65582
- * @returns {number|null} The next focus index or null if not determined.
65583
- */
65584
- _getNextFocusIndex(currentIndex, focusables, actives) {
65585
- if (this.controlTabOrder) {
65586
- // Calculate the new index based on the current index and tab direction
65587
- let newFocusIndex =
65588
- currentIndex + (this.tabDirection === "forward" ? 1 : -1);
65589
-
65590
- // Wrap-around logic
65591
- if (newFocusIndex < 0) newFocusIndex = focusables.length - 1;
65592
- if (newFocusIndex >= focusables.length) newFocusIndex = 0;
65593
-
65594
- // Early return with the new index
65595
- return newFocusIndex;
65596
- }
65597
-
65598
- // Determine if we need to wrap
65599
- const atFirst =
65600
- actives.includes(focusables[0]) || actives.includes(this.container);
65601
- const atLast = actives.includes(focusables[focusables.length - 1]);
65602
-
65603
- // Only wrap if at the ends
65604
- if (this.tabDirection === "backward" && atFirst) {
65605
- return focusables.length - 1;
65606
- }
65607
-
65608
- if (this.tabDirection === "forward" && atLast) {
65609
- return 0;
65610
- }
65611
-
65612
- // No wrap, so don't change focus, return early
65613
- return null;
65614
- }
65615
-
65616
- /**
65617
- * Handles the Tab key press event to manage focus within the container.
65618
- * @param {KeyboardEvent} e The keyboard event triggered by the user.
65619
- * @returns {void}
65620
- */
65621
- _handleTabKey(e) {
65622
- // Update the focusable elements
65623
- const focusables = this._getFocusableElements();
65624
-
65625
- // If there are no focusable elements, exit
65626
- if (!focusables.length) return;
65627
-
65628
- // Set the tab direction based on the key pressed
65629
- this.tabDirection = e.shiftKey ? "backward" : "forward";
65630
-
65631
- // Get the active elements that are currently focused
65632
- const actives = this._getActiveElements();
65633
-
65634
- // If we're at either end of the focusable elements, wrap around to the other end
65635
- let focusIndex = focusables.findIndex((el) => actives.includes(el));
65636
-
65637
- // Fallback if we have no focused element
65638
- if (focusIndex === -1) focusIndex = 0;
65639
-
65640
- // Get the next focus index based on the current focus index, tab direction, and controlTabOrder setting
65641
- // Is null if no new focus index is determined
65642
- const newFocusIndex = this._getNextFocusIndex(
65643
- focusIndex,
65644
- focusables,
65645
- actives,
65646
- );
65647
-
65648
- // If we have a new focus index, set focus to that element
65649
- if (newFocusIndex !== null) {
65650
- e.preventDefault();
65651
- focusables[newFocusIndex].focus();
65652
- }
65653
- }
65654
-
65655
- /**
65656
- * Catches the keydown event
65657
- * @param {KeyboardEvent} e The keyboard event triggered by user interaction.
65658
- * @private
65659
- */
65660
- _onKeydown = (e) => {
65661
- // Handle tab
65662
- if (e.key === "Tab") this._handleTabKey(e);
65663
- };
65664
-
65665
- /**
65666
- * Retrieves all focusable elements within the container in DOM order, including those in shadow DOM and slots.
65667
- * Returns a unique, ordered array of elements that can receive focus.
65668
- *
65669
- * @returns {Array<HTMLElement>} An array of focusable elements within the container.
65670
- * @private
65671
- */
65672
- _getFocusableElements() {
65673
- // Use the imported utility function to get focusable elements
65674
- const elements = getFocusableElements$1(this.container);
65675
-
65676
- // Return the elements found
65677
- return elements;
65678
- }
65679
-
65680
- /**
65681
- * Moves focus to the first focusable element within the container.
65682
- * Useful for setting initial focus when activating the focus trap.
65683
- */
65684
- focusFirstElement() {
65685
- const focusables = this._getFocusableElements();
65686
- if (focusables.length) focusables[0].focus();
65687
- }
65688
-
65689
- /**
65690
- * Moves focus to the last focusable element within the container.
65691
- * Useful for setting focus when deactivating or cycling focus in reverse.
65692
- */
65693
- focusLastElement() {
65694
- const focusables = this._getFocusableElements();
65695
- if (focusables.length) focusables[focusables.length - 1].focus();
65696
- }
65697
-
65698
- /**
65699
- * Removes event listeners and attributes added by the focus trap.
65700
- * Call this method to clean up when the focus trap is no longer needed.
65701
- */
65702
- disconnect() {
65703
- if (this.container.hasAttribute("data-focus-trap-container")) {
65704
- this.container.removeAttribute("data-focus-trap-container");
65705
- }
65706
-
65707
- this.container.removeEventListener("keydown", this._onKeydown);
65708
- }
65709
- };
65710
-
65711
65504
  // Copyright (c) Alaska Air. All right reserved. Licensed under the Apache-2.0 license
65712
65505
  // See LICENSE in the project root for license information.
65713
65506
 
@@ -66205,7 +65998,7 @@ let AuroDropdownBib$1 = class AuroDropdownBib extends i$2 {
66205
65998
  classes[`shape-${this.shape}`] = true;
66206
65999
 
66207
66000
  return u$d`
66208
- <dialog class="${e$2(classes)}" part="bibContainer" role="${o$4(this.dialogRole)}" aria-labelledby="${o$4(this.dialogLabel ? 'dialogLabel' : undefined)}">
66001
+ <dialog tabindex="-1" class="${e$2(classes)}" part="bibContainer" role="${o$4(this.dialogRole)}" aria-labelledby="${o$4(this.dialogLabel ? 'dialogLabel' : undefined)}">
66209
66002
  ${this.dialogLabel ? u$d`<span id="dialogLabel" class="util_displayHiddenVisually">${this.dialogLabel}</span>` : ''}
66210
66003
  <slot></slot>
66211
66004
  <span id="srAnnouncement" class="util_displayHiddenVisually" aria-live="polite" role="status"></span>
@@ -66456,7 +66249,7 @@ let AuroHelpText$2 = class AuroHelpText extends i$2 {
66456
66249
  }
66457
66250
  };
66458
66251
 
66459
- var formkitVersion$2 = '202607072023';
66252
+ var formkitVersion$2 = '202607102214';
66460
66253
 
66461
66254
  let AuroElement$2$1 = class AuroElement extends i$2 {
66462
66255
  static get properties() {
@@ -66747,7 +66540,7 @@ let AuroDropdown$1 = class AuroDropdown extends AuroElement$2$1 {
66747
66540
  */
66748
66541
  focus() {
66749
66542
  if (this.isPopoverVisible && this.bibContent) {
66750
- const focusables = getFocusableElements$1(this.bibContent);
66543
+ const focusables = getFocusableElements$2(this.bibContent);
66751
66544
  if (focusables.length > 0) {
66752
66545
  focusables[0].focus();
66753
66546
  }
@@ -67210,7 +67003,10 @@ let AuroDropdown$1 = class AuroDropdown extends AuroElement$2$1 {
67210
67003
  }
67211
67004
 
67212
67005
 
67213
- if (!this.isPopoverVisible) {
67006
+ // On Tab-driven close (eventType "focusloss"), let focus advance naturally
67007
+ // — restoring to the trigger would trap the user on this dropdown, forcing
67008
+ // an extra Tab to move on. Escape and outside-click still restore.
67009
+ if (!this.isPopoverVisible && eventType !== "focusloss") {
67214
67010
  // wait til the bib gets fully closed and rendered
67215
67011
  setTimeout(() => {
67216
67012
  // Skip if the bib re-opened, or if focus moved intentionally outside the dropdown (not to body).
@@ -67365,7 +67161,7 @@ let AuroDropdown$1 = class AuroDropdown extends AuroElement$2$1 {
67365
67161
  }
67366
67162
 
67367
67163
  // Collect focusable elements from the bib content.
67368
- const focusables = getFocusableElements$1(this.bibContent);
67164
+ const focusables = getFocusableElements$2(this.bibContent);
67369
67165
 
67370
67166
  // Fallback: try from slotted content directly
67371
67167
  if (!focusables.length) {
@@ -67374,7 +67170,7 @@ let AuroDropdown$1 = class AuroDropdown extends AuroElement$2$1 {
67374
67170
 
67375
67171
  for (const node of assignedNodes) {
67376
67172
  if (node.nodeType === Node.ELEMENT_NODE) {
67377
- focusables.push(...getFocusableElements$1(node));
67173
+ focusables.push(...getFocusableElements$2(node));
67378
67174
  }
67379
67175
  }
67380
67176
  }
@@ -67434,21 +67230,22 @@ let AuroDropdown$1 = class AuroDropdown extends AuroElement$2$1 {
67434
67230
 
67435
67231
  // Move initial focus into the bib content, matching FocusTrap behavior
67436
67232
  requestAnimationFrame(() => {
67437
- const focusables = getFocusableElements$1(this.bibContent);
67233
+ const focusables = getFocusableElements$2(this.bibContent);
67438
67234
  if (focusables.length) {
67439
67235
  focusables[0].focus();
67440
67236
  }
67441
67237
  });
67442
67238
  } else {
67443
- // Normal desktop: use FocusTrap on the bib element.
67444
- // Defer focusFirstElement to the next frame because the popover
67445
- // is positioned asynchronously by Floating UI — calling focus()
67446
- // synchronously here would target elements with zero dimensions
67447
- // and the focus call would be silently ignored.
67448
- this.focusTrap = new FocusTrap$1(this.bibContent);
67239
+ // Normal desktop (non-modal): move initial focus into the bib but
67240
+ // don't trap Tab. Tab should exit the bib and let the floater's
67241
+ // handleFocusLoss close it, matching native <select>/<details>
67242
+ // behavior. Deferred one frame because Floating UI positions the
67243
+ // popover asynchronously a synchronous focus() would target
67244
+ // zero-dimension elements and be silently ignored.
67449
67245
  requestAnimationFrame(() => {
67450
- if (this.focusTrap) {
67451
- this.focusTrap.focusFirstElement();
67246
+ const focusables = getFocusableElements$2(this.bibContent);
67247
+ if (focusables.length) {
67248
+ focusables[0].focus();
67452
67249
  }
67453
67250
  });
67454
67251
  }
@@ -67664,7 +67461,7 @@ let AuroDropdown$1 = class AuroDropdown extends AuroElement$2$1 {
67664
67461
  if (triggerContentNodes) {
67665
67462
 
67666
67463
  // See if any of them are focusable elements
67667
- this.triggerContentFocusable = triggerContentNodes.some((node) => getFocusableElements$1(node).length > 0);
67464
+ this.triggerContentFocusable = triggerContentNodes.some((node) => getFocusableElements$2(node).length > 0);
67668
67465
 
67669
67466
  // If any of them are focusable elements
67670
67467
  if (this.triggerContentFocusable) {
@@ -80074,7 +79871,7 @@ let AuroHelpText$1$1 = class AuroHelpText extends i$2 {
80074
79871
  }
80075
79872
  };
80076
79873
 
80077
- var formkitVersion$1$1 = '202607072023';
79874
+ var formkitVersion$1$1 = '202607102214';
80078
79875
 
80079
79876
  // Copyright (c) 2025 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
80080
79877
  // See LICENSE in the project root for license information.
@@ -81195,7 +80992,7 @@ let AuroBibtemplate$1 = class AuroBibtemplate extends i$2 {
81195
80992
  }
81196
80993
  };
81197
80994
 
81198
- var formkitVersion$3 = '202607072023';
80995
+ var formkitVersion$3 = '202607102214';
81199
80996
 
81200
80997
  var styleCss$1$3 = i$4`.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}`;
81201
80998
 
@@ -81978,6 +81775,8 @@ class AuroCombobox extends AuroElement$3 {
81978
81775
 
81979
81776
  /**
81980
81777
  * If set, the `icon` attribute will be applied to the trigger `auro-input` element.
81778
+ * Icon rendering is currently limited to `type="credit-card"`. Setting `triggerIcon`
81779
+ * without a supported `type` propagates the attribute but does not render a visible icon.
81981
81780
  */
81982
81781
  triggerIcon: {
81983
81782
  type: Boolean,
@@ -82009,7 +81808,7 @@ class AuroCombobox extends AuroElement$3 {
82009
81808
  },
82010
81809
 
82011
81810
  /**
82012
- * Value selected for the dropdown menu.
81811
+ * Value selected for the dropdown menu. When set programmatically or as a preset attribute, the value must match a selectable option. If it matches an option marked `disabled` or `static`, the selection is rejected: `value` and `optionSelected` are cleared to `undefined`. `hidden` options (including those filtered out by type-ahead) remain selectable by value.
82013
81812
  */
82014
81813
  value: {
82015
81814
  type: String
@@ -82505,7 +82304,12 @@ class AuroCombobox extends AuroElement$3 {
82505
82304
  this.dropdown.bibDialogLabel = labelElement.textContent.trim() || undefined;
82506
82305
  }
82507
82306
 
82508
- // Exposes the CSS parts from the bibtemplate for styling
82307
+ if (this.customBibWidth) {
82308
+ this.dropdown.dropdownWidth = this.customBibWidth;
82309
+ }
82310
+
82311
+ // Exposes the CSS parts from the dropdown and bibtemplate for styling
82312
+ this.dropdown.exposeCssParts();
82509
82313
  this.bibtemplate.exposeCssParts();
82510
82314
 
82511
82315
  this.hideBib = this.hideBib.bind(this);
@@ -82725,8 +82529,11 @@ class AuroCombobox extends AuroElement$3 {
82725
82529
  // do not close while typing in suggestion mode with no value selected, to allow freeform input
82726
82530
  this.hideBib();
82727
82531
 
82728
- // Move focus to the clear button when the user makes a selection.
82729
- if (!isEcho && this.menu.value !== undefined) {
82532
+ // Move focus to the clear button when the user makes a selection,
82533
+ // unless the Shift+Tab handler opted this selection out.
82534
+ if (this._suppressClearBtnFocusOnSelection) {
82535
+ this._suppressClearBtnFocusOnSelection = false;
82536
+ } else if (!isEcho && this.menu.value !== undefined) {
82730
82537
  this.setClearBtnFocus();
82731
82538
  }
82732
82539
 
@@ -83132,6 +82939,12 @@ class AuroCombobox extends AuroElement$3 {
83132
82939
  this.value = undefined;
83133
82940
  this.typedValue = undefined;
83134
82941
  this.input.value = undefined;
82942
+ // Fullscreen bib mounts a second auro-input that holds the user-facing
82943
+ // native <input> on mobile; clearing only the trigger leaves stale text
82944
+ // there when the bib is reopened after reset.
82945
+ if (this.inputInBib) {
82946
+ this.inputInBib.value = undefined;
82947
+ }
83135
82948
  this.menu.value = undefined;
83136
82949
  this.validation.reset(this);
83137
82950
  this.touched = false;
@@ -83710,6 +83523,18 @@ let AuroLibraryRuntimeUtils$4 = class AuroLibraryRuntimeUtils {
83710
83523
  }
83711
83524
  };
83712
83525
 
83526
+ /**
83527
+ * Serializes a multi-select value array back into the String `value` property.
83528
+ * An empty (or missing) array collapses to `undefined` so an emptied selection
83529
+ * clears `value` rather than reflecting a `"[]"` attribute.
83530
+ * @private
83531
+ * @param {Array<string>|undefined} values - The selected values.
83532
+ * @returns {string|undefined} JSON string of the values, or undefined when empty.
83533
+ */
83534
+ function serializeMultiSelectValue(values) {
83535
+ return values && values.length > 0 ? JSON.stringify(values) : undefined;
83536
+ }
83537
+
83713
83538
  /**
83714
83539
  * Validates if an option can be interacted with.
83715
83540
  * @private
@@ -83722,6 +83547,20 @@ function isOptionInteractive(option) {
83722
83547
  !option.hasAttribute('static');
83723
83548
  }
83724
83549
 
83550
+ /**
83551
+ * Validates if an option may be selected by matching a programmatic value.
83552
+ * Unlike `isOptionInteractive`, `hidden` is allowed: the combobox toggles
83553
+ * `hidden` as its type-ahead filter, so a filtered-out option is still a
83554
+ * valid programmatic selection. Only disabled and static options — which are
83555
+ * never selectable — are rejected.
83556
+ * @param {HTMLElement} option - The option to check.
83557
+ * @returns {boolean} True if option can be selected by value.
83558
+ */
83559
+ function isSelectableByValue(option) {
83560
+ return !option.hasAttribute('disabled') &&
83561
+ !option.hasAttribute('static');
83562
+ }
83563
+
83725
83564
  /**
83726
83565
  * Helper method to dispatch custom events.
83727
83566
  * @param {HTMLElement} element - Element to dispatch event from.
@@ -83891,22 +83730,26 @@ class AuroMenu extends AuroElement$2 {
83891
83730
 
83892
83731
  /**
83893
83732
  * Specifies the current active menuOption.
83733
+ * @readonly
83894
83734
  */
83895
83735
  optionActive: {
83896
83736
  type: Object,
83897
- attribute: 'optionactive'
83737
+ attribute: false
83898
83738
  },
83899
83739
 
83900
83740
  /**
83901
- * An array of currently selected menu options, type `HTMLElement` by default. In multi-select mode, `optionSelected` is an array of HTML elements.
83741
+ * The currently selected menu option(s). In single-select mode this is a single `HTMLElement` (or `undefined` when nothing is selected). In multi-select mode this is an array of `HTMLElement`s.
83742
+ * @readonly
83902
83743
  */
83903
83744
  optionSelected: {
83904
83745
  // Allow HTMLElement, HTMLElement[] arrays and undefined
83905
- type: Object
83746
+ type: Object,
83747
+ attribute: false
83906
83748
  },
83907
83749
 
83908
83750
  /**
83909
83751
  * The value of the selected option. In multi-select mode, this is a JSON stringified array of selected option values.
83752
+ * Options marked `disabled` or `static` are not selectable by value; `hidden` options remain selectable. In single-select mode, if the value matches a non-selectable option the selection is cleared (`optionSelected` becomes `undefined`) and `auroMenu-selectValueFailure` is dispatched. In multi-select mode, non-selectable entries are dropped from the value and the remaining selectable entries are selected; `auroMenu-selectValueFailure` is dispatched only when none of the entries match a selectable option.
83910
83753
  */
83911
83754
  value: {
83912
83755
  type: String,
@@ -84030,7 +83873,7 @@ class AuroMenu extends AuroElement$2 {
84030
83873
  }
84031
83874
 
84032
83875
  /**
84033
- * Selects options by value.
83876
+ * Selects options by value. Options marked `disabled` or `static` are not selectable; `hidden` options remain selectable. In single-select mode, if the value matches a non-selectable option the selection is cleared and `auroMenu-selectValueFailure` is dispatched. In multi-select mode, non-selectable entries are dropped and the remaining selectable entries are selected; `auroMenu-selectValueFailure` is dispatched only when none of the entries match a selectable option. Passing `undefined`, `null`, an empty string, or an empty array clears the selection without dispatching a failure.
84034
83877
  * @param {string|string[]|undefined|null} value - The value(s) to select.
84035
83878
  * @public
84036
83879
  */
@@ -84115,6 +83958,11 @@ class AuroMenu extends AuroElement$2 {
84115
83958
  this.initItems();
84116
83959
  }
84117
83960
 
83961
+ // Set when reconciliation reassigns `value` below. That reassignment schedules a
83962
+ // second updated() cycle, so the `event`-attribute dispatch is deferred to that
83963
+ // cycle to avoid firing option custom events twice on the same selection.
83964
+ let valueReconciled = false;
83965
+
84118
83966
  // Handle null/undefined/empty case — empty/whitespace strings clear selection
84119
83967
  // consistently with selectByValue(''), and avoid downstream `.includes('')` matches.
84120
83968
  if (this.value === undefined || this.value === null || (typeof this.value === 'string' && this.value.trim() === '')) {
@@ -84127,11 +83975,31 @@ class AuroMenu extends AuroElement$2 {
84127
83975
  // Defensive default: `formattedValue` can be undefined for unexpected value types,
84128
83976
  // and calling `.includes` on undefined would throw during reconciliation.
84129
83977
  const valueArray = this.formattedValue || [];
84130
- const matchingOptions = this.items ? this.items.filter((item) => valueArray.includes(item.value)) : [];
83978
+ const matchingOptions = this.items ? this.items.filter((item) => isSelectableByValue(item) && valueArray.includes(item.value)) : [];
84131
83979
  newSelected = matchingOptions.length > 0 ? matchingOptions : undefined;
83980
+
83981
+ // Reconcile `value` with the selectable set. Drop only entries whose option is
83982
+ // loaded but non-selectable (disabled/static) — leaving them would desync `value`
83983
+ // from `optionSelected`, and the toggle handlers rebuild `value` from `formattedValue`,
83984
+ // so the rejected entry would resurface on the next select/deselect. Entries with no
83985
+ // matching item yet are preserved so async preselection still works once options render.
83986
+ const rejectedValues = this.items
83987
+ ? this.items.filter((item) => !isSelectableByValue(item) && valueArray.includes(item.value)).map((item) => item.value)
83988
+ : [];
83989
+ if (rejectedValues.length > 0) {
83990
+ const reconciled = valueArray.filter((val) => !rejectedValues.includes(val));
83991
+ this.value = serializeMultiSelectValue(reconciled);
83992
+ valueReconciled = true;
83993
+ }
84132
83994
  } else {
84133
- // In single-select mode, this.value should be a string
84134
- const matchingOption = this.items ? this.items.find((item) => item.value === this.value) : undefined;
83995
+ // In single-select mode, this.value should be a string. Reject
83996
+ // disabled/static options so a programmatic value pointing at a
83997
+ // non-selectable option falls through to the no-match path below
83998
+ // (dispatching auroMenu-selectValueFailure) instead of pinning it.
83999
+ // `hidden` is intentionally NOT excluded: the combobox toggles
84000
+ // `hidden` as its type-ahead filter, so a filtered-out option is
84001
+ // still a valid programmatic selection.
84002
+ const matchingOption = this.items ? this.items.find((item) => isSelectableByValue(item) && item.value === this.value) : undefined;
84135
84003
 
84136
84004
  if (matchingOption) {
84137
84005
  newSelected = matchingOption;
@@ -84173,8 +84041,9 @@ class AuroMenu extends AuroElement$2 {
84173
84041
  ]
84174
84042
  ]));
84175
84043
 
84176
- // Notify of changes
84177
- if (this.optionSelected !== undefined) {
84044
+ // Notify of changes. Skip when reconciliation just reassigned `value`: the
84045
+ // follow-on update cycle re-runs this branch and fires the events exactly once.
84046
+ if (this.optionSelected !== undefined && !valueReconciled) {
84178
84047
  const selected = Array.isArray(this.optionSelected) ? this.optionSelected : [this.optionSelected];
84179
84048
  selected.forEach((opt) => {
84180
84049
  if (opt.hasAttribute('event')) {
@@ -84387,7 +84256,7 @@ class AuroMenu extends AuroElement$2 {
84387
84256
  const currentSelected = this.optionSelected || [];
84388
84257
 
84389
84258
  if (!currentValue.includes(option.value)) {
84390
- this.value = JSON.stringify([
84259
+ this.value = serializeMultiSelectValue([
84391
84260
  ...currentValue,
84392
84261
  option.value
84393
84262
  ]);
@@ -84413,15 +84282,9 @@ class AuroMenu extends AuroElement$2 {
84413
84282
  */
84414
84283
  handleDeselectState(option) {
84415
84284
  if (this.multiSelect) {
84416
- // Remove this option from array
84285
+ // Remove this option from array; an empty result collapses `value` to undefined.
84417
84286
  const newFormattedValue = (this.formattedValue || []).filter((val) => val !== option.value);
84418
-
84419
- // If array is empty after removal, set back to undefined
84420
- if (newFormattedValue && newFormattedValue.length === 0) {
84421
- this.value = undefined;
84422
- } else {
84423
- this.value = JSON.stringify(newFormattedValue);
84424
- }
84287
+ this.value = serializeMultiSelectValue(newFormattedValue);
84425
84288
 
84426
84289
  this.optionSelected = this.optionSelected.filter((val) => val !== option);
84427
84290
  if (this.optionSelected.length === 0) {
@@ -84468,6 +84331,11 @@ class AuroMenu extends AuroElement$2 {
84468
84331
  this.optionSelected = undefined;
84469
84332
  this._index = -1;
84470
84333
 
84334
+ // Clear active option state so a follow-up open/navigation starts fresh
84335
+ // rather than reusing a stale reference from before the reset.
84336
+ this.items?.forEach((item) => item.classList.remove('active'));
84337
+ this.optionActive = undefined;
84338
+
84471
84339
  // Reset UI state
84472
84340
  this.updateItemsState(new Map([
84473
84341
  [
@@ -84917,6 +84785,7 @@ let menuOptionIdCounter = 0;
84917
84785
  * The `auro-menuoption` element provides users a way to define a menu option.
84918
84786
  * @customElement auro-menuoption
84919
84787
  *
84788
+ * @attr {Boolean} static - When present, marks the option as non-interactive — it renders but is skipped during keyboard navigation and cannot be selected. Useful for section headers, informational rows inside a menu, or attaching event listeners.
84920
84789
  * @slot default - The default slot for the menu option text.
84921
84790
  *
84922
84791
  * @event auroMenuOption-mouseover - Notifies that this option has been hovered over.
@@ -84946,6 +84815,7 @@ class AuroMenuOption extends AuroElement$2 {
84946
84815
  this.noCheckmark = false;
84947
84816
  this.disabled = false;
84948
84817
  this.noMatch = false;
84818
+ this.persistent = false;
84949
84819
 
84950
84820
  /**
84951
84821
  * @private
@@ -84967,6 +84837,12 @@ class AuroMenuOption extends AuroElement$2 {
84967
84837
  type: Boolean,
84968
84838
  reflect: true
84969
84839
  },
84840
+
84841
+ /**
84842
+ * **Deprecated.** Use the `value` attribute on `auro-menu` to set the selected option when the menu renders (or call `menu.selectByValue(value)` programmatically). Support for the child-level `selected` attribute will be removed in a future major release.
84843
+ *
84844
+ * @deprecated Use the `value` attribute on `auro-menu` instead.
84845
+ */
84970
84846
  selected: {
84971
84847
  type: Boolean,
84972
84848
  reflect: true
@@ -85001,6 +84877,12 @@ class AuroMenuOption extends AuroElement$2 {
85001
84877
  reflect: true,
85002
84878
  attribute: 'nomatch'
85003
84879
  },
84880
+
84881
+ /** When true, this option is excluded from `matchWord` DOM rewriting — useful for utility rows (e.g., "Add new…") that must render identically regardless of the current filter. */
84882
+ persistent: {
84883
+ type: Boolean,
84884
+ reflect: true
84885
+ },
85004
84886
  };
85005
84887
  }
85006
84888
 
@@ -86051,7 +85933,7 @@ const selectKeyboardStrategy = {
86051
85933
  ArrowDown(component, evt, ctx) {
86052
85934
  evt.preventDefault();
86053
85935
  if (ctx.isExpanded) {
86054
- if (evt.altKey || evt.ctrlKey || evt.metaKey) {
85936
+ if (evt.altKey || evt.ctrlKey) {
86055
85937
  // navigate to last enabled option
86056
85938
  selectKeyboardStrategy.End(component, evt, ctx);
86057
85939
  } else {
@@ -86065,7 +85947,7 @@ const selectKeyboardStrategy = {
86065
85947
  ArrowUp(component, evt, ctx) {
86066
85948
  evt.preventDefault();
86067
85949
  if (ctx.isExpanded) {
86068
- if (evt.altKey || evt.ctrlKey || evt.metaKey) {
85950
+ if (evt.altKey || evt.ctrlKey) {
86069
85951
  // navigate to first enabled option
86070
85952
  selectKeyboardStrategy.Home(component, evt, ctx);
86071
85953
  } else {
@@ -88480,12 +88362,40 @@ class AuroFloatingUI {
88480
88362
  return;
88481
88363
  }
88482
88364
 
88365
+ // Chrome-specific: during popover top-layer promotion after a click on a
88366
+ // slotted focusable, :focus-within can briefly evaluate false while the
88367
+ // active element is still structurally inside the trigger/bib. Fall back
88368
+ // to a shadow-piercing ancestry walk from the deep active element before
88369
+ // treating this as a real focus loss.
88370
+ try {
88371
+ let active = document.activeElement;
88372
+ while (active && active.shadowRoot && active.shadowRoot.activeElement) {
88373
+ active = active.shadowRoot.activeElement;
88374
+ }
88375
+ const targets = [element, element.trigger, element.bib].filter(Boolean);
88376
+ let node = active;
88377
+ while (node) {
88378
+ if (targets.includes(node)) {
88379
+ return;
88380
+ }
88381
+ node =
88382
+ node.parentElement ||
88383
+ (node.getRootNode && node.getRootNode().host) ||
88384
+ null;
88385
+ }
88386
+ } catch (e) {
88387
+ // Defensive: fall through to the existing close path if traversal fails.
88388
+ }
88389
+
88483
88390
  // if fullscreen bib is in fullscreen mode, do not close
88484
88391
  if (element.bib.hasAttribute("isfullscreen")) {
88485
88392
  return;
88486
88393
  }
88487
88394
 
88488
- this.hideBib("keydown");
88395
+ // eventType "focusloss" distinguishes a Tab/click-driven close from an
88396
+ // Escape keydown close. Consumers use this to decide whether to restore
88397
+ // focus to the trigger (Escape) or let it advance naturally (Tab).
88398
+ this.hideBib("focusloss");
88489
88399
  }
88490
88400
 
88491
88401
  setupHideHandlers() {
@@ -89155,199 +89065,6 @@ function getFocusableElements(container) {
89155
89065
  return tabIndexedUniqueElements;
89156
89066
  }
89157
89067
 
89158
- /**
89159
- * FocusTrap manages keyboard focus within a specified container element, ensuring that focus does not leave the container when tabbing.
89160
- * It is commonly used for modal dialogs or overlays to improve accessibility by trapping focus within interactive UI components.
89161
- */
89162
- class FocusTrap {
89163
- /**
89164
- * Creates a new FocusTrap instance for the given container element.
89165
- * Initializes event listeners and prepares the container for focus management.
89166
- *
89167
- * @param {HTMLElement} container The DOM element to trap focus within.
89168
- * @param {boolean} [controlTabOrder=false] If true enables manual control of the tab order by the FocusTrap.
89169
- * @throws {Error} If the provided container is not a valid HTMLElement.
89170
- */
89171
- constructor(container, controlTabOrder = false) {
89172
- if (!container || !(container instanceof HTMLElement)) {
89173
- throw new Error("FocusTrap requires a valid HTMLElement.");
89174
- }
89175
-
89176
- this.container = container;
89177
- this.tabDirection = "forward"; // or 'backward';
89178
- this.controlTabOrder = controlTabOrder;
89179
-
89180
- this._init();
89181
- }
89182
-
89183
- /**
89184
- * Initializes the focus trap by setting up event listeners and attributes on the container.
89185
- * Prepares the container for focus management, including support for shadow DOM and inert attributes.
89186
- *
89187
- * @private
89188
- */
89189
- _init() {
89190
- // Add inert attribute to prevent focusing programmatically as well (if supported)
89191
- if ("inert" in HTMLElement.prototype) {
89192
- this.container.inert = false; // Ensure the container isn't inert
89193
- this.container.setAttribute("data-focus-trap-container", true); // Mark for identification
89194
- }
89195
-
89196
- // Track tab direction
89197
- this.container.addEventListener("keydown", this._onKeydown);
89198
- }
89199
-
89200
- /**
89201
- * Gets an array of currently active (focused) elements in the document and shadow DOM.
89202
- * @returns {Array<HTMLElement>} An array of focusable elements within the container.
89203
- * @private
89204
- */
89205
- _getActiveElements() {
89206
- // Get the active element(s) in the document and shadow root
89207
- // This will include the active element in the shadow DOM if it exists
89208
- // Active element may be inside the shadow DOM depending on delegatesFocus, so we need to check both
89209
- let { activeElement } = document;
89210
- const actives = [activeElement];
89211
- while (activeElement?.shadowRoot?.activeElement) {
89212
- actives.push(activeElement.shadowRoot.activeElement);
89213
- activeElement = activeElement.shadowRoot.activeElement;
89214
- }
89215
- return actives;
89216
- }
89217
-
89218
- /**
89219
- * Gets the next focus index based on the current index and focusable elements.
89220
- * @param {number} currentIndex The current index of the focused element.
89221
- * @param {Array<HTMLElement>} focusables The array of focusable elements.
89222
- * @returns {number|null} The next focus index or null if not determined.
89223
- */
89224
- _getNextFocusIndex(currentIndex, focusables, actives) {
89225
- if (this.controlTabOrder) {
89226
- // Calculate the new index based on the current index and tab direction
89227
- let newFocusIndex =
89228
- currentIndex + (this.tabDirection === "forward" ? 1 : -1);
89229
-
89230
- // Wrap-around logic
89231
- if (newFocusIndex < 0) newFocusIndex = focusables.length - 1;
89232
- if (newFocusIndex >= focusables.length) newFocusIndex = 0;
89233
-
89234
- // Early return with the new index
89235
- return newFocusIndex;
89236
- }
89237
-
89238
- // Determine if we need to wrap
89239
- const atFirst =
89240
- actives.includes(focusables[0]) || actives.includes(this.container);
89241
- const atLast = actives.includes(focusables[focusables.length - 1]);
89242
-
89243
- // Only wrap if at the ends
89244
- if (this.tabDirection === "backward" && atFirst) {
89245
- return focusables.length - 1;
89246
- }
89247
-
89248
- if (this.tabDirection === "forward" && atLast) {
89249
- return 0;
89250
- }
89251
-
89252
- // No wrap, so don't change focus, return early
89253
- return null;
89254
- }
89255
-
89256
- /**
89257
- * Handles the Tab key press event to manage focus within the container.
89258
- * @param {KeyboardEvent} e The keyboard event triggered by the user.
89259
- * @returns {void}
89260
- */
89261
- _handleTabKey(e) {
89262
- // Update the focusable elements
89263
- const focusables = this._getFocusableElements();
89264
-
89265
- // If there are no focusable elements, exit
89266
- if (!focusables.length) return;
89267
-
89268
- // Set the tab direction based on the key pressed
89269
- this.tabDirection = e.shiftKey ? "backward" : "forward";
89270
-
89271
- // Get the active elements that are currently focused
89272
- const actives = this._getActiveElements();
89273
-
89274
- // If we're at either end of the focusable elements, wrap around to the other end
89275
- let focusIndex = focusables.findIndex((el) => actives.includes(el));
89276
-
89277
- // Fallback if we have no focused element
89278
- if (focusIndex === -1) focusIndex = 0;
89279
-
89280
- // Get the next focus index based on the current focus index, tab direction, and controlTabOrder setting
89281
- // Is null if no new focus index is determined
89282
- const newFocusIndex = this._getNextFocusIndex(
89283
- focusIndex,
89284
- focusables,
89285
- actives,
89286
- );
89287
-
89288
- // If we have a new focus index, set focus to that element
89289
- if (newFocusIndex !== null) {
89290
- e.preventDefault();
89291
- focusables[newFocusIndex].focus();
89292
- }
89293
- }
89294
-
89295
- /**
89296
- * Catches the keydown event
89297
- * @param {KeyboardEvent} e The keyboard event triggered by user interaction.
89298
- * @private
89299
- */
89300
- _onKeydown = (e) => {
89301
- // Handle tab
89302
- if (e.key === "Tab") this._handleTabKey(e);
89303
- };
89304
-
89305
- /**
89306
- * Retrieves all focusable elements within the container in DOM order, including those in shadow DOM and slots.
89307
- * Returns a unique, ordered array of elements that can receive focus.
89308
- *
89309
- * @returns {Array<HTMLElement>} An array of focusable elements within the container.
89310
- * @private
89311
- */
89312
- _getFocusableElements() {
89313
- // Use the imported utility function to get focusable elements
89314
- const elements = getFocusableElements(this.container);
89315
-
89316
- // Return the elements found
89317
- return elements;
89318
- }
89319
-
89320
- /**
89321
- * Moves focus to the first focusable element within the container.
89322
- * Useful for setting initial focus when activating the focus trap.
89323
- */
89324
- focusFirstElement() {
89325
- const focusables = this._getFocusableElements();
89326
- if (focusables.length) focusables[0].focus();
89327
- }
89328
-
89329
- /**
89330
- * Moves focus to the last focusable element within the container.
89331
- * Useful for setting focus when deactivating or cycling focus in reverse.
89332
- */
89333
- focusLastElement() {
89334
- const focusables = this._getFocusableElements();
89335
- if (focusables.length) focusables[focusables.length - 1].focus();
89336
- }
89337
-
89338
- /**
89339
- * Removes event listeners and attributes added by the focus trap.
89340
- * Call this method to clean up when the focus trap is no longer needed.
89341
- */
89342
- disconnect() {
89343
- if (this.container.hasAttribute("data-focus-trap-container")) {
89344
- this.container.removeAttribute("data-focus-trap-container");
89345
- }
89346
-
89347
- this.container.removeEventListener("keydown", this._onKeydown);
89348
- }
89349
- }
89350
-
89351
89068
  // Copyright (c) Alaska Air. All right reserved. Licensed under the Apache-2.0 license
89352
89069
  // See LICENSE in the project root for license information.
89353
89070
 
@@ -89845,7 +89562,7 @@ class AuroDropdownBib extends i$2 {
89845
89562
  classes[`shape-${this.shape}`] = true;
89846
89563
 
89847
89564
  return u$d`
89848
- <dialog class="${e$2(classes)}" part="bibContainer" role="${o$4(this.dialogRole)}" aria-labelledby="${o$4(this.dialogLabel ? 'dialogLabel' : undefined)}">
89565
+ <dialog tabindex="-1" class="${e$2(classes)}" part="bibContainer" role="${o$4(this.dialogRole)}" aria-labelledby="${o$4(this.dialogLabel ? 'dialogLabel' : undefined)}">
89849
89566
  ${this.dialogLabel ? u$d`<span id="dialogLabel" class="util_displayHiddenVisually">${this.dialogLabel}</span>` : ''}
89850
89567
  <slot></slot>
89851
89568
  <span id="srAnnouncement" class="util_displayHiddenVisually" aria-live="polite" role="status"></span>
@@ -90096,7 +89813,7 @@ let AuroHelpText$1 = class AuroHelpText extends i$2 {
90096
89813
  }
90097
89814
  };
90098
89815
 
90099
- var formkitVersion$1 = '202607072023';
89816
+ var formkitVersion$1 = '202607102214';
90100
89817
 
90101
89818
  class AuroElement extends i$2 {
90102
89819
  static get properties() {
@@ -90850,7 +90567,10 @@ class AuroDropdown extends AuroElement {
90850
90567
  }
90851
90568
 
90852
90569
 
90853
- if (!this.isPopoverVisible) {
90570
+ // On Tab-driven close (eventType "focusloss"), let focus advance naturally
90571
+ // — restoring to the trigger would trap the user on this dropdown, forcing
90572
+ // an extra Tab to move on. Escape and outside-click still restore.
90573
+ if (!this.isPopoverVisible && eventType !== "focusloss") {
90854
90574
  // wait til the bib gets fully closed and rendered
90855
90575
  setTimeout(() => {
90856
90576
  // Skip if the bib re-opened, or if focus moved intentionally outside the dropdown (not to body).
@@ -91080,15 +90800,16 @@ class AuroDropdown extends AuroElement {
91080
90800
  }
91081
90801
  });
91082
90802
  } else {
91083
- // Normal desktop: use FocusTrap on the bib element.
91084
- // Defer focusFirstElement to the next frame because the popover
91085
- // is positioned asynchronously by Floating UI — calling focus()
91086
- // synchronously here would target elements with zero dimensions
91087
- // and the focus call would be silently ignored.
91088
- this.focusTrap = new FocusTrap(this.bibContent);
90803
+ // Normal desktop (non-modal): move initial focus into the bib but
90804
+ // don't trap Tab. Tab should exit the bib and let the floater's
90805
+ // handleFocusLoss close it, matching native <select>/<details>
90806
+ // behavior. Deferred one frame because Floating UI positions the
90807
+ // popover asynchronously a synchronous focus() would target
90808
+ // zero-dimension elements and be silently ignored.
91089
90809
  requestAnimationFrame(() => {
91090
- if (this.focusTrap) {
91091
- this.focusTrap.focusFirstElement();
90810
+ const focusables = getFocusableElements(this.bibContent);
90811
+ if (focusables.length) {
90812
+ focusables[0].focus();
91092
90813
  }
91093
90814
  });
91094
90815
  }
@@ -92135,7 +91856,7 @@ class AuroHelpText extends i$2 {
92135
91856
  }
92136
91857
  }
92137
91858
 
92138
- var formkitVersion = '202607072023';
91859
+ var formkitVersion = '202607102214';
92139
91860
 
92140
91861
  var styleCss = i$4`.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}.body-default{font-size:var(--wcss-body-default-font-size, 1rem);font-weight:var(--wcss-body-default-weight, );line-height:var(--wcss-body-default-line-height, 1.5rem)}.body-default,.body-default-emphasized{font-family:var(--wcss-body-family, "AS Circular"),system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;letter-spacing:var(--wcss-body-letter-spacing, 0)}.body-default-emphasized{font-size:var(--wcss-body-default-emphasized-font-size, 1rem);font-weight:var(--wcss-body-default-emphasized-weight, );line-height:var(--wcss-body-default-emphasized-line-height, 1.5rem)}.body-lg{font-size:var(--wcss-body-lg-font-size, 1.125rem);font-weight:var(--wcss-body-lg-weight, );line-height:var(--wcss-body-lg-line-height, 1.625rem)}.body-lg,.body-lg-emphasized{font-family:var(--wcss-body-family, "AS Circular"),system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;letter-spacing:var(--wcss-body-letter-spacing, 0)}.body-lg-emphasized{font-size:var(--wcss-body-lg-emphasized-font-size, 1.125rem);font-weight:var(--wcss-body-lg-emphasized-weight, );line-height:var(--wcss-body-lg-emphasized-line-height, 1.625rem)}.body-sm{font-size:var(--wcss-body-sm-font-size, 0.875rem);font-weight:var(--wcss-body-sm-weight, );line-height:var(--wcss-body-sm-line-height, 1.25rem)}.body-sm,.body-sm-emphasized{font-family:var(--wcss-body-family, "AS Circular"),system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;letter-spacing:var(--wcss-body-letter-spacing, 0)}.body-sm-emphasized{font-size:var(--wcss-body-sm-emphasized-font-size, 0.875rem);font-weight:var(--wcss-body-sm-emphasized-weight, );line-height:var(--wcss-body-sm-emphasized-line-height, 1.25rem)}.body-xs{font-size:var(--wcss-body-xs-font-size, 0.75rem);font-weight:var(--wcss-body-xs-weight, );line-height:var(--wcss-body-xs-line-height, 1rem)}.body-xs,.body-xs-emphasized{font-family:var(--wcss-body-family, "AS Circular"),system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;letter-spacing:var(--wcss-body-letter-spacing, 0)}.body-xs-emphasized{font-size:var(--wcss-body-xs-emphasized-font-size, 0.75rem);font-weight:var(--wcss-body-xs-emphasized-weight, );line-height:var(--wcss-body-xs-emphasized-line-height, 1rem)}.body-2xs{font-size:var(--wcss-body-2xs-font-size, 0.625rem);font-weight:var(--wcss-body-2xs-weight, );line-height:var(--wcss-body-2xs-line-height, 0.875rem)}.body-2xs,.body-2xs-emphasized{font-family:var(--wcss-body-family, "AS Circular"),system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;letter-spacing:var(--wcss-body-letter-spacing, 0)}.body-2xs-emphasized{font-size:var(--wcss-body-2xs-emphasized-font-size, 0.625rem);font-weight:var(--wcss-body-2xs-emphasized-weight, );line-height:var(--wcss-body-2xs-emphasized-line-height, 0.875rem)}.display-2xl{font-family:var(--wcss-display-2xl-family, "AS Circular"),var(--wcss-display-2xl-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-display-2xl-font-size, clamp(3.5rem, 6vw, 5.375rem));font-weight:var(--wcss-display-2xl-weight, 300);letter-spacing:var(--wcss-display-2xl-letter-spacing, 0);line-height:var(--wcss-display-2xl-line-height, 1.3)}.display-xl{font-family:var(--wcss-display-xl-family, "AS Circular"),var(--wcss-display-xl-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-display-xl-font-size, clamp(3rem, 5.3333333333vw, 4.5rem));font-weight:var(--wcss-display-xl-weight, 300);letter-spacing:var(--wcss-display-xl-letter-spacing, 0);line-height:var(--wcss-display-xl-line-height, 1.3)}.display-lg{font-family:var(--wcss-display-lg-family, "AS Circular"),var(--wcss-display-lg-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-display-lg-font-size, clamp(2.75rem, 4.6666666667vw, 4rem));font-weight:var(--wcss-display-lg-weight, 300);letter-spacing:var(--wcss-display-lg-letter-spacing, 0);line-height:var(--wcss-display-lg-line-height, 1.3)}.display-md{font-family:var(--wcss-display-md-family, "AS Circular"),var(--wcss-display-md-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-display-md-font-size, clamp(2.5rem, 4vw, 3.5rem));font-weight:var(--wcss-display-md-weight, 300);letter-spacing:var(--wcss-display-md-letter-spacing, 0);line-height:var(--wcss-display-md-line-height, 1.3)}.display-sm{font-family:var(--wcss-display-sm-family, "AS Circular"),var(--wcss-display-sm-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-display-sm-font-size, clamp(2rem, 3.6666666667vw, 3rem));font-weight:var(--wcss-display-sm-weight, 300);letter-spacing:var(--wcss-display-sm-letter-spacing, 0);line-height:var(--wcss-display-sm-line-height, 1.3)}.display-xs{font-family:var(--wcss-display-xs-family, "AS Circular"),var(--wcss-display-xs-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-display-xs-font-size, clamp(1.75rem, 3vw, 2.375rem));font-weight:var(--wcss-display-xs-weight, 300);letter-spacing:var(--wcss-display-xs-letter-spacing, 0);line-height:var(--wcss-display-xs-line-height, 1.3)}.heading-xl{font-family:var(--wcss-heading-xl-family, "AS Circular"),var(--wcss-heading-xl-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-heading-xl-font-size, clamp(2rem, 3vw, 2.5rem));font-weight:var(--wcss-heading-xl-weight, 300);letter-spacing:var(--wcss-heading-xl-letter-spacing, 0);line-height:var(--wcss-heading-xl-line-height, 1.3)}.heading-lg{font-family:var(--wcss-heading-lg-family, "AS Circular"),var(--wcss-heading-lg-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-heading-lg-font-size, clamp(1.75rem, 2.6666666667vw, 2.25rem));font-weight:var(--wcss-heading-lg-weight, 300);letter-spacing:var(--wcss-heading-lg-letter-spacing, 0);line-height:var(--wcss-heading-lg-line-height, 1.3)}.heading-md{font-family:var(--wcss-heading-md-family, "AS Circular"),var(--wcss-heading-md-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-heading-md-font-size, clamp(1.625rem, 2.3333333333vw, 1.75rem));font-weight:var(--wcss-heading-md-weight, 300);letter-spacing:var(--wcss-heading-md-letter-spacing, 0);line-height:var(--wcss-heading-md-line-height, 1.3)}.heading-sm{font-family:var(--wcss-heading-sm-family, "AS Circular"),var(--wcss-heading-sm-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-heading-sm-font-size, clamp(1.375rem, 2vw, 1.5rem));font-weight:var(--wcss-heading-sm-weight, 300);letter-spacing:var(--wcss-heading-sm-letter-spacing, 0);line-height:var(--wcss-heading-sm-line-height, 1.3)}.heading-xs{font-family:var(--wcss-heading-xs-family, "AS Circular"),var(--wcss-heading-xs-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-heading-xs-font-size, clamp(1.25rem, 1.6666666667vw, 1.25rem));font-weight:var(--wcss-heading-xs-weight, 300);letter-spacing:var(--wcss-heading-xs-letter-spacing, 0);line-height:var(--wcss-heading-xs-line-height, 1.3)}.heading-2xs{font-family:var(--wcss-heading-2xs-family, "AS Circular"),var(--wcss-heading-2xs-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-heading-2xs-font-size, clamp(1.125rem, 1.5vw, 1.125rem));font-weight:var(--wcss-heading-2xs-weight, 300);letter-spacing:var(--wcss-heading-2xs-letter-spacing, 0);line-height:var(--wcss-heading-2xs-line-height, 1.3)}.accent-2xl{font-family:var(--wcss-accent-2xl-family, "Good OT"),var(--wcss-accent-2xl-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-accent-2xl-font-size, clamp(2rem, 3.1666666667vw, 2.375rem));font-weight:var(--wcss-accent-2xl-weight, 450);letter-spacing:var(--wcss-accent-2xl-letter-spacing, 0.05em);line-height:var(--wcss-accent-2xl-line-height, 1)}.accent-2xl,.accent-xl{text-transform:uppercase}.accent-xl{font-family:var(--wcss-accent-xl-family, "Good OT"),var(--wcss-accent-xl-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-accent-xl-font-size, clamp(1.625rem, 2.3333333333vw, 2rem));font-weight:var(--wcss-accent-xl-weight, 450);letter-spacing:var(--wcss-accent-xl-letter-spacing, 0.05em);line-height:var(--wcss-accent-xl-line-height, 1.3)}.accent-lg{font-family:var(--wcss-accent-lg-family, "Good OT"),var(--wcss-accent-lg-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-accent-lg-font-size, clamp(1.5rem, 2.1666666667vw, 1.75rem));font-weight:var(--wcss-accent-lg-weight, 450);letter-spacing:var(--wcss-accent-lg-letter-spacing, 0.05em);line-height:var(--wcss-accent-lg-line-height, 1.3)}.accent-lg,.accent-md{text-transform:uppercase}.accent-md{font-family:var(--wcss-accent-md-family, "Good OT"),var(--wcss-accent-md-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-accent-md-font-size, clamp(1.375rem, 1.8333333333vw, 1.5rem));font-weight:var(--wcss-accent-md-weight, 500);letter-spacing:var(--wcss-accent-md-letter-spacing, 0.05em);line-height:var(--wcss-accent-md-line-height, 1.3)}.accent-sm{font-family:var(--wcss-accent-sm-family, "Good OT"),var(--wcss-accent-sm-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-accent-sm-font-size, clamp(1.125rem, 1.5vw, 1.25rem));font-weight:var(--wcss-accent-sm-weight, 500);letter-spacing:var(--wcss-accent-sm-letter-spacing, 0.05em);line-height:var(--wcss-accent-sm-line-height, 1.3)}.accent-sm,.accent-xs{text-transform:uppercase}.accent-xs{font-family:var(--wcss-accent-xs-family, "Good OT"),var(--wcss-accent-xs-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-accent-xs-font-size, clamp(1rem, 1.3333333333vw, 1rem));font-weight:var(--wcss-accent-xs-weight, 500);letter-spacing:var(--wcss-accent-xs-letter-spacing, 0.1em);line-height:var(--wcss-accent-xs-line-height, 1.3)}.accent-2xs{font-family:var(--wcss-accent-2xs-family, "Good OT"),var(--wcss-accent-2xs-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-accent-2xs-font-size, clamp(0.875rem, 1.1666666667vw, 0.875rem));font-weight:var(--wcss-accent-2xs-weight, 450);letter-spacing:var(--wcss-accent-2xs-letter-spacing, 0.1em);line-height:var(--wcss-accent-2xs-line-height, 1.3);text-transform:uppercase}[auro-dropdown]{--ds-auro-dropdown-trigger-border-color: var(--ds-auro-select-border-color);--ds-auro-dropdown-trigger-background-color: var(--ds-auro-select-background-color);--ds-auro-dropdown-trigger-container-color: var(--ds-auro-select-background-color);--ds-auro-dropdown-trigger-outline-color: var(--ds-auro-select-outline-color)}:host{display:inline-block;text-align:left;vertical-align:top}:host([layout*=emphasized]) [auro-dropdown],:host([layout*=snowflake]) [auro-dropdown]{--ds-auro-select-border-color: transparent}:host([layout*=emphasized]) .mainContent,:host([layout*=snowflake]) .mainContent{text-align:center}.mainContent{position:relative;display:flex;overflow:hidden;flex:1;flex-direction:column;align-items:center;justify-content:center}.valueContainer [slot=displayValue]{display:none}.accents{display:flex;flex-direction:row;align-items:center;justify-content:center}::slotted([slot=typeIcon]){margin-right:var(--ds-size-100, 0.5rem)}.displayValue{display:block}.displayValue:not(.force){display:none}.displayValue:not(.force).hasContent:is(.withValue):not(.hasFocus){display:block}.triggerContent{display:flex;width:100%;align-items:center;justify-content:center}:host([layout*=emphasized]) .triggerContent{padding:0 var(--ds-size-100, 0.5rem) 0 var(--ds-size-300, 1.5rem)}:host([layout*=snowflake]) .triggerContent{padding:0 var(--ds-size-100, 0.5rem) 0 var(--ds-size-200, 1rem)}:host([layout*=snowflake]) label{padding-block:var(--ds-size-25, 0.125rem)}:host([layout*=classic]) .triggerContent{padding:0 var(--ds-size-100, 0.5rem)}:host([layout*=classic]) .mainContent{align-items:start}:host([layout*=classic]) label{overflow:hidden;cursor:text;text-overflow:ellipsis;white-space:nowrap}:host([layout*=classic]) .value{height:auto}label{color:var(--ds-auro-select-label-text-color)}:host(:is([validity]:not([validity=valid]))) [auro-dropdown]{--ds-auro-select-border-color: var(--ds-basic-color-status-error, #e31f26);--ds-auro-select-outline-color: var(--ds-basic-color-status-error, #e31f26);--ds-auro-dropdown-helptext-text-color: var(--ds-basic-color-texticon-default, #2a2a2a)}:host([ondark]:is([validity]:not([validity=valid]))) [auro-dropdown],:host([appearance=inverse]:is([validity]:not([validity=valid]))) [auro-dropdown]{--ds-auro-select-border-color: var(--ds-advanced-color-state-error-inverse, #f9a4a8);--ds-auro-select-outline-color: var(--ds-advanced-color-state-error-inverse, #f9a4a8);--ds-auro-dropdown-helptext-text-color: var(--ds-basic-color-texticon-inverse, #ffffff)}#slotHolder{display:none}:host([fluid]){width:100%}:host([disabled]){pointer-events:none;user-select:none}:host([disabled]:not([ondark])) [auro-dropdown],:host([disabled]:not([appearance=inverse])) [auro-dropdown]{--ds-auro-select-border-color: var(--ds-basic-color-border-subtle, #dddddd)}:host(:not([layout*=classic])[disabled][ondark]) [auro-dropdown],:host(:not([layout*=classic])[disabled][appearance=inverse]) [auro-dropdown]{--ds-auro-select-border-color: transparent}`;
92141
91862
 
@@ -92577,7 +92298,7 @@ class AuroSelect extends AuroElement$1 {
92577
92298
  },
92578
92299
 
92579
92300
  /**
92580
- * Value selected for the component.
92301
+ * Value selected for the component. When set programmatically or as a preset attribute, the value must match a selectable option. If it matches an option marked `disabled` or `static`, the selection is rejected: `value` is cleared to `undefined` while `optionSelected` is cleared to `undefined` in single-select or `[]` in multiSelect. `hidden` options remain selectable by value.
92581
92302
  */
92582
92303
  value: {
92583
92304
  type: String,
@@ -93397,6 +93118,10 @@ class AuroSelect extends AuroElement$1 {
93397
93118
  this._observeLabelChanges();
93398
93119
  }
93399
93120
 
93121
+ /**
93122
+ * Sets the selected value by matching it against the menu options. Options marked `disabled` or `static` are not selectable: if the value matches one, the selection is rejected and `value` is cleared to `undefined` while `optionSelected` is cleared to `undefined` in single-select or `[]` in multiSelect. `hidden` options remain selectable.
93123
+ * @param {string} value - The value to match against the menu options.
93124
+ */
93400
93125
  setMenuValue(value) {
93401
93126
  if (!this.menu) return;
93402
93127
  this.menu.selectByValue(value);