@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
@@ -13379,7 +13379,7 @@ let AuroHelpText$8 = class AuroHelpText extends i$3 {
13379
13379
  }
13380
13380
  };
13381
13381
 
13382
- var formkitVersion$8 = '202607072023';
13382
+ var formkitVersion$8 = '202607102214';
13383
13383
 
13384
13384
  // Copyright (c) 2025 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
13385
13385
  // See LICENSE in the project root for license information.
@@ -27776,7 +27776,7 @@ let AuroBibtemplate$3 = class AuroBibtemplate extends i$3 {
27776
27776
  }
27777
27777
  };
27778
27778
 
27779
- var formkitVersion$2$1 = '202607072023';
27779
+ var formkitVersion$2$1 = '202607102214';
27780
27780
 
27781
27781
  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$2`${s$3(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$6`: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}
27782
27782
  `,u$4$2=i$6`.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}}
@@ -32053,12 +32053,40 @@ let AuroFloatingUI$3 = class AuroFloatingUI {
32053
32053
  return;
32054
32054
  }
32055
32055
 
32056
+ // Chrome-specific: during popover top-layer promotion after a click on a
32057
+ // slotted focusable, :focus-within can briefly evaluate false while the
32058
+ // active element is still structurally inside the trigger/bib. Fall back
32059
+ // to a shadow-piercing ancestry walk from the deep active element before
32060
+ // treating this as a real focus loss.
32061
+ try {
32062
+ let active = document.activeElement;
32063
+ while (active && active.shadowRoot && active.shadowRoot.activeElement) {
32064
+ active = active.shadowRoot.activeElement;
32065
+ }
32066
+ const targets = [element, element.trigger, element.bib].filter(Boolean);
32067
+ let node = active;
32068
+ while (node) {
32069
+ if (targets.includes(node)) {
32070
+ return;
32071
+ }
32072
+ node =
32073
+ node.parentElement ||
32074
+ (node.getRootNode && node.getRootNode().host) ||
32075
+ null;
32076
+ }
32077
+ } catch (e) {
32078
+ // Defensive: fall through to the existing close path if traversal fails.
32079
+ }
32080
+
32056
32081
  // if fullscreen bib is in fullscreen mode, do not close
32057
32082
  if (element.bib.hasAttribute("isfullscreen")) {
32058
32083
  return;
32059
32084
  }
32060
32085
 
32061
- this.hideBib("keydown");
32086
+ // eventType "focusloss" distinguishes a Tab/click-driven close from an
32087
+ // Escape keydown close. Consumers use this to decide whether to restore
32088
+ // focus to the trigger (Escape) or let it advance naturally (Tab).
32089
+ this.hideBib("focusloss");
32062
32090
  }
32063
32091
 
32064
32092
  setupHideHandlers() {
@@ -32547,7 +32575,7 @@ let AuroFloatingUI$3 = class AuroFloatingUI {
32547
32575
  };
32548
32576
 
32549
32577
  // Selectors for focusable elements
32550
- const FOCUSABLE_SELECTORS$3 = [
32578
+ const FOCUSABLE_SELECTORS$4 = [
32551
32579
  "a[href]",
32552
32580
  "button:not([disabled])",
32553
32581
  "textarea:not([disabled])",
@@ -32561,7 +32589,7 @@ const FOCUSABLE_SELECTORS$3 = [
32561
32589
  ];
32562
32590
 
32563
32591
  // List of custom components that are known to be focusable
32564
- const FOCUSABLE_COMPONENTS$3 = [
32592
+ const FOCUSABLE_COMPONENTS$4 = [
32565
32593
  "auro-checkbox",
32566
32594
  "auro-radio",
32567
32595
  "auro-dropdown",
@@ -32583,12 +32611,12 @@ const FOCUSABLE_COMPONENTS$3 = [
32583
32611
  * @param {HTMLElement} element The element to check for focusability.
32584
32612
  * @returns {boolean} True if the element is a focusable custom component, false otherwise.
32585
32613
  */
32586
- function isFocusableComponent$3(element) {
32614
+ function isFocusableComponent$4(element) {
32587
32615
  const componentName = element.tagName.toLowerCase();
32588
32616
 
32589
32617
  // Guard Clause: Element is a focusable component
32590
32618
  if (
32591
- !FOCUSABLE_COMPONENTS$3.some(
32619
+ !FOCUSABLE_COMPONENTS$4.some(
32592
32620
  (name) => element.hasAttribute(name) || componentName === name,
32593
32621
  )
32594
32622
  )
@@ -32612,7 +32640,7 @@ function isFocusableComponent$3(element) {
32612
32640
  * @param {HTMLElement} element The element whose tabindex to read.
32613
32641
  * @returns {?number} The numeric tabindex or null if missing/invalid.
32614
32642
  */
32615
- function getNumericTabIndex$3(element) {
32643
+ function getNumericTabIndex$4(element) {
32616
32644
  const raw = element.getAttribute("tabindex");
32617
32645
  if (raw == null) return null;
32618
32646
 
@@ -32628,7 +32656,7 @@ function getNumericTabIndex$3(element) {
32628
32656
  * @param {HTMLElement} container The container to search within
32629
32657
  * @returns {Array<HTMLElement>} An array of focusable elements within the container.
32630
32658
  */
32631
- function getFocusableElements$3(container) {
32659
+ function getFocusableElements$4(container) {
32632
32660
  // Get elements in DOM order by walking the tree
32633
32661
  const orderedFocusableElements = [];
32634
32662
 
@@ -32637,7 +32665,7 @@ function getFocusableElements$3(container) {
32637
32665
  // Check if current element is focusable
32638
32666
  if (root.nodeType === Node.ELEMENT_NODE) {
32639
32667
  // Check if this is a custom component that is focusable
32640
- const isComponentFocusable = isFocusableComponent$3(root);
32668
+ const isComponentFocusable = isFocusableComponent$4(root);
32641
32669
 
32642
32670
  if (isComponentFocusable) {
32643
32671
  // Add the component itself as a focusable element and don't traverse its shadow DOM
@@ -32646,7 +32674,7 @@ function getFocusableElements$3(container) {
32646
32674
  }
32647
32675
 
32648
32676
  // Check if the element itself matches any selector
32649
- for (const selector of FOCUSABLE_SELECTORS$3) {
32677
+ for (const selector of FOCUSABLE_SELECTORS$4) {
32650
32678
  if (root.matches?.(selector)) {
32651
32679
  orderedFocusableElements.push(root);
32652
32680
  break; // Once we know it's focusable, no need to check other selectors
@@ -32700,20 +32728,20 @@ function getFocusableElements$3(container) {
32700
32728
 
32701
32729
  // First extract elements with valid positive tabindex
32702
32730
  const elementsWithTabindex = uniqueElements.filter((el) => {
32703
- const tabindex = getNumericTabIndex$3(el);
32731
+ const tabindex = getNumericTabIndex$4(el);
32704
32732
  return tabindex !== null && tabindex > 0;
32705
32733
  });
32706
32734
 
32707
32735
  // Sort these elements by their tabindex value
32708
32736
  elementsWithTabindex.sort((a, b) => {
32709
- const aIndex = getNumericTabIndex$3(a) ?? 0;
32710
- const bIndex = getNumericTabIndex$3(b) ?? 0;
32737
+ const aIndex = getNumericTabIndex$4(a) ?? 0;
32738
+ const bIndex = getNumericTabIndex$4(b) ?? 0;
32711
32739
  return aIndex - bIndex;
32712
32740
  });
32713
32741
 
32714
32742
  // Elements without tabindex (preserving their original order)
32715
32743
  const elementsWithoutTabindex = uniqueElements.filter((el) => {
32716
- const tabindex = getNumericTabIndex$3(el);
32744
+ const tabindex = getNumericTabIndex$4(el);
32717
32745
 
32718
32746
  // Elements without tabindex or with tabindex of 0 stay in DOM order
32719
32747
  return tabindex === null || tabindex === 0;
@@ -32728,199 +32756,6 @@ function getFocusableElements$3(container) {
32728
32756
  return tabIndexedUniqueElements;
32729
32757
  }
32730
32758
 
32731
- /**
32732
- * FocusTrap manages keyboard focus within a specified container element, ensuring that focus does not leave the container when tabbing.
32733
- * It is commonly used for modal dialogs or overlays to improve accessibility by trapping focus within interactive UI components.
32734
- */
32735
- let FocusTrap$3 = class FocusTrap {
32736
- /**
32737
- * Creates a new FocusTrap instance for the given container element.
32738
- * Initializes event listeners and prepares the container for focus management.
32739
- *
32740
- * @param {HTMLElement} container The DOM element to trap focus within.
32741
- * @param {boolean} [controlTabOrder=false] If true enables manual control of the tab order by the FocusTrap.
32742
- * @throws {Error} If the provided container is not a valid HTMLElement.
32743
- */
32744
- constructor(container, controlTabOrder = false) {
32745
- if (!container || !(container instanceof HTMLElement)) {
32746
- throw new Error("FocusTrap requires a valid HTMLElement.");
32747
- }
32748
-
32749
- this.container = container;
32750
- this.tabDirection = "forward"; // or 'backward';
32751
- this.controlTabOrder = controlTabOrder;
32752
-
32753
- this._init();
32754
- }
32755
-
32756
- /**
32757
- * Initializes the focus trap by setting up event listeners and attributes on the container.
32758
- * Prepares the container for focus management, including support for shadow DOM and inert attributes.
32759
- *
32760
- * @private
32761
- */
32762
- _init() {
32763
- // Add inert attribute to prevent focusing programmatically as well (if supported)
32764
- if ("inert" in HTMLElement.prototype) {
32765
- this.container.inert = false; // Ensure the container isn't inert
32766
- this.container.setAttribute("data-focus-trap-container", true); // Mark for identification
32767
- }
32768
-
32769
- // Track tab direction
32770
- this.container.addEventListener("keydown", this._onKeydown);
32771
- }
32772
-
32773
- /**
32774
- * Gets an array of currently active (focused) elements in the document and shadow DOM.
32775
- * @returns {Array<HTMLElement>} An array of focusable elements within the container.
32776
- * @private
32777
- */
32778
- _getActiveElements() {
32779
- // Get the active element(s) in the document and shadow root
32780
- // This will include the active element in the shadow DOM if it exists
32781
- // Active element may be inside the shadow DOM depending on delegatesFocus, so we need to check both
32782
- let { activeElement } = document;
32783
- const actives = [activeElement];
32784
- while (activeElement?.shadowRoot?.activeElement) {
32785
- actives.push(activeElement.shadowRoot.activeElement);
32786
- activeElement = activeElement.shadowRoot.activeElement;
32787
- }
32788
- return actives;
32789
- }
32790
-
32791
- /**
32792
- * Gets the next focus index based on the current index and focusable elements.
32793
- * @param {number} currentIndex The current index of the focused element.
32794
- * @param {Array<HTMLElement>} focusables The array of focusable elements.
32795
- * @returns {number|null} The next focus index or null if not determined.
32796
- */
32797
- _getNextFocusIndex(currentIndex, focusables, actives) {
32798
- if (this.controlTabOrder) {
32799
- // Calculate the new index based on the current index and tab direction
32800
- let newFocusIndex =
32801
- currentIndex + (this.tabDirection === "forward" ? 1 : -1);
32802
-
32803
- // Wrap-around logic
32804
- if (newFocusIndex < 0) newFocusIndex = focusables.length - 1;
32805
- if (newFocusIndex >= focusables.length) newFocusIndex = 0;
32806
-
32807
- // Early return with the new index
32808
- return newFocusIndex;
32809
- }
32810
-
32811
- // Determine if we need to wrap
32812
- const atFirst =
32813
- actives.includes(focusables[0]) || actives.includes(this.container);
32814
- const atLast = actives.includes(focusables[focusables.length - 1]);
32815
-
32816
- // Only wrap if at the ends
32817
- if (this.tabDirection === "backward" && atFirst) {
32818
- return focusables.length - 1;
32819
- }
32820
-
32821
- if (this.tabDirection === "forward" && atLast) {
32822
- return 0;
32823
- }
32824
-
32825
- // No wrap, so don't change focus, return early
32826
- return null;
32827
- }
32828
-
32829
- /**
32830
- * Handles the Tab key press event to manage focus within the container.
32831
- * @param {KeyboardEvent} e The keyboard event triggered by the user.
32832
- * @returns {void}
32833
- */
32834
- _handleTabKey(e) {
32835
- // Update the focusable elements
32836
- const focusables = this._getFocusableElements();
32837
-
32838
- // If there are no focusable elements, exit
32839
- if (!focusables.length) return;
32840
-
32841
- // Set the tab direction based on the key pressed
32842
- this.tabDirection = e.shiftKey ? "backward" : "forward";
32843
-
32844
- // Get the active elements that are currently focused
32845
- const actives = this._getActiveElements();
32846
-
32847
- // If we're at either end of the focusable elements, wrap around to the other end
32848
- let focusIndex = focusables.findIndex((el) => actives.includes(el));
32849
-
32850
- // Fallback if we have no focused element
32851
- if (focusIndex === -1) focusIndex = 0;
32852
-
32853
- // Get the next focus index based on the current focus index, tab direction, and controlTabOrder setting
32854
- // Is null if no new focus index is determined
32855
- const newFocusIndex = this._getNextFocusIndex(
32856
- focusIndex,
32857
- focusables,
32858
- actives,
32859
- );
32860
-
32861
- // If we have a new focus index, set focus to that element
32862
- if (newFocusIndex !== null) {
32863
- e.preventDefault();
32864
- focusables[newFocusIndex].focus();
32865
- }
32866
- }
32867
-
32868
- /**
32869
- * Catches the keydown event
32870
- * @param {KeyboardEvent} e The keyboard event triggered by user interaction.
32871
- * @private
32872
- */
32873
- _onKeydown = (e) => {
32874
- // Handle tab
32875
- if (e.key === "Tab") this._handleTabKey(e);
32876
- };
32877
-
32878
- /**
32879
- * Retrieves all focusable elements within the container in DOM order, including those in shadow DOM and slots.
32880
- * Returns a unique, ordered array of elements that can receive focus.
32881
- *
32882
- * @returns {Array<HTMLElement>} An array of focusable elements within the container.
32883
- * @private
32884
- */
32885
- _getFocusableElements() {
32886
- // Use the imported utility function to get focusable elements
32887
- const elements = getFocusableElements$3(this.container);
32888
-
32889
- // Return the elements found
32890
- return elements;
32891
- }
32892
-
32893
- /**
32894
- * Moves focus to the first focusable element within the container.
32895
- * Useful for setting initial focus when activating the focus trap.
32896
- */
32897
- focusFirstElement() {
32898
- const focusables = this._getFocusableElements();
32899
- if (focusables.length) focusables[0].focus();
32900
- }
32901
-
32902
- /**
32903
- * Moves focus to the last focusable element within the container.
32904
- * Useful for setting focus when deactivating or cycling focus in reverse.
32905
- */
32906
- focusLastElement() {
32907
- const focusables = this._getFocusableElements();
32908
- if (focusables.length) focusables[focusables.length - 1].focus();
32909
- }
32910
-
32911
- /**
32912
- * Removes event listeners and attributes added by the focus trap.
32913
- * Call this method to clean up when the focus trap is no longer needed.
32914
- */
32915
- disconnect() {
32916
- if (this.container.hasAttribute("data-focus-trap-container")) {
32917
- this.container.removeAttribute("data-focus-trap-container");
32918
- }
32919
-
32920
- this.container.removeEventListener("keydown", this._onKeydown);
32921
- }
32922
- };
32923
-
32924
32759
  // Copyright (c) Alaska Air. All right reserved. Licensed under the Apache-2.0 license
32925
32760
  // See LICENSE in the project root for license information.
32926
32761
 
@@ -33418,7 +33253,7 @@ let AuroDropdownBib$3 = class AuroDropdownBib extends i$3 {
33418
33253
  classes[`shape-${this.shape}`] = true;
33419
33254
 
33420
33255
  return u$c`
33421
- <dialog class="${e$2(classes)}" part="bibContainer" role="${o$4(this.dialogRole)}" aria-labelledby="${o$4(this.dialogLabel ? 'dialogLabel' : undefined)}">
33256
+ <dialog tabindex="-1" class="${e$2(classes)}" part="bibContainer" role="${o$4(this.dialogRole)}" aria-labelledby="${o$4(this.dialogLabel ? 'dialogLabel' : undefined)}">
33422
33257
  ${this.dialogLabel ? u$c`<span id="dialogLabel" class="util_displayHiddenVisually">${this.dialogLabel}</span>` : ''}
33423
33258
  <slot></slot>
33424
33259
  <span id="srAnnouncement" class="util_displayHiddenVisually" aria-live="polite" role="status"></span>
@@ -33669,7 +33504,7 @@ let AuroHelpText$2$1 = class AuroHelpText extends i$3 {
33669
33504
  }
33670
33505
  };
33671
33506
 
33672
- var formkitVersion$1$3 = '202607072023';
33507
+ var formkitVersion$1$3 = '202607102214';
33673
33508
 
33674
33509
  let AuroElement$2$2 = class AuroElement extends i$3 {
33675
33510
  static get properties() {
@@ -33960,7 +33795,7 @@ let AuroDropdown$3 = class AuroDropdown extends AuroElement$2$2 {
33960
33795
  */
33961
33796
  focus() {
33962
33797
  if (this.isPopoverVisible && this.bibContent) {
33963
- const focusables = getFocusableElements$3(this.bibContent);
33798
+ const focusables = getFocusableElements$4(this.bibContent);
33964
33799
  if (focusables.length > 0) {
33965
33800
  focusables[0].focus();
33966
33801
  }
@@ -34423,7 +34258,10 @@ let AuroDropdown$3 = class AuroDropdown extends AuroElement$2$2 {
34423
34258
  }
34424
34259
 
34425
34260
 
34426
- if (!this.isPopoverVisible) {
34261
+ // On Tab-driven close (eventType "focusloss"), let focus advance naturally
34262
+ // — restoring to the trigger would trap the user on this dropdown, forcing
34263
+ // an extra Tab to move on. Escape and outside-click still restore.
34264
+ if (!this.isPopoverVisible && eventType !== "focusloss") {
34427
34265
  // wait til the bib gets fully closed and rendered
34428
34266
  setTimeout(() => {
34429
34267
  // Skip if the bib re-opened, or if focus moved intentionally outside the dropdown (not to body).
@@ -34578,7 +34416,7 @@ let AuroDropdown$3 = class AuroDropdown extends AuroElement$2$2 {
34578
34416
  }
34579
34417
 
34580
34418
  // Collect focusable elements from the bib content.
34581
- const focusables = getFocusableElements$3(this.bibContent);
34419
+ const focusables = getFocusableElements$4(this.bibContent);
34582
34420
 
34583
34421
  // Fallback: try from slotted content directly
34584
34422
  if (!focusables.length) {
@@ -34587,7 +34425,7 @@ let AuroDropdown$3 = class AuroDropdown extends AuroElement$2$2 {
34587
34425
 
34588
34426
  for (const node of assignedNodes) {
34589
34427
  if (node.nodeType === Node.ELEMENT_NODE) {
34590
- focusables.push(...getFocusableElements$3(node));
34428
+ focusables.push(...getFocusableElements$4(node));
34591
34429
  }
34592
34430
  }
34593
34431
  }
@@ -34647,21 +34485,22 @@ let AuroDropdown$3 = class AuroDropdown extends AuroElement$2$2 {
34647
34485
 
34648
34486
  // Move initial focus into the bib content, matching FocusTrap behavior
34649
34487
  requestAnimationFrame(() => {
34650
- const focusables = getFocusableElements$3(this.bibContent);
34488
+ const focusables = getFocusableElements$4(this.bibContent);
34651
34489
  if (focusables.length) {
34652
34490
  focusables[0].focus();
34653
34491
  }
34654
34492
  });
34655
34493
  } else {
34656
- // Normal desktop: use FocusTrap on the bib element.
34657
- // Defer focusFirstElement to the next frame because the popover
34658
- // is positioned asynchronously by Floating UI — calling focus()
34659
- // synchronously here would target elements with zero dimensions
34660
- // and the focus call would be silently ignored.
34661
- this.focusTrap = new FocusTrap$3(this.bibContent);
34494
+ // Normal desktop (non-modal): move initial focus into the bib but
34495
+ // don't trap Tab. Tab should exit the bib and let the floater's
34496
+ // handleFocusLoss close it, matching native <select>/<details>
34497
+ // behavior. Deferred one frame because Floating UI positions the
34498
+ // popover asynchronously a synchronous focus() would target
34499
+ // zero-dimension elements and be silently ignored.
34662
34500
  requestAnimationFrame(() => {
34663
- if (this.focusTrap) {
34664
- this.focusTrap.focusFirstElement();
34501
+ const focusables = getFocusableElements$4(this.bibContent);
34502
+ if (focusables.length) {
34503
+ focusables[0].focus();
34665
34504
  }
34666
34505
  });
34667
34506
  }
@@ -34877,7 +34716,7 @@ let AuroDropdown$3 = class AuroDropdown extends AuroElement$2$2 {
34877
34716
  if (triggerContentNodes) {
34878
34717
 
34879
34718
  // See if any of them are focusable elements
34880
- this.triggerContentFocusable = triggerContentNodes.some((node) => getFocusableElements$3(node).length > 0);
34719
+ this.triggerContentFocusable = triggerContentNodes.some((node) => getFocusableElements$4(node).length > 0);
34881
34720
 
34882
34721
  // If any of them are focusable elements
34883
34722
  if (this.triggerContentFocusable) {
@@ -47287,7 +47126,7 @@ let AuroHelpText$1$3 = class AuroHelpText extends i$3 {
47287
47126
  }
47288
47127
  };
47289
47128
 
47290
- var formkitVersion$7 = '202607072023';
47129
+ var formkitVersion$7 = '202607102214';
47291
47130
 
47292
47131
  // Copyright (c) 2025 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
47293
47132
  // See LICENSE in the project root for license information.
@@ -49833,11 +49672,14 @@ class AuroDatePicker extends AuroElement$5 {
49833
49672
  // what centralDate renders, causing all cells to have tabindex="-1".
49834
49673
  this.calendar.activeCellDate = null;
49835
49674
 
49836
- // Show the month containing the selected date (or today) instead of
49837
- // whichever month the user last navigated to. Route through
49838
- // updateCentralDate so centralDate stays first-of-month.
49839
- // Respect consumer-provided centralDate/calendarStartDate if no value is set.
49840
- if (this.valueObject) {
49675
+ // On open, reset the visible month to a predictable source rather than
49676
+ // whichever month the user last navigated to. Route through updateCentralDate
49677
+ // so centralDate stays first-of-month.
49678
+ // Priority: calendarFocusDate (when valid) -> value (when set) -> today (when neither is set).
49679
+ // Respect consumer-provided centralDate/calendarStartDate/minDate when neither calendarFocusDate nor value is set.
49680
+ if (this.calendarFocusDate && dateFormatter$1.isValidDate(this.calendarFocusDate)) {
49681
+ this.calendarRenderUtil.updateCentralDate(this, this.calendarFocusDateObject);
49682
+ } else if (this.valueObject) {
49841
49683
  this.calendarRenderUtil.updateCentralDate(this, this.value);
49842
49684
  } else if (!this.centralDate && !this.calendarStartDate && !this.minDate) {
49843
49685
  this.calendarRenderUtil.updateCentralDate(this, new Date());
@@ -50378,10 +50220,6 @@ class AuroDatePicker extends AuroElement$5 {
50378
50220
  }
50379
50221
  }
50380
50222
 
50381
- if (changedProperties.has('calendarFocusDate')) {
50382
- this.handleFocusDateChange();
50383
- }
50384
-
50385
50223
  if (changedProperties.has('calendarStartDate')) {
50386
50224
  this.calendar.setAttribute('calendarStartDate', this.calendarStartDate || '');
50387
50225
  }
@@ -50504,6 +50342,13 @@ class AuroDatePicker extends AuroElement$5 {
50504
50342
  this.setHasValue();
50505
50343
  }
50506
50344
 
50345
+ // Run focus-date handling AFTER value/valueEnd so that when a consumer sets
50346
+ // calendarFocusDate together with value, the focus date wins for the visible
50347
+ // month instead of being overwritten by the value branch's updateCentralDate.
50348
+ if (changedProperties.has('calendarFocusDate')) {
50349
+ this.handleFocusDateChange();
50350
+ }
50351
+
50507
50352
  if (changedProperties.has('error')) {
50508
50353
  // Error attribute is passed down to the last input in the list to control the error state
50509
50354
  // This is done to prevent error icon from displaying on both inputs in range support
@@ -50612,9 +50457,28 @@ class AuroDatePicker extends AuroElement$5 {
50612
50457
  * @returns {void}
50613
50458
  */
50614
50459
  handleClick(event) {
50615
-
50616
- // Get the initial target of the click event
50617
- const [initTarget] = event.composedPath();
50460
+ const path = event.composedPath();
50461
+ const [initTarget] = path;
50462
+ const pathIncludesBib = path.includes(this.dropdown?.bibContent);
50463
+ const triggerIsInert = this.dropdown?.trigger?.inert;
50464
+
50465
+ // When desktopModal is open, the datepicker marks the dropdown's #trigger
50466
+ // element inert to keep AT and Tab off the input. Inert also blocks pointer
50467
+ // events, so a click on the visible trigger area passes through to the
50468
+ // wrapper <div> that sits alongside #trigger in the dropdown's shadow root.
50469
+ // composedPath() then no longer contains #trigger, and the floater's
50470
+ // window-level click-outside handler treats the click as an outside click
50471
+ // and closes the bib. Suppress that misdetection here: if the click lands
50472
+ // inside the trigger's bounds and outside the bib, stop propagation before
50473
+ // it reaches the window listener.
50474
+ if (this.dropdown?.isPopoverVisible && triggerIsInert && !pathIncludesBib) {
50475
+ const triggerRect = this.dropdown.trigger?.getBoundingClientRect();
50476
+ if (triggerRect &&
50477
+ event.clientX >= triggerRect.left && event.clientX <= triggerRect.right &&
50478
+ event.clientY >= triggerRect.top && event.clientY <= triggerRect.bottom) {
50479
+ event.stopPropagation();
50480
+ }
50481
+ }
50618
50482
 
50619
50483
  // Determine if the current layout requires special handling
50620
50484
  const layoutRequiresHandling = ['snowflake'].includes(this.layout);
@@ -50623,7 +50487,7 @@ class AuroDatePicker extends AuroElement$5 {
50623
50487
  const targetIsInput = initTarget.tagName === 'INPUT';
50624
50488
  const isFocusAlreadyOnInput = this.inputList.includes(this.shadowRoot.activeElement);
50625
50489
 
50626
- if (layoutRequiresHandling && !targetIsInput && !isFocusAlreadyOnInput && !event.composedPath().includes(this.dropdown.bibContent)) {
50490
+ if (layoutRequiresHandling && !targetIsInput && !isFocusAlreadyOnInput && !pathIncludesBib) {
50627
50491
  // Focus the first input
50628
50492
  this.inputList[0].focus();
50629
50493
  }
@@ -52203,7 +52067,7 @@ let AuroHelpText$1$2 = class AuroHelpText extends i$3 {
52203
52067
  }
52204
52068
  };
52205
52069
 
52206
- var formkitVersion$1$2 = '202607072023';
52070
+ var formkitVersion$1$2 = '202607102214';
52207
52071
 
52208
52072
  // Copyright (c) 2026 Alaska Airlines. All rights reserved. Licensed under the Apache-2.0 license
52209
52073
  // See LICENSE in the project root for license information.
@@ -52544,21 +52408,6 @@ class AuroCounter extends i$3 {
52544
52408
  }
52545
52409
  }
52546
52410
 
52547
- /**
52548
- * Handles the slotchange event for the description slot.
52549
- * Updates ariaDescribedByElements on the spinbutton.
52550
- *
52551
- * @param {Event} event - The slotchange event.
52552
- * @private
52553
- */
52554
- onDescriptionSlotChange(event) {
52555
- const spinbutton = this.shadowRoot.querySelector('[role="spinbutton"]');
52556
- if (spinbutton) {
52557
- const assigned = event.target.assignedElements();
52558
- spinbutton.ariaDescribedByElements = assigned.length > 0 ? assigned : [];
52559
- }
52560
- }
52561
-
52562
52411
  updated(changedProperties) {
52563
52412
  if (changedProperties.has("value")) {
52564
52413
  this.validate();
@@ -52614,7 +52463,7 @@ class AuroCounter extends i$3 {
52614
52463
  <label class="label">
52615
52464
  <slot @slotchange="${this.onDefaultSlotChange}"></slot>
52616
52465
  </label>
52617
- <slot name="description" class="body-xs" @slotchange="${this.onDescriptionSlotChange}"></slot>
52466
+ <slot name="description" class="body-xs"></slot>
52618
52467
  </div>
52619
52468
  <div
52620
52469
  part="counterControl"
@@ -54915,12 +54764,40 @@ let AuroFloatingUI$2 = class AuroFloatingUI {
54915
54764
  return;
54916
54765
  }
54917
54766
 
54767
+ // Chrome-specific: during popover top-layer promotion after a click on a
54768
+ // slotted focusable, :focus-within can briefly evaluate false while the
54769
+ // active element is still structurally inside the trigger/bib. Fall back
54770
+ // to a shadow-piercing ancestry walk from the deep active element before
54771
+ // treating this as a real focus loss.
54772
+ try {
54773
+ let active = document.activeElement;
54774
+ while (active && active.shadowRoot && active.shadowRoot.activeElement) {
54775
+ active = active.shadowRoot.activeElement;
54776
+ }
54777
+ const targets = [element, element.trigger, element.bib].filter(Boolean);
54778
+ let node = active;
54779
+ while (node) {
54780
+ if (targets.includes(node)) {
54781
+ return;
54782
+ }
54783
+ node =
54784
+ node.parentElement ||
54785
+ (node.getRootNode && node.getRootNode().host) ||
54786
+ null;
54787
+ }
54788
+ } catch (e) {
54789
+ // Defensive: fall through to the existing close path if traversal fails.
54790
+ }
54791
+
54918
54792
  // if fullscreen bib is in fullscreen mode, do not close
54919
54793
  if (element.bib.hasAttribute("isfullscreen")) {
54920
54794
  return;
54921
54795
  }
54922
54796
 
54923
- this.hideBib("keydown");
54797
+ // eventType "focusloss" distinguishes a Tab/click-driven close from an
54798
+ // Escape keydown close. Consumers use this to decide whether to restore
54799
+ // focus to the trigger (Escape) or let it advance naturally (Tab).
54800
+ this.hideBib("focusloss");
54924
54801
  }
54925
54802
 
54926
54803
  setupHideHandlers() {
@@ -55409,7 +55286,7 @@ let AuroFloatingUI$2 = class AuroFloatingUI {
55409
55286
  };
55410
55287
 
55411
55288
  // Selectors for focusable elements
55412
- const FOCUSABLE_SELECTORS$2 = [
55289
+ const FOCUSABLE_SELECTORS$3 = [
55413
55290
  "a[href]",
55414
55291
  "button:not([disabled])",
55415
55292
  "textarea:not([disabled])",
@@ -55423,7 +55300,7 @@ const FOCUSABLE_SELECTORS$2 = [
55423
55300
  ];
55424
55301
 
55425
55302
  // List of custom components that are known to be focusable
55426
- const FOCUSABLE_COMPONENTS$2 = [
55303
+ const FOCUSABLE_COMPONENTS$3 = [
55427
55304
  "auro-checkbox",
55428
55305
  "auro-radio",
55429
55306
  "auro-dropdown",
@@ -55445,12 +55322,12 @@ const FOCUSABLE_COMPONENTS$2 = [
55445
55322
  * @param {HTMLElement} element The element to check for focusability.
55446
55323
  * @returns {boolean} True if the element is a focusable custom component, false otherwise.
55447
55324
  */
55448
- function isFocusableComponent$2(element) {
55325
+ function isFocusableComponent$3(element) {
55449
55326
  const componentName = element.tagName.toLowerCase();
55450
55327
 
55451
55328
  // Guard Clause: Element is a focusable component
55452
55329
  if (
55453
- !FOCUSABLE_COMPONENTS$2.some(
55330
+ !FOCUSABLE_COMPONENTS$3.some(
55454
55331
  (name) => element.hasAttribute(name) || componentName === name,
55455
55332
  )
55456
55333
  )
@@ -55474,7 +55351,7 @@ function isFocusableComponent$2(element) {
55474
55351
  * @param {HTMLElement} element The element whose tabindex to read.
55475
55352
  * @returns {?number} The numeric tabindex or null if missing/invalid.
55476
55353
  */
55477
- function getNumericTabIndex$2(element) {
55354
+ function getNumericTabIndex$3(element) {
55478
55355
  const raw = element.getAttribute("tabindex");
55479
55356
  if (raw == null) return null;
55480
55357
 
@@ -55490,7 +55367,7 @@ function getNumericTabIndex$2(element) {
55490
55367
  * @param {HTMLElement} container The container to search within
55491
55368
  * @returns {Array<HTMLElement>} An array of focusable elements within the container.
55492
55369
  */
55493
- function getFocusableElements$2(container) {
55370
+ function getFocusableElements$3(container) {
55494
55371
  // Get elements in DOM order by walking the tree
55495
55372
  const orderedFocusableElements = [];
55496
55373
 
@@ -55499,7 +55376,7 @@ function getFocusableElements$2(container) {
55499
55376
  // Check if current element is focusable
55500
55377
  if (root.nodeType === Node.ELEMENT_NODE) {
55501
55378
  // Check if this is a custom component that is focusable
55502
- const isComponentFocusable = isFocusableComponent$2(root);
55379
+ const isComponentFocusable = isFocusableComponent$3(root);
55503
55380
 
55504
55381
  if (isComponentFocusable) {
55505
55382
  // Add the component itself as a focusable element and don't traverse its shadow DOM
@@ -55508,7 +55385,7 @@ function getFocusableElements$2(container) {
55508
55385
  }
55509
55386
 
55510
55387
  // Check if the element itself matches any selector
55511
- for (const selector of FOCUSABLE_SELECTORS$2) {
55388
+ for (const selector of FOCUSABLE_SELECTORS$3) {
55512
55389
  if (root.matches?.(selector)) {
55513
55390
  orderedFocusableElements.push(root);
55514
55391
  break; // Once we know it's focusable, no need to check other selectors
@@ -55562,20 +55439,20 @@ function getFocusableElements$2(container) {
55562
55439
 
55563
55440
  // First extract elements with valid positive tabindex
55564
55441
  const elementsWithTabindex = uniqueElements.filter((el) => {
55565
- const tabindex = getNumericTabIndex$2(el);
55442
+ const tabindex = getNumericTabIndex$3(el);
55566
55443
  return tabindex !== null && tabindex > 0;
55567
55444
  });
55568
55445
 
55569
55446
  // Sort these elements by their tabindex value
55570
55447
  elementsWithTabindex.sort((a, b) => {
55571
- const aIndex = getNumericTabIndex$2(a) ?? 0;
55572
- const bIndex = getNumericTabIndex$2(b) ?? 0;
55448
+ const aIndex = getNumericTabIndex$3(a) ?? 0;
55449
+ const bIndex = getNumericTabIndex$3(b) ?? 0;
55573
55450
  return aIndex - bIndex;
55574
55451
  });
55575
55452
 
55576
55453
  // Elements without tabindex (preserving their original order)
55577
55454
  const elementsWithoutTabindex = uniqueElements.filter((el) => {
55578
- const tabindex = getNumericTabIndex$2(el);
55455
+ const tabindex = getNumericTabIndex$3(el);
55579
55456
 
55580
55457
  // Elements without tabindex or with tabindex of 0 stay in DOM order
55581
55458
  return tabindex === null || tabindex === 0;
@@ -55590,199 +55467,6 @@ function getFocusableElements$2(container) {
55590
55467
  return tabIndexedUniqueElements;
55591
55468
  }
55592
55469
 
55593
- /**
55594
- * FocusTrap manages keyboard focus within a specified container element, ensuring that focus does not leave the container when tabbing.
55595
- * It is commonly used for modal dialogs or overlays to improve accessibility by trapping focus within interactive UI components.
55596
- */
55597
- let FocusTrap$2 = class FocusTrap {
55598
- /**
55599
- * Creates a new FocusTrap instance for the given container element.
55600
- * Initializes event listeners and prepares the container for focus management.
55601
- *
55602
- * @param {HTMLElement} container The DOM element to trap focus within.
55603
- * @param {boolean} [controlTabOrder=false] If true enables manual control of the tab order by the FocusTrap.
55604
- * @throws {Error} If the provided container is not a valid HTMLElement.
55605
- */
55606
- constructor(container, controlTabOrder = false) {
55607
- if (!container || !(container instanceof HTMLElement)) {
55608
- throw new Error("FocusTrap requires a valid HTMLElement.");
55609
- }
55610
-
55611
- this.container = container;
55612
- this.tabDirection = "forward"; // or 'backward';
55613
- this.controlTabOrder = controlTabOrder;
55614
-
55615
- this._init();
55616
- }
55617
-
55618
- /**
55619
- * Initializes the focus trap by setting up event listeners and attributes on the container.
55620
- * Prepares the container for focus management, including support for shadow DOM and inert attributes.
55621
- *
55622
- * @private
55623
- */
55624
- _init() {
55625
- // Add inert attribute to prevent focusing programmatically as well (if supported)
55626
- if ("inert" in HTMLElement.prototype) {
55627
- this.container.inert = false; // Ensure the container isn't inert
55628
- this.container.setAttribute("data-focus-trap-container", true); // Mark for identification
55629
- }
55630
-
55631
- // Track tab direction
55632
- this.container.addEventListener("keydown", this._onKeydown);
55633
- }
55634
-
55635
- /**
55636
- * Gets an array of currently active (focused) elements in the document and shadow DOM.
55637
- * @returns {Array<HTMLElement>} An array of focusable elements within the container.
55638
- * @private
55639
- */
55640
- _getActiveElements() {
55641
- // Get the active element(s) in the document and shadow root
55642
- // This will include the active element in the shadow DOM if it exists
55643
- // Active element may be inside the shadow DOM depending on delegatesFocus, so we need to check both
55644
- let { activeElement } = document;
55645
- const actives = [activeElement];
55646
- while (activeElement?.shadowRoot?.activeElement) {
55647
- actives.push(activeElement.shadowRoot.activeElement);
55648
- activeElement = activeElement.shadowRoot.activeElement;
55649
- }
55650
- return actives;
55651
- }
55652
-
55653
- /**
55654
- * Gets the next focus index based on the current index and focusable elements.
55655
- * @param {number} currentIndex The current index of the focused element.
55656
- * @param {Array<HTMLElement>} focusables The array of focusable elements.
55657
- * @returns {number|null} The next focus index or null if not determined.
55658
- */
55659
- _getNextFocusIndex(currentIndex, focusables, actives) {
55660
- if (this.controlTabOrder) {
55661
- // Calculate the new index based on the current index and tab direction
55662
- let newFocusIndex =
55663
- currentIndex + (this.tabDirection === "forward" ? 1 : -1);
55664
-
55665
- // Wrap-around logic
55666
- if (newFocusIndex < 0) newFocusIndex = focusables.length - 1;
55667
- if (newFocusIndex >= focusables.length) newFocusIndex = 0;
55668
-
55669
- // Early return with the new index
55670
- return newFocusIndex;
55671
- }
55672
-
55673
- // Determine if we need to wrap
55674
- const atFirst =
55675
- actives.includes(focusables[0]) || actives.includes(this.container);
55676
- const atLast = actives.includes(focusables[focusables.length - 1]);
55677
-
55678
- // Only wrap if at the ends
55679
- if (this.tabDirection === "backward" && atFirst) {
55680
- return focusables.length - 1;
55681
- }
55682
-
55683
- if (this.tabDirection === "forward" && atLast) {
55684
- return 0;
55685
- }
55686
-
55687
- // No wrap, so don't change focus, return early
55688
- return null;
55689
- }
55690
-
55691
- /**
55692
- * Handles the Tab key press event to manage focus within the container.
55693
- * @param {KeyboardEvent} e The keyboard event triggered by the user.
55694
- * @returns {void}
55695
- */
55696
- _handleTabKey(e) {
55697
- // Update the focusable elements
55698
- const focusables = this._getFocusableElements();
55699
-
55700
- // If there are no focusable elements, exit
55701
- if (!focusables.length) return;
55702
-
55703
- // Set the tab direction based on the key pressed
55704
- this.tabDirection = e.shiftKey ? "backward" : "forward";
55705
-
55706
- // Get the active elements that are currently focused
55707
- const actives = this._getActiveElements();
55708
-
55709
- // If we're at either end of the focusable elements, wrap around to the other end
55710
- let focusIndex = focusables.findIndex((el) => actives.includes(el));
55711
-
55712
- // Fallback if we have no focused element
55713
- if (focusIndex === -1) focusIndex = 0;
55714
-
55715
- // Get the next focus index based on the current focus index, tab direction, and controlTabOrder setting
55716
- // Is null if no new focus index is determined
55717
- const newFocusIndex = this._getNextFocusIndex(
55718
- focusIndex,
55719
- focusables,
55720
- actives,
55721
- );
55722
-
55723
- // If we have a new focus index, set focus to that element
55724
- if (newFocusIndex !== null) {
55725
- e.preventDefault();
55726
- focusables[newFocusIndex].focus();
55727
- }
55728
- }
55729
-
55730
- /**
55731
- * Catches the keydown event
55732
- * @param {KeyboardEvent} e The keyboard event triggered by user interaction.
55733
- * @private
55734
- */
55735
- _onKeydown = (e) => {
55736
- // Handle tab
55737
- if (e.key === "Tab") this._handleTabKey(e);
55738
- };
55739
-
55740
- /**
55741
- * Retrieves all focusable elements within the container in DOM order, including those in shadow DOM and slots.
55742
- * Returns a unique, ordered array of elements that can receive focus.
55743
- *
55744
- * @returns {Array<HTMLElement>} An array of focusable elements within the container.
55745
- * @private
55746
- */
55747
- _getFocusableElements() {
55748
- // Use the imported utility function to get focusable elements
55749
- const elements = getFocusableElements$2(this.container);
55750
-
55751
- // Return the elements found
55752
- return elements;
55753
- }
55754
-
55755
- /**
55756
- * Moves focus to the first focusable element within the container.
55757
- * Useful for setting initial focus when activating the focus trap.
55758
- */
55759
- focusFirstElement() {
55760
- const focusables = this._getFocusableElements();
55761
- if (focusables.length) focusables[0].focus();
55762
- }
55763
-
55764
- /**
55765
- * Moves focus to the last focusable element within the container.
55766
- * Useful for setting focus when deactivating or cycling focus in reverse.
55767
- */
55768
- focusLastElement() {
55769
- const focusables = this._getFocusableElements();
55770
- if (focusables.length) focusables[focusables.length - 1].focus();
55771
- }
55772
-
55773
- /**
55774
- * Removes event listeners and attributes added by the focus trap.
55775
- * Call this method to clean up when the focus trap is no longer needed.
55776
- */
55777
- disconnect() {
55778
- if (this.container.hasAttribute("data-focus-trap-container")) {
55779
- this.container.removeAttribute("data-focus-trap-container");
55780
- }
55781
-
55782
- this.container.removeEventListener("keydown", this._onKeydown);
55783
- }
55784
- };
55785
-
55786
55470
  // Copyright (c) Alaska Air. All right reserved. Licensed under the Apache-2.0 license
55787
55471
  // See LICENSE in the project root for license information.
55788
55472
 
@@ -56280,7 +55964,7 @@ let AuroDropdownBib$2 = class AuroDropdownBib extends i$3 {
56280
55964
  classes[`shape-${this.shape}`] = true;
56281
55965
 
56282
55966
  return u$c`
56283
- <dialog class="${e$2(classes)}" part="bibContainer" role="${o$4(this.dialogRole)}" aria-labelledby="${o$4(this.dialogLabel ? 'dialogLabel' : undefined)}">
55967
+ <dialog tabindex="-1" class="${e$2(classes)}" part="bibContainer" role="${o$4(this.dialogRole)}" aria-labelledby="${o$4(this.dialogLabel ? 'dialogLabel' : undefined)}">
56284
55968
  ${this.dialogLabel ? u$c`<span id="dialogLabel" class="util_displayHiddenVisually">${this.dialogLabel}</span>` : ''}
56285
55969
  <slot></slot>
56286
55970
  <span id="srAnnouncement" class="util_displayHiddenVisually" aria-live="polite" role="status"></span>
@@ -56531,7 +56215,7 @@ let AuroHelpText$6 = class AuroHelpText extends i$3 {
56531
56215
  }
56532
56216
  };
56533
56217
 
56534
- var formkitVersion$6 = '202607072023';
56218
+ var formkitVersion$6 = '202607102214';
56535
56219
 
56536
56220
  let AuroElement$1$2 = class AuroElement extends i$3 {
56537
56221
  static get properties() {
@@ -56822,7 +56506,7 @@ let AuroDropdown$2 = class AuroDropdown extends AuroElement$1$2 {
56822
56506
  */
56823
56507
  focus() {
56824
56508
  if (this.isPopoverVisible && this.bibContent) {
56825
- const focusables = getFocusableElements$2(this.bibContent);
56509
+ const focusables = getFocusableElements$3(this.bibContent);
56826
56510
  if (focusables.length > 0) {
56827
56511
  focusables[0].focus();
56828
56512
  }
@@ -57285,7 +56969,10 @@ let AuroDropdown$2 = class AuroDropdown extends AuroElement$1$2 {
57285
56969
  }
57286
56970
 
57287
56971
 
57288
- if (!this.isPopoverVisible) {
56972
+ // On Tab-driven close (eventType "focusloss"), let focus advance naturally
56973
+ // — restoring to the trigger would trap the user on this dropdown, forcing
56974
+ // an extra Tab to move on. Escape and outside-click still restore.
56975
+ if (!this.isPopoverVisible && eventType !== "focusloss") {
57289
56976
  // wait til the bib gets fully closed and rendered
57290
56977
  setTimeout(() => {
57291
56978
  // Skip if the bib re-opened, or if focus moved intentionally outside the dropdown (not to body).
@@ -57440,7 +57127,7 @@ let AuroDropdown$2 = class AuroDropdown extends AuroElement$1$2 {
57440
57127
  }
57441
57128
 
57442
57129
  // Collect focusable elements from the bib content.
57443
- const focusables = getFocusableElements$2(this.bibContent);
57130
+ const focusables = getFocusableElements$3(this.bibContent);
57444
57131
 
57445
57132
  // Fallback: try from slotted content directly
57446
57133
  if (!focusables.length) {
@@ -57449,7 +57136,7 @@ let AuroDropdown$2 = class AuroDropdown extends AuroElement$1$2 {
57449
57136
 
57450
57137
  for (const node of assignedNodes) {
57451
57138
  if (node.nodeType === Node.ELEMENT_NODE) {
57452
- focusables.push(...getFocusableElements$2(node));
57139
+ focusables.push(...getFocusableElements$3(node));
57453
57140
  }
57454
57141
  }
57455
57142
  }
@@ -57509,21 +57196,22 @@ let AuroDropdown$2 = class AuroDropdown extends AuroElement$1$2 {
57509
57196
 
57510
57197
  // Move initial focus into the bib content, matching FocusTrap behavior
57511
57198
  requestAnimationFrame(() => {
57512
- const focusables = getFocusableElements$2(this.bibContent);
57199
+ const focusables = getFocusableElements$3(this.bibContent);
57513
57200
  if (focusables.length) {
57514
57201
  focusables[0].focus();
57515
57202
  }
57516
57203
  });
57517
57204
  } else {
57518
- // Normal desktop: use FocusTrap on the bib element.
57519
- // Defer focusFirstElement to the next frame because the popover
57520
- // is positioned asynchronously by Floating UI — calling focus()
57521
- // synchronously here would target elements with zero dimensions
57522
- // and the focus call would be silently ignored.
57523
- this.focusTrap = new FocusTrap$2(this.bibContent);
57205
+ // Normal desktop (non-modal): move initial focus into the bib but
57206
+ // don't trap Tab. Tab should exit the bib and let the floater's
57207
+ // handleFocusLoss close it, matching native <select>/<details>
57208
+ // behavior. Deferred one frame because Floating UI positions the
57209
+ // popover asynchronously a synchronous focus() would target
57210
+ // zero-dimension elements and be silently ignored.
57524
57211
  requestAnimationFrame(() => {
57525
- if (this.focusTrap) {
57526
- this.focusTrap.focusFirstElement();
57212
+ const focusables = getFocusableElements$3(this.bibContent);
57213
+ if (focusables.length) {
57214
+ focusables[0].focus();
57527
57215
  }
57528
57216
  });
57529
57217
  }
@@ -57739,7 +57427,7 @@ let AuroDropdown$2 = class AuroDropdown extends AuroElement$1$2 {
57739
57427
  if (triggerContentNodes) {
57740
57428
 
57741
57429
  // See if any of them are focusable elements
57742
- this.triggerContentFocusable = triggerContentNodes.some((node) => getFocusableElements$2(node).length > 0);
57430
+ this.triggerContentFocusable = triggerContentNodes.some((node) => getFocusableElements$3(node).length > 0);
57743
57431
 
57744
57432
  // If any of them are focusable elements
57745
57433
  if (this.triggerContentFocusable) {
@@ -59121,6 +58809,19 @@ class AuroCounterGroup extends AuroElement$4 {
59121
58809
 
59122
58810
  if (this.isDropdown) {
59123
58811
  applyKeyboardStrategy$1$2(this, counterGroupKeyboardStrategy);
58812
+
58813
+ // noHideOnThisFocusLoss=true on the dropdown prevents handleFocusLoss from
58814
+ // closing the bib when focus moves out via Tab. Close explicitly via focusout:
58815
+ // if relatedTarget is outside the counter-group's light DOM, focus has left.
58816
+ this.addEventListener('focusout', (event) => {
58817
+ if (!this.dropdown?.isPopoverVisible || this.dropdown?.isBibFullscreen) {
58818
+ return;
58819
+ }
58820
+ if (event.relatedTarget && this.contains(event.relatedTarget)) {
58821
+ return;
58822
+ }
58823
+ this.hideBib();
58824
+ });
59124
58825
  }
59125
58826
  }
59126
58827
 
@@ -60511,7 +60212,7 @@ let AuroHelpText$5 = class AuroHelpText extends i$3 {
60511
60212
  }
60512
60213
  };
60513
60214
 
60514
- var formkitVersion$5 = '202607072023';
60215
+ var formkitVersion$5 = '202607102214';
60515
60216
 
60516
60217
  // Copyright (c) Alaska Air. All right reserved. Licensed under the Apache-2.0 license
60517
60218
  // See LICENSE in the project root for license information.
@@ -62276,7 +61977,7 @@ let AuroHelpText$4 = class AuroHelpText extends i$3 {
62276
61977
  }
62277
61978
  };
62278
61979
 
62279
- var formkitVersion$4 = '202607072023';
61980
+ var formkitVersion$4 = '202607102214';
62280
61981
 
62281
61982
  // Copyright (c) 2026 Alaska Airlines. All rights reserved. Licensed under the Apache-2.0 license
62282
61983
  // See LICENSE in the project root for license information.
@@ -63467,6 +63168,188 @@ function navigateArrow$1(component, direction, options = {}) {
63467
63168
  }
63468
63169
  }
63469
63170
 
63171
+ // Selectors for focusable elements
63172
+ const FOCUSABLE_SELECTORS$1 = [
63173
+ "a[href]",
63174
+ "button:not([disabled])",
63175
+ "textarea:not([disabled])",
63176
+ "input:not([disabled])",
63177
+ "select:not([disabled])",
63178
+ '[role="tab"]:not([disabled])',
63179
+ '[role="link"]:not([disabled])',
63180
+ '[role="button"]:not([disabled])',
63181
+ '[tabindex]:not([tabindex="-1"])',
63182
+ '[contenteditable]:not([contenteditable="false"])',
63183
+ ];
63184
+
63185
+ // List of custom components that are known to be focusable
63186
+ const FOCUSABLE_COMPONENTS$1 = [
63187
+ "auro-checkbox",
63188
+ "auro-radio",
63189
+ "auro-dropdown",
63190
+ "auro-button",
63191
+ "auro-combobox",
63192
+ "auro-input",
63193
+ "auro-counter",
63194
+ // 'auro-menu', // Auro menu is not focusable by default, it uses a different interaction model
63195
+ "auro-select",
63196
+ "auro-datepicker",
63197
+ "auro-hyperlink",
63198
+ "auro-accordion",
63199
+ ];
63200
+
63201
+ /**
63202
+ * Determines if a given element is a custom focusable component.
63203
+ * Returns true if the element matches a known focusable component and is not disabled.
63204
+ *
63205
+ * @param {HTMLElement} element The element to check for focusability.
63206
+ * @returns {boolean} True if the element is a focusable custom component, false otherwise.
63207
+ */
63208
+ function isFocusableComponent$1(element) {
63209
+ const componentName = element.tagName.toLowerCase();
63210
+
63211
+ // Guard Clause: Element is a focusable component
63212
+ if (
63213
+ !FOCUSABLE_COMPONENTS$1.some(
63214
+ (name) => element.hasAttribute(name) || componentName === name,
63215
+ )
63216
+ )
63217
+ return false;
63218
+
63219
+ // Guard Clause: Element is not disabled
63220
+ if (element.hasAttribute("disabled")) return false;
63221
+
63222
+ // Guard Clause: The element is a hyperlink and has no href attribute
63223
+ if (componentName.match("hyperlink") && !element.hasAttribute("href"))
63224
+ return false;
63225
+
63226
+ // If all guard clauses pass, the element is a focusable component
63227
+ return true;
63228
+ }
63229
+
63230
+ /**
63231
+ * Safely get a numeric tabindex for an element.
63232
+ * Returns a number if the tabindex is a valid integer, otherwise null.
63233
+ *
63234
+ * @param {HTMLElement} element The element whose tabindex to read.
63235
+ * @returns {?number} The numeric tabindex or null if missing/invalid.
63236
+ */
63237
+ function getNumericTabIndex$1(element) {
63238
+ const raw = element.getAttribute("tabindex");
63239
+ if (raw == null) return null;
63240
+
63241
+ const value = Number.parseInt(raw, 10);
63242
+ return Number.isNaN(value) ? null : value;
63243
+ }
63244
+
63245
+ /**
63246
+ * Retrieves all focusable elements within the container in DOM order, including those in shadow DOM and slots.
63247
+ * Returns a unique, ordered array of elements that can receive focus.
63248
+ * Also sorts elements with tabindex first, preserving their order.
63249
+ *
63250
+ * @param {HTMLElement} container The container to search within
63251
+ * @returns {Array<HTMLElement>} An array of focusable elements within the container.
63252
+ */
63253
+ function getFocusableElements$1(container) {
63254
+ // Get elements in DOM order by walking the tree
63255
+ const orderedFocusableElements = [];
63256
+
63257
+ // Define a recursive function to collect focusable elements in DOM order
63258
+ const collectFocusableElements = (root) => {
63259
+ // Check if current element is focusable
63260
+ if (root.nodeType === Node.ELEMENT_NODE) {
63261
+ // Check if this is a custom component that is focusable
63262
+ const isComponentFocusable = isFocusableComponent$1(root);
63263
+
63264
+ if (isComponentFocusable) {
63265
+ // Add the component itself as a focusable element and don't traverse its shadow DOM
63266
+ orderedFocusableElements.push(root);
63267
+ return; // Skip traversing inside this component
63268
+ }
63269
+
63270
+ // Check if the element itself matches any selector
63271
+ for (const selector of FOCUSABLE_SELECTORS$1) {
63272
+ if (root.matches?.(selector)) {
63273
+ orderedFocusableElements.push(root);
63274
+ break; // Once we know it's focusable, no need to check other selectors
63275
+ }
63276
+ }
63277
+
63278
+ // Process shadow DOM only for non-Auro components
63279
+ if (root.shadowRoot) {
63280
+ // Process shadow DOM children in order
63281
+ if (root.shadowRoot.children) {
63282
+ Array.from(root.shadowRoot.children).forEach((child) => {
63283
+ collectFocusableElements(child);
63284
+ });
63285
+ }
63286
+ }
63287
+
63288
+ // Process slots and their assigned nodes in order
63289
+ if (root.tagName === "SLOT") {
63290
+ const assignedNodes = root.assignedNodes({ flatten: true });
63291
+ for (const node of assignedNodes) {
63292
+ collectFocusableElements(node);
63293
+ }
63294
+ } else {
63295
+ // Process light DOM children in order
63296
+ if (root.children) {
63297
+ Array.from(root.children).forEach((child) => {
63298
+ collectFocusableElements(child);
63299
+ });
63300
+ }
63301
+ }
63302
+ }
63303
+ };
63304
+
63305
+ // Start the traversal from the container
63306
+ collectFocusableElements(container);
63307
+
63308
+ // Remove duplicates that might have been collected through different paths
63309
+ // while preserving order
63310
+ const uniqueElements = [];
63311
+ const seen = new Set();
63312
+
63313
+ for (const element of orderedFocusableElements) {
63314
+ if (!seen.has(element)) {
63315
+ seen.add(element);
63316
+ uniqueElements.push(element);
63317
+ }
63318
+ }
63319
+
63320
+ // Move tab-indexed elements to the front while preserving their order
63321
+ // This ensures that elements with tabindex are prioritized in the focus order
63322
+
63323
+ // First extract elements with valid positive tabindex
63324
+ const elementsWithTabindex = uniqueElements.filter((el) => {
63325
+ const tabindex = getNumericTabIndex$1(el);
63326
+ return tabindex !== null && tabindex > 0;
63327
+ });
63328
+
63329
+ // Sort these elements by their tabindex value
63330
+ elementsWithTabindex.sort((a, b) => {
63331
+ const aIndex = getNumericTabIndex$1(a) ?? 0;
63332
+ const bIndex = getNumericTabIndex$1(b) ?? 0;
63333
+ return aIndex - bIndex;
63334
+ });
63335
+
63336
+ // Elements without tabindex (preserving their original order)
63337
+ const elementsWithoutTabindex = uniqueElements.filter((el) => {
63338
+ const tabindex = getNumericTabIndex$1(el);
63339
+
63340
+ // Elements without tabindex or with tabindex of 0 stay in DOM order
63341
+ return tabindex === null || tabindex === 0;
63342
+ });
63343
+
63344
+ // Combine both arrays with tabindex elements first
63345
+ const tabIndexedUniqueElements = [
63346
+ ...elementsWithTabindex,
63347
+ ...elementsWithoutTabindex,
63348
+ ];
63349
+
63350
+ return tabIndexedUniqueElements;
63351
+ }
63352
+
63470
63353
  /* eslint-disable no-underscore-dangle */
63471
63354
 
63472
63355
  /**
@@ -63512,6 +63395,82 @@ function reconcileMenuIndex(menu) {
63512
63395
  }
63513
63396
  }
63514
63397
 
63398
+ /**
63399
+ * Commit the highlighted option and close the bib.
63400
+ * @param {Element} component - The auro-combobox host element.
63401
+ */
63402
+ function selectAndClose(component) {
63403
+ reconcileMenuIndex(component.menu);
63404
+ component.menu.makeSelection();
63405
+ component.hideBib();
63406
+ }
63407
+
63408
+ /**
63409
+ * Whether `el` is currently visible enough to receive focus. Prefers the
63410
+ * browser's `checkVisibility()` (Chrome/Safari; Firefox behind a flag until
63411
+ * recently); otherwise combines a display/visibility check with an
63412
+ * ancestor-hidden probe that keeps position:fixed elements visible.
63413
+ * @param {Element} el - The element to test.
63414
+ * @returns {boolean}
63415
+ */
63416
+ function isVisibleForFocus(el) {
63417
+ if (typeof el.checkVisibility === 'function') {
63418
+ return el.checkVisibility();
63419
+ }
63420
+ const style = el.ownerDocument.defaultView.getComputedStyle(el);
63421
+ if (style.display === 'none' || style.visibility === 'hidden') {
63422
+ return false;
63423
+ }
63424
+ return el.offsetParent !== null || style.position === 'fixed';
63425
+ }
63426
+
63427
+ /**
63428
+ * Return the tab stop that comes before `component` in page tab order,
63429
+ * skipping any hidden entries the walker doesn't filter itself.
63430
+ * @param {Element} component - The auro-combobox host element.
63431
+ * @returns {Element|null}
63432
+ */
63433
+ function getPreviousTabStop(component) {
63434
+ const tabStops = getFocusableElements$1(component.ownerDocument.body);
63435
+ const componentIndex = tabStops.indexOf(component);
63436
+ for (let index = componentIndex - 1; index >= 0; index -= 1) {
63437
+ if (isVisibleForFocus(tabStops[index])) {
63438
+ return tabStops[index];
63439
+ }
63440
+ }
63441
+ return null;
63442
+ }
63443
+
63444
+ /**
63445
+ * Commit the highlighted option, close the bib, and move focus to the tab
63446
+ * stop before the combobox — the Shift+Tab exit path (AB#1592239).
63447
+ * Returns true when this function moved focus and the caller should
63448
+ * preventDefault; false when no previous tab stop was found and the browser's
63449
+ * native traversal should run.
63450
+ * @param {Element} component - The auro-combobox host element.
63451
+ * @returns {boolean}
63452
+ */
63453
+ function selectAndExitBackward(component) {
63454
+ const previousTabStop = getPreviousTabStop(component);
63455
+
63456
+ // Opts this selection out of setClearBtnFocus so the focus move below
63457
+ // isn't clobbered. Consumed by auro-combobox's selection listener; also
63458
+ // cleared via microtask in case makeSelection is a no-op and the listener
63459
+ // never fires (microtasks run before the next user event, so this can't
63460
+ // leak into an unrelated selection).
63461
+ component._suppressClearBtnFocusOnSelection = true;
63462
+ selectAndClose(component);
63463
+ queueMicrotask(() => {
63464
+ component._suppressClearBtnFocusOnSelection = false;
63465
+ });
63466
+
63467
+ if (!previousTabStop) {
63468
+ return false;
63469
+ }
63470
+ doubleRaf$1(() => previousTabStop.focus());
63471
+ return true;
63472
+ }
63473
+
63515
63474
  const comboboxKeyboardStrategy = {
63516
63475
  ArrowDown(component, evt, ctx) {
63517
63476
  // If the clear button has focus, let the browser handle ArrowDown normally.
@@ -63611,18 +63570,17 @@ const comboboxKeyboardStrategy = {
63611
63570
 
63612
63571
  Tab(component, evt, ctx) {
63613
63572
  if (ctx.isExpanded && !isClearBtnFocused(ctx)) {
63614
- // When the clear button is focused, Tab events do not bubble out of
63615
- // its shadow DOM, so this handler only fires when the clear button
63616
- // is NOT focused. In that case, select the active option and close.
63617
- reconcileMenuIndex(component.menu);
63618
- component.menu.makeSelection();
63619
- component.hideBib();
63573
+ if (evt.shiftKey) {
63574
+ if (selectAndExitBackward(component)) {
63575
+ evt.preventDefault();
63576
+ }
63577
+ return;
63578
+ }
63579
+
63580
+ selectAndClose(component);
63620
63581
 
63621
- // In fullscreen modal mode, closing the dialog does not
63622
- // automatically restores focus to the input. In the tab case,
63623
- // Explicitly move focus to the trigger's clear button so the
63624
- // user can continues tabbing through the page normally.
63625
- if (ctx.isModal && !evt.shiftKey) {
63582
+ if (ctx.isModal) {
63583
+ // Fullscreen close does not automatically restore focus to the input.
63626
63584
  component.setClearBtnFocus();
63627
63585
  }
63628
63586
  }
@@ -65881,12 +65839,40 @@ let AuroFloatingUI$1 = class AuroFloatingUI {
65881
65839
  return;
65882
65840
  }
65883
65841
 
65842
+ // Chrome-specific: during popover top-layer promotion after a click on a
65843
+ // slotted focusable, :focus-within can briefly evaluate false while the
65844
+ // active element is still structurally inside the trigger/bib. Fall back
65845
+ // to a shadow-piercing ancestry walk from the deep active element before
65846
+ // treating this as a real focus loss.
65847
+ try {
65848
+ let active = document.activeElement;
65849
+ while (active && active.shadowRoot && active.shadowRoot.activeElement) {
65850
+ active = active.shadowRoot.activeElement;
65851
+ }
65852
+ const targets = [element, element.trigger, element.bib].filter(Boolean);
65853
+ let node = active;
65854
+ while (node) {
65855
+ if (targets.includes(node)) {
65856
+ return;
65857
+ }
65858
+ node =
65859
+ node.parentElement ||
65860
+ (node.getRootNode && node.getRootNode().host) ||
65861
+ null;
65862
+ }
65863
+ } catch (e) {
65864
+ // Defensive: fall through to the existing close path if traversal fails.
65865
+ }
65866
+
65884
65867
  // if fullscreen bib is in fullscreen mode, do not close
65885
65868
  if (element.bib.hasAttribute("isfullscreen")) {
65886
65869
  return;
65887
65870
  }
65888
65871
 
65889
- this.hideBib("keydown");
65872
+ // eventType "focusloss" distinguishes a Tab/click-driven close from an
65873
+ // Escape keydown close. Consumers use this to decide whether to restore
65874
+ // focus to the trigger (Escape) or let it advance naturally (Tab).
65875
+ this.hideBib("focusloss");
65890
65876
  }
65891
65877
 
65892
65878
  setupHideHandlers() {
@@ -66375,7 +66361,7 @@ let AuroFloatingUI$1 = class AuroFloatingUI {
66375
66361
  };
66376
66362
 
66377
66363
  // Selectors for focusable elements
66378
- const FOCUSABLE_SELECTORS$1 = [
66364
+ const FOCUSABLE_SELECTORS$2 = [
66379
66365
  "a[href]",
66380
66366
  "button:not([disabled])",
66381
66367
  "textarea:not([disabled])",
@@ -66389,7 +66375,7 @@ const FOCUSABLE_SELECTORS$1 = [
66389
66375
  ];
66390
66376
 
66391
66377
  // List of custom components that are known to be focusable
66392
- const FOCUSABLE_COMPONENTS$1 = [
66378
+ const FOCUSABLE_COMPONENTS$2 = [
66393
66379
  "auro-checkbox",
66394
66380
  "auro-radio",
66395
66381
  "auro-dropdown",
@@ -66411,12 +66397,12 @@ const FOCUSABLE_COMPONENTS$1 = [
66411
66397
  * @param {HTMLElement} element The element to check for focusability.
66412
66398
  * @returns {boolean} True if the element is a focusable custom component, false otherwise.
66413
66399
  */
66414
- function isFocusableComponent$1(element) {
66400
+ function isFocusableComponent$2(element) {
66415
66401
  const componentName = element.tagName.toLowerCase();
66416
66402
 
66417
66403
  // Guard Clause: Element is a focusable component
66418
66404
  if (
66419
- !FOCUSABLE_COMPONENTS$1.some(
66405
+ !FOCUSABLE_COMPONENTS$2.some(
66420
66406
  (name) => element.hasAttribute(name) || componentName === name,
66421
66407
  )
66422
66408
  )
@@ -66440,7 +66426,7 @@ function isFocusableComponent$1(element) {
66440
66426
  * @param {HTMLElement} element The element whose tabindex to read.
66441
66427
  * @returns {?number} The numeric tabindex or null if missing/invalid.
66442
66428
  */
66443
- function getNumericTabIndex$1(element) {
66429
+ function getNumericTabIndex$2(element) {
66444
66430
  const raw = element.getAttribute("tabindex");
66445
66431
  if (raw == null) return null;
66446
66432
 
@@ -66456,7 +66442,7 @@ function getNumericTabIndex$1(element) {
66456
66442
  * @param {HTMLElement} container The container to search within
66457
66443
  * @returns {Array<HTMLElement>} An array of focusable elements within the container.
66458
66444
  */
66459
- function getFocusableElements$1(container) {
66445
+ function getFocusableElements$2(container) {
66460
66446
  // Get elements in DOM order by walking the tree
66461
66447
  const orderedFocusableElements = [];
66462
66448
 
@@ -66465,7 +66451,7 @@ function getFocusableElements$1(container) {
66465
66451
  // Check if current element is focusable
66466
66452
  if (root.nodeType === Node.ELEMENT_NODE) {
66467
66453
  // Check if this is a custom component that is focusable
66468
- const isComponentFocusable = isFocusableComponent$1(root);
66454
+ const isComponentFocusable = isFocusableComponent$2(root);
66469
66455
 
66470
66456
  if (isComponentFocusable) {
66471
66457
  // Add the component itself as a focusable element and don't traverse its shadow DOM
@@ -66474,7 +66460,7 @@ function getFocusableElements$1(container) {
66474
66460
  }
66475
66461
 
66476
66462
  // Check if the element itself matches any selector
66477
- for (const selector of FOCUSABLE_SELECTORS$1) {
66463
+ for (const selector of FOCUSABLE_SELECTORS$2) {
66478
66464
  if (root.matches?.(selector)) {
66479
66465
  orderedFocusableElements.push(root);
66480
66466
  break; // Once we know it's focusable, no need to check other selectors
@@ -66528,20 +66514,20 @@ function getFocusableElements$1(container) {
66528
66514
 
66529
66515
  // First extract elements with valid positive tabindex
66530
66516
  const elementsWithTabindex = uniqueElements.filter((el) => {
66531
- const tabindex = getNumericTabIndex$1(el);
66517
+ const tabindex = getNumericTabIndex$2(el);
66532
66518
  return tabindex !== null && tabindex > 0;
66533
66519
  });
66534
66520
 
66535
66521
  // Sort these elements by their tabindex value
66536
66522
  elementsWithTabindex.sort((a, b) => {
66537
- const aIndex = getNumericTabIndex$1(a) ?? 0;
66538
- const bIndex = getNumericTabIndex$1(b) ?? 0;
66523
+ const aIndex = getNumericTabIndex$2(a) ?? 0;
66524
+ const bIndex = getNumericTabIndex$2(b) ?? 0;
66539
66525
  return aIndex - bIndex;
66540
66526
  });
66541
66527
 
66542
66528
  // Elements without tabindex (preserving their original order)
66543
66529
  const elementsWithoutTabindex = uniqueElements.filter((el) => {
66544
- const tabindex = getNumericTabIndex$1(el);
66530
+ const tabindex = getNumericTabIndex$2(el);
66545
66531
 
66546
66532
  // Elements without tabindex or with tabindex of 0 stay in DOM order
66547
66533
  return tabindex === null || tabindex === 0;
@@ -66556,199 +66542,6 @@ function getFocusableElements$1(container) {
66556
66542
  return tabIndexedUniqueElements;
66557
66543
  }
66558
66544
 
66559
- /**
66560
- * FocusTrap manages keyboard focus within a specified container element, ensuring that focus does not leave the container when tabbing.
66561
- * It is commonly used for modal dialogs or overlays to improve accessibility by trapping focus within interactive UI components.
66562
- */
66563
- let FocusTrap$1 = class FocusTrap {
66564
- /**
66565
- * Creates a new FocusTrap instance for the given container element.
66566
- * Initializes event listeners and prepares the container for focus management.
66567
- *
66568
- * @param {HTMLElement} container The DOM element to trap focus within.
66569
- * @param {boolean} [controlTabOrder=false] If true enables manual control of the tab order by the FocusTrap.
66570
- * @throws {Error} If the provided container is not a valid HTMLElement.
66571
- */
66572
- constructor(container, controlTabOrder = false) {
66573
- if (!container || !(container instanceof HTMLElement)) {
66574
- throw new Error("FocusTrap requires a valid HTMLElement.");
66575
- }
66576
-
66577
- this.container = container;
66578
- this.tabDirection = "forward"; // or 'backward';
66579
- this.controlTabOrder = controlTabOrder;
66580
-
66581
- this._init();
66582
- }
66583
-
66584
- /**
66585
- * Initializes the focus trap by setting up event listeners and attributes on the container.
66586
- * Prepares the container for focus management, including support for shadow DOM and inert attributes.
66587
- *
66588
- * @private
66589
- */
66590
- _init() {
66591
- // Add inert attribute to prevent focusing programmatically as well (if supported)
66592
- if ("inert" in HTMLElement.prototype) {
66593
- this.container.inert = false; // Ensure the container isn't inert
66594
- this.container.setAttribute("data-focus-trap-container", true); // Mark for identification
66595
- }
66596
-
66597
- // Track tab direction
66598
- this.container.addEventListener("keydown", this._onKeydown);
66599
- }
66600
-
66601
- /**
66602
- * Gets an array of currently active (focused) elements in the document and shadow DOM.
66603
- * @returns {Array<HTMLElement>} An array of focusable elements within the container.
66604
- * @private
66605
- */
66606
- _getActiveElements() {
66607
- // Get the active element(s) in the document and shadow root
66608
- // This will include the active element in the shadow DOM if it exists
66609
- // Active element may be inside the shadow DOM depending on delegatesFocus, so we need to check both
66610
- let { activeElement } = document;
66611
- const actives = [activeElement];
66612
- while (activeElement?.shadowRoot?.activeElement) {
66613
- actives.push(activeElement.shadowRoot.activeElement);
66614
- activeElement = activeElement.shadowRoot.activeElement;
66615
- }
66616
- return actives;
66617
- }
66618
-
66619
- /**
66620
- * Gets the next focus index based on the current index and focusable elements.
66621
- * @param {number} currentIndex The current index of the focused element.
66622
- * @param {Array<HTMLElement>} focusables The array of focusable elements.
66623
- * @returns {number|null} The next focus index or null if not determined.
66624
- */
66625
- _getNextFocusIndex(currentIndex, focusables, actives) {
66626
- if (this.controlTabOrder) {
66627
- // Calculate the new index based on the current index and tab direction
66628
- let newFocusIndex =
66629
- currentIndex + (this.tabDirection === "forward" ? 1 : -1);
66630
-
66631
- // Wrap-around logic
66632
- if (newFocusIndex < 0) newFocusIndex = focusables.length - 1;
66633
- if (newFocusIndex >= focusables.length) newFocusIndex = 0;
66634
-
66635
- // Early return with the new index
66636
- return newFocusIndex;
66637
- }
66638
-
66639
- // Determine if we need to wrap
66640
- const atFirst =
66641
- actives.includes(focusables[0]) || actives.includes(this.container);
66642
- const atLast = actives.includes(focusables[focusables.length - 1]);
66643
-
66644
- // Only wrap if at the ends
66645
- if (this.tabDirection === "backward" && atFirst) {
66646
- return focusables.length - 1;
66647
- }
66648
-
66649
- if (this.tabDirection === "forward" && atLast) {
66650
- return 0;
66651
- }
66652
-
66653
- // No wrap, so don't change focus, return early
66654
- return null;
66655
- }
66656
-
66657
- /**
66658
- * Handles the Tab key press event to manage focus within the container.
66659
- * @param {KeyboardEvent} e The keyboard event triggered by the user.
66660
- * @returns {void}
66661
- */
66662
- _handleTabKey(e) {
66663
- // Update the focusable elements
66664
- const focusables = this._getFocusableElements();
66665
-
66666
- // If there are no focusable elements, exit
66667
- if (!focusables.length) return;
66668
-
66669
- // Set the tab direction based on the key pressed
66670
- this.tabDirection = e.shiftKey ? "backward" : "forward";
66671
-
66672
- // Get the active elements that are currently focused
66673
- const actives = this._getActiveElements();
66674
-
66675
- // If we're at either end of the focusable elements, wrap around to the other end
66676
- let focusIndex = focusables.findIndex((el) => actives.includes(el));
66677
-
66678
- // Fallback if we have no focused element
66679
- if (focusIndex === -1) focusIndex = 0;
66680
-
66681
- // Get the next focus index based on the current focus index, tab direction, and controlTabOrder setting
66682
- // Is null if no new focus index is determined
66683
- const newFocusIndex = this._getNextFocusIndex(
66684
- focusIndex,
66685
- focusables,
66686
- actives,
66687
- );
66688
-
66689
- // If we have a new focus index, set focus to that element
66690
- if (newFocusIndex !== null) {
66691
- e.preventDefault();
66692
- focusables[newFocusIndex].focus();
66693
- }
66694
- }
66695
-
66696
- /**
66697
- * Catches the keydown event
66698
- * @param {KeyboardEvent} e The keyboard event triggered by user interaction.
66699
- * @private
66700
- */
66701
- _onKeydown = (e) => {
66702
- // Handle tab
66703
- if (e.key === "Tab") this._handleTabKey(e);
66704
- };
66705
-
66706
- /**
66707
- * Retrieves all focusable elements within the container in DOM order, including those in shadow DOM and slots.
66708
- * Returns a unique, ordered array of elements that can receive focus.
66709
- *
66710
- * @returns {Array<HTMLElement>} An array of focusable elements within the container.
66711
- * @private
66712
- */
66713
- _getFocusableElements() {
66714
- // Use the imported utility function to get focusable elements
66715
- const elements = getFocusableElements$1(this.container);
66716
-
66717
- // Return the elements found
66718
- return elements;
66719
- }
66720
-
66721
- /**
66722
- * Moves focus to the first focusable element within the container.
66723
- * Useful for setting initial focus when activating the focus trap.
66724
- */
66725
- focusFirstElement() {
66726
- const focusables = this._getFocusableElements();
66727
- if (focusables.length) focusables[0].focus();
66728
- }
66729
-
66730
- /**
66731
- * Moves focus to the last focusable element within the container.
66732
- * Useful for setting focus when deactivating or cycling focus in reverse.
66733
- */
66734
- focusLastElement() {
66735
- const focusables = this._getFocusableElements();
66736
- if (focusables.length) focusables[focusables.length - 1].focus();
66737
- }
66738
-
66739
- /**
66740
- * Removes event listeners and attributes added by the focus trap.
66741
- * Call this method to clean up when the focus trap is no longer needed.
66742
- */
66743
- disconnect() {
66744
- if (this.container.hasAttribute("data-focus-trap-container")) {
66745
- this.container.removeAttribute("data-focus-trap-container");
66746
- }
66747
-
66748
- this.container.removeEventListener("keydown", this._onKeydown);
66749
- }
66750
- };
66751
-
66752
66545
  // Copyright (c) Alaska Air. All right reserved. Licensed under the Apache-2.0 license
66753
66546
  // See LICENSE in the project root for license information.
66754
66547
 
@@ -67246,7 +67039,7 @@ let AuroDropdownBib$1 = class AuroDropdownBib extends i$3 {
67246
67039
  classes[`shape-${this.shape}`] = true;
67247
67040
 
67248
67041
  return u$c`
67249
- <dialog class="${e$2(classes)}" part="bibContainer" role="${o$4(this.dialogRole)}" aria-labelledby="${o$4(this.dialogLabel ? 'dialogLabel' : undefined)}">
67042
+ <dialog tabindex="-1" class="${e$2(classes)}" part="bibContainer" role="${o$4(this.dialogRole)}" aria-labelledby="${o$4(this.dialogLabel ? 'dialogLabel' : undefined)}">
67250
67043
  ${this.dialogLabel ? u$c`<span id="dialogLabel" class="util_displayHiddenVisually">${this.dialogLabel}</span>` : ''}
67251
67044
  <slot></slot>
67252
67045
  <span id="srAnnouncement" class="util_displayHiddenVisually" aria-live="polite" role="status"></span>
@@ -67497,7 +67290,7 @@ let AuroHelpText$2 = class AuroHelpText extends i$3 {
67497
67290
  }
67498
67291
  };
67499
67292
 
67500
- var formkitVersion$2 = '202607072023';
67293
+ var formkitVersion$2 = '202607102214';
67501
67294
 
67502
67295
  let AuroElement$2$1 = class AuroElement extends i$3 {
67503
67296
  static get properties() {
@@ -67788,7 +67581,7 @@ let AuroDropdown$1 = class AuroDropdown extends AuroElement$2$1 {
67788
67581
  */
67789
67582
  focus() {
67790
67583
  if (this.isPopoverVisible && this.bibContent) {
67791
- const focusables = getFocusableElements$1(this.bibContent);
67584
+ const focusables = getFocusableElements$2(this.bibContent);
67792
67585
  if (focusables.length > 0) {
67793
67586
  focusables[0].focus();
67794
67587
  }
@@ -68251,7 +68044,10 @@ let AuroDropdown$1 = class AuroDropdown extends AuroElement$2$1 {
68251
68044
  }
68252
68045
 
68253
68046
 
68254
- if (!this.isPopoverVisible) {
68047
+ // On Tab-driven close (eventType "focusloss"), let focus advance naturally
68048
+ // — restoring to the trigger would trap the user on this dropdown, forcing
68049
+ // an extra Tab to move on. Escape and outside-click still restore.
68050
+ if (!this.isPopoverVisible && eventType !== "focusloss") {
68255
68051
  // wait til the bib gets fully closed and rendered
68256
68052
  setTimeout(() => {
68257
68053
  // Skip if the bib re-opened, or if focus moved intentionally outside the dropdown (not to body).
@@ -68406,7 +68202,7 @@ let AuroDropdown$1 = class AuroDropdown extends AuroElement$2$1 {
68406
68202
  }
68407
68203
 
68408
68204
  // Collect focusable elements from the bib content.
68409
- const focusables = getFocusableElements$1(this.bibContent);
68205
+ const focusables = getFocusableElements$2(this.bibContent);
68410
68206
 
68411
68207
  // Fallback: try from slotted content directly
68412
68208
  if (!focusables.length) {
@@ -68415,7 +68211,7 @@ let AuroDropdown$1 = class AuroDropdown extends AuroElement$2$1 {
68415
68211
 
68416
68212
  for (const node of assignedNodes) {
68417
68213
  if (node.nodeType === Node.ELEMENT_NODE) {
68418
- focusables.push(...getFocusableElements$1(node));
68214
+ focusables.push(...getFocusableElements$2(node));
68419
68215
  }
68420
68216
  }
68421
68217
  }
@@ -68475,21 +68271,22 @@ let AuroDropdown$1 = class AuroDropdown extends AuroElement$2$1 {
68475
68271
 
68476
68272
  // Move initial focus into the bib content, matching FocusTrap behavior
68477
68273
  requestAnimationFrame(() => {
68478
- const focusables = getFocusableElements$1(this.bibContent);
68274
+ const focusables = getFocusableElements$2(this.bibContent);
68479
68275
  if (focusables.length) {
68480
68276
  focusables[0].focus();
68481
68277
  }
68482
68278
  });
68483
68279
  } else {
68484
- // Normal desktop: use FocusTrap on the bib element.
68485
- // Defer focusFirstElement to the next frame because the popover
68486
- // is positioned asynchronously by Floating UI — calling focus()
68487
- // synchronously here would target elements with zero dimensions
68488
- // and the focus call would be silently ignored.
68489
- this.focusTrap = new FocusTrap$1(this.bibContent);
68280
+ // Normal desktop (non-modal): move initial focus into the bib but
68281
+ // don't trap Tab. Tab should exit the bib and let the floater's
68282
+ // handleFocusLoss close it, matching native <select>/<details>
68283
+ // behavior. Deferred one frame because Floating UI positions the
68284
+ // popover asynchronously a synchronous focus() would target
68285
+ // zero-dimension elements and be silently ignored.
68490
68286
  requestAnimationFrame(() => {
68491
- if (this.focusTrap) {
68492
- this.focusTrap.focusFirstElement();
68287
+ const focusables = getFocusableElements$2(this.bibContent);
68288
+ if (focusables.length) {
68289
+ focusables[0].focus();
68493
68290
  }
68494
68291
  });
68495
68292
  }
@@ -68705,7 +68502,7 @@ let AuroDropdown$1 = class AuroDropdown extends AuroElement$2$1 {
68705
68502
  if (triggerContentNodes) {
68706
68503
 
68707
68504
  // See if any of them are focusable elements
68708
- this.triggerContentFocusable = triggerContentNodes.some((node) => getFocusableElements$1(node).length > 0);
68505
+ this.triggerContentFocusable = triggerContentNodes.some((node) => getFocusableElements$2(node).length > 0);
68709
68506
 
68710
68507
  // If any of them are focusable elements
68711
68508
  if (this.triggerContentFocusable) {
@@ -81115,7 +80912,7 @@ let AuroHelpText$1$1 = class AuroHelpText extends i$3 {
81115
80912
  }
81116
80913
  };
81117
80914
 
81118
- var formkitVersion$1$1 = '202607072023';
80915
+ var formkitVersion$1$1 = '202607102214';
81119
80916
 
81120
80917
  // Copyright (c) 2025 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
81121
80918
  // See LICENSE in the project root for license information.
@@ -82236,7 +82033,7 @@ let AuroBibtemplate$1 = class AuroBibtemplate extends i$3 {
82236
82033
  }
82237
82034
  };
82238
82035
 
82239
- var formkitVersion$3 = '202607072023';
82036
+ var formkitVersion$3 = '202607102214';
82240
82037
 
82241
82038
  var styleCss$1$3 = i$6`.util_displayInline{display:inline}.util_displayInlineBlock{display:inline-block}.util_displayBlock{display:block}.util_displayFlex{display:flex}.util_displayHidden{display:none}.util_displayHiddenVisually{position:absolute;overflow:hidden;clip:rect(1px, 1px, 1px, 1px);width:1px;height:1px;padding:0;border:0}:host{display:block;text-align:left}:host [auro-dropdown]{--ds-auro-dropdown-trigger-background-color: transparent}:host #inputInBib::part(wrapper){box-shadow:none}:host #inputInBib::part(accent-left){display:none}:host([layout*=classic]) [auro-input]{width:100%}:host([layout*=classic]) [auro-input]::part(helpText){display:none}:host([layout*=classic]) #slotHolder{display:none}`;
82242
82039
 
@@ -83019,6 +82816,8 @@ class AuroCombobox extends AuroElement$3 {
83019
82816
 
83020
82817
  /**
83021
82818
  * If set, the `icon` attribute will be applied to the trigger `auro-input` element.
82819
+ * Icon rendering is currently limited to `type="credit-card"`. Setting `triggerIcon`
82820
+ * without a supported `type` propagates the attribute but does not render a visible icon.
83022
82821
  */
83023
82822
  triggerIcon: {
83024
82823
  type: Boolean,
@@ -83050,7 +82849,7 @@ class AuroCombobox extends AuroElement$3 {
83050
82849
  },
83051
82850
 
83052
82851
  /**
83053
- * Value selected for the dropdown menu.
82852
+ * 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.
83054
82853
  */
83055
82854
  value: {
83056
82855
  type: String
@@ -83546,7 +83345,12 @@ class AuroCombobox extends AuroElement$3 {
83546
83345
  this.dropdown.bibDialogLabel = labelElement.textContent.trim() || undefined;
83547
83346
  }
83548
83347
 
83549
- // Exposes the CSS parts from the bibtemplate for styling
83348
+ if (this.customBibWidth) {
83349
+ this.dropdown.dropdownWidth = this.customBibWidth;
83350
+ }
83351
+
83352
+ // Exposes the CSS parts from the dropdown and bibtemplate for styling
83353
+ this.dropdown.exposeCssParts();
83550
83354
  this.bibtemplate.exposeCssParts();
83551
83355
 
83552
83356
  this.hideBib = this.hideBib.bind(this);
@@ -83766,8 +83570,11 @@ class AuroCombobox extends AuroElement$3 {
83766
83570
  // do not close while typing in suggestion mode with no value selected, to allow freeform input
83767
83571
  this.hideBib();
83768
83572
 
83769
- // Move focus to the clear button when the user makes a selection.
83770
- if (!isEcho && this.menu.value !== undefined) {
83573
+ // Move focus to the clear button when the user makes a selection,
83574
+ // unless the Shift+Tab handler opted this selection out.
83575
+ if (this._suppressClearBtnFocusOnSelection) {
83576
+ this._suppressClearBtnFocusOnSelection = false;
83577
+ } else if (!isEcho && this.menu.value !== undefined) {
83771
83578
  this.setClearBtnFocus();
83772
83579
  }
83773
83580
 
@@ -84173,6 +83980,12 @@ class AuroCombobox extends AuroElement$3 {
84173
83980
  this.value = undefined;
84174
83981
  this.typedValue = undefined;
84175
83982
  this.input.value = undefined;
83983
+ // Fullscreen bib mounts a second auro-input that holds the user-facing
83984
+ // native <input> on mobile; clearing only the trigger leaves stale text
83985
+ // there when the bib is reopened after reset.
83986
+ if (this.inputInBib) {
83987
+ this.inputInBib.value = undefined;
83988
+ }
84176
83989
  this.menu.value = undefined;
84177
83990
  this.validation.reset(this);
84178
83991
  this.touched = false;
@@ -84751,6 +84564,18 @@ let AuroLibraryRuntimeUtils$4 = class AuroLibraryRuntimeUtils {
84751
84564
  }
84752
84565
  };
84753
84566
 
84567
+ /**
84568
+ * Serializes a multi-select value array back into the String `value` property.
84569
+ * An empty (or missing) array collapses to `undefined` so an emptied selection
84570
+ * clears `value` rather than reflecting a `"[]"` attribute.
84571
+ * @private
84572
+ * @param {Array<string>|undefined} values - The selected values.
84573
+ * @returns {string|undefined} JSON string of the values, or undefined when empty.
84574
+ */
84575
+ function serializeMultiSelectValue(values) {
84576
+ return values && values.length > 0 ? JSON.stringify(values) : undefined;
84577
+ }
84578
+
84754
84579
  /**
84755
84580
  * Validates if an option can be interacted with.
84756
84581
  * @private
@@ -84763,6 +84588,20 @@ function isOptionInteractive(option) {
84763
84588
  !option.hasAttribute('static');
84764
84589
  }
84765
84590
 
84591
+ /**
84592
+ * Validates if an option may be selected by matching a programmatic value.
84593
+ * Unlike `isOptionInteractive`, `hidden` is allowed: the combobox toggles
84594
+ * `hidden` as its type-ahead filter, so a filtered-out option is still a
84595
+ * valid programmatic selection. Only disabled and static options — which are
84596
+ * never selectable — are rejected.
84597
+ * @param {HTMLElement} option - The option to check.
84598
+ * @returns {boolean} True if option can be selected by value.
84599
+ */
84600
+ function isSelectableByValue(option) {
84601
+ return !option.hasAttribute('disabled') &&
84602
+ !option.hasAttribute('static');
84603
+ }
84604
+
84766
84605
  /**
84767
84606
  * Helper method to dispatch custom events.
84768
84607
  * @param {HTMLElement} element - Element to dispatch event from.
@@ -84932,22 +84771,26 @@ class AuroMenu extends AuroElement$2 {
84932
84771
 
84933
84772
  /**
84934
84773
  * Specifies the current active menuOption.
84774
+ * @readonly
84935
84775
  */
84936
84776
  optionActive: {
84937
84777
  type: Object,
84938
- attribute: 'optionactive'
84778
+ attribute: false
84939
84779
  },
84940
84780
 
84941
84781
  /**
84942
- * An array of currently selected menu options, type `HTMLElement` by default. In multi-select mode, `optionSelected` is an array of HTML elements.
84782
+ * 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.
84783
+ * @readonly
84943
84784
  */
84944
84785
  optionSelected: {
84945
84786
  // Allow HTMLElement, HTMLElement[] arrays and undefined
84946
- type: Object
84787
+ type: Object,
84788
+ attribute: false
84947
84789
  },
84948
84790
 
84949
84791
  /**
84950
84792
  * The value of the selected option. In multi-select mode, this is a JSON stringified array of selected option values.
84793
+ * 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.
84951
84794
  */
84952
84795
  value: {
84953
84796
  type: String,
@@ -85071,7 +84914,7 @@ class AuroMenu extends AuroElement$2 {
85071
84914
  }
85072
84915
 
85073
84916
  /**
85074
- * Selects options by value.
84917
+ * 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.
85075
84918
  * @param {string|string[]|undefined|null} value - The value(s) to select.
85076
84919
  * @public
85077
84920
  */
@@ -85156,6 +84999,11 @@ class AuroMenu extends AuroElement$2 {
85156
84999
  this.initItems();
85157
85000
  }
85158
85001
 
85002
+ // Set when reconciliation reassigns `value` below. That reassignment schedules a
85003
+ // second updated() cycle, so the `event`-attribute dispatch is deferred to that
85004
+ // cycle to avoid firing option custom events twice on the same selection.
85005
+ let valueReconciled = false;
85006
+
85159
85007
  // Handle null/undefined/empty case — empty/whitespace strings clear selection
85160
85008
  // consistently with selectByValue(''), and avoid downstream `.includes('')` matches.
85161
85009
  if (this.value === undefined || this.value === null || (typeof this.value === 'string' && this.value.trim() === '')) {
@@ -85168,11 +85016,31 @@ class AuroMenu extends AuroElement$2 {
85168
85016
  // Defensive default: `formattedValue` can be undefined for unexpected value types,
85169
85017
  // and calling `.includes` on undefined would throw during reconciliation.
85170
85018
  const valueArray = this.formattedValue || [];
85171
- const matchingOptions = this.items ? this.items.filter((item) => valueArray.includes(item.value)) : [];
85019
+ const matchingOptions = this.items ? this.items.filter((item) => isSelectableByValue(item) && valueArray.includes(item.value)) : [];
85172
85020
  newSelected = matchingOptions.length > 0 ? matchingOptions : undefined;
85021
+
85022
+ // Reconcile `value` with the selectable set. Drop only entries whose option is
85023
+ // loaded but non-selectable (disabled/static) — leaving them would desync `value`
85024
+ // from `optionSelected`, and the toggle handlers rebuild `value` from `formattedValue`,
85025
+ // so the rejected entry would resurface on the next select/deselect. Entries with no
85026
+ // matching item yet are preserved so async preselection still works once options render.
85027
+ const rejectedValues = this.items
85028
+ ? this.items.filter((item) => !isSelectableByValue(item) && valueArray.includes(item.value)).map((item) => item.value)
85029
+ : [];
85030
+ if (rejectedValues.length > 0) {
85031
+ const reconciled = valueArray.filter((val) => !rejectedValues.includes(val));
85032
+ this.value = serializeMultiSelectValue(reconciled);
85033
+ valueReconciled = true;
85034
+ }
85173
85035
  } else {
85174
- // In single-select mode, this.value should be a string
85175
- const matchingOption = this.items ? this.items.find((item) => item.value === this.value) : undefined;
85036
+ // In single-select mode, this.value should be a string. Reject
85037
+ // disabled/static options so a programmatic value pointing at a
85038
+ // non-selectable option falls through to the no-match path below
85039
+ // (dispatching auroMenu-selectValueFailure) instead of pinning it.
85040
+ // `hidden` is intentionally NOT excluded: the combobox toggles
85041
+ // `hidden` as its type-ahead filter, so a filtered-out option is
85042
+ // still a valid programmatic selection.
85043
+ const matchingOption = this.items ? this.items.find((item) => isSelectableByValue(item) && item.value === this.value) : undefined;
85176
85044
 
85177
85045
  if (matchingOption) {
85178
85046
  newSelected = matchingOption;
@@ -85214,8 +85082,9 @@ class AuroMenu extends AuroElement$2 {
85214
85082
  ]
85215
85083
  ]));
85216
85084
 
85217
- // Notify of changes
85218
- if (this.optionSelected !== undefined) {
85085
+ // Notify of changes. Skip when reconciliation just reassigned `value`: the
85086
+ // follow-on update cycle re-runs this branch and fires the events exactly once.
85087
+ if (this.optionSelected !== undefined && !valueReconciled) {
85219
85088
  const selected = Array.isArray(this.optionSelected) ? this.optionSelected : [this.optionSelected];
85220
85089
  selected.forEach((opt) => {
85221
85090
  if (opt.hasAttribute('event')) {
@@ -85428,7 +85297,7 @@ class AuroMenu extends AuroElement$2 {
85428
85297
  const currentSelected = this.optionSelected || [];
85429
85298
 
85430
85299
  if (!currentValue.includes(option.value)) {
85431
- this.value = JSON.stringify([
85300
+ this.value = serializeMultiSelectValue([
85432
85301
  ...currentValue,
85433
85302
  option.value
85434
85303
  ]);
@@ -85454,15 +85323,9 @@ class AuroMenu extends AuroElement$2 {
85454
85323
  */
85455
85324
  handleDeselectState(option) {
85456
85325
  if (this.multiSelect) {
85457
- // Remove this option from array
85326
+ // Remove this option from array; an empty result collapses `value` to undefined.
85458
85327
  const newFormattedValue = (this.formattedValue || []).filter((val) => val !== option.value);
85459
-
85460
- // If array is empty after removal, set back to undefined
85461
- if (newFormattedValue && newFormattedValue.length === 0) {
85462
- this.value = undefined;
85463
- } else {
85464
- this.value = JSON.stringify(newFormattedValue);
85465
- }
85328
+ this.value = serializeMultiSelectValue(newFormattedValue);
85466
85329
 
85467
85330
  this.optionSelected = this.optionSelected.filter((val) => val !== option);
85468
85331
  if (this.optionSelected.length === 0) {
@@ -85509,6 +85372,11 @@ class AuroMenu extends AuroElement$2 {
85509
85372
  this.optionSelected = undefined;
85510
85373
  this._index = -1;
85511
85374
 
85375
+ // Clear active option state so a follow-up open/navigation starts fresh
85376
+ // rather than reusing a stale reference from before the reset.
85377
+ this.items?.forEach((item) => item.classList.remove('active'));
85378
+ this.optionActive = undefined;
85379
+
85512
85380
  // Reset UI state
85513
85381
  this.updateItemsState(new Map([
85514
85382
  [
@@ -85958,6 +85826,7 @@ let menuOptionIdCounter = 0;
85958
85826
  * The `auro-menuoption` element provides users a way to define a menu option.
85959
85827
  * @customElement auro-menuoption
85960
85828
  *
85829
+ * @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.
85961
85830
  * @slot default - The default slot for the menu option text.
85962
85831
  *
85963
85832
  * @event auroMenuOption-mouseover - Notifies that this option has been hovered over.
@@ -85987,6 +85856,7 @@ class AuroMenuOption extends AuroElement$2 {
85987
85856
  this.noCheckmark = false;
85988
85857
  this.disabled = false;
85989
85858
  this.noMatch = false;
85859
+ this.persistent = false;
85990
85860
 
85991
85861
  /**
85992
85862
  * @private
@@ -86008,6 +85878,12 @@ class AuroMenuOption extends AuroElement$2 {
86008
85878
  type: Boolean,
86009
85879
  reflect: true
86010
85880
  },
85881
+
85882
+ /**
85883
+ * **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.
85884
+ *
85885
+ * @deprecated Use the `value` attribute on `auro-menu` instead.
85886
+ */
86011
85887
  selected: {
86012
85888
  type: Boolean,
86013
85889
  reflect: true
@@ -86042,6 +85918,12 @@ class AuroMenuOption extends AuroElement$2 {
86042
85918
  reflect: true,
86043
85919
  attribute: 'nomatch'
86044
85920
  },
85921
+
85922
+ /** 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. */
85923
+ persistent: {
85924
+ type: Boolean,
85925
+ reflect: true
85926
+ },
86045
85927
  };
86046
85928
  }
86047
85929
 
@@ -87092,7 +86974,7 @@ const selectKeyboardStrategy = {
87092
86974
  ArrowDown(component, evt, ctx) {
87093
86975
  evt.preventDefault();
87094
86976
  if (ctx.isExpanded) {
87095
- if (evt.altKey || evt.ctrlKey || evt.metaKey) {
86977
+ if (evt.altKey || evt.ctrlKey) {
87096
86978
  // navigate to last enabled option
87097
86979
  selectKeyboardStrategy.End(component, evt, ctx);
87098
86980
  } else {
@@ -87106,7 +86988,7 @@ const selectKeyboardStrategy = {
87106
86988
  ArrowUp(component, evt, ctx) {
87107
86989
  evt.preventDefault();
87108
86990
  if (ctx.isExpanded) {
87109
- if (evt.altKey || evt.ctrlKey || evt.metaKey) {
86991
+ if (evt.altKey || evt.ctrlKey) {
87110
86992
  // navigate to first enabled option
87111
86993
  selectKeyboardStrategy.Home(component, evt, ctx);
87112
86994
  } else {
@@ -89521,12 +89403,40 @@ class AuroFloatingUI {
89521
89403
  return;
89522
89404
  }
89523
89405
 
89406
+ // Chrome-specific: during popover top-layer promotion after a click on a
89407
+ // slotted focusable, :focus-within can briefly evaluate false while the
89408
+ // active element is still structurally inside the trigger/bib. Fall back
89409
+ // to a shadow-piercing ancestry walk from the deep active element before
89410
+ // treating this as a real focus loss.
89411
+ try {
89412
+ let active = document.activeElement;
89413
+ while (active && active.shadowRoot && active.shadowRoot.activeElement) {
89414
+ active = active.shadowRoot.activeElement;
89415
+ }
89416
+ const targets = [element, element.trigger, element.bib].filter(Boolean);
89417
+ let node = active;
89418
+ while (node) {
89419
+ if (targets.includes(node)) {
89420
+ return;
89421
+ }
89422
+ node =
89423
+ node.parentElement ||
89424
+ (node.getRootNode && node.getRootNode().host) ||
89425
+ null;
89426
+ }
89427
+ } catch (e) {
89428
+ // Defensive: fall through to the existing close path if traversal fails.
89429
+ }
89430
+
89524
89431
  // if fullscreen bib is in fullscreen mode, do not close
89525
89432
  if (element.bib.hasAttribute("isfullscreen")) {
89526
89433
  return;
89527
89434
  }
89528
89435
 
89529
- this.hideBib("keydown");
89436
+ // eventType "focusloss" distinguishes a Tab/click-driven close from an
89437
+ // Escape keydown close. Consumers use this to decide whether to restore
89438
+ // focus to the trigger (Escape) or let it advance naturally (Tab).
89439
+ this.hideBib("focusloss");
89530
89440
  }
89531
89441
 
89532
89442
  setupHideHandlers() {
@@ -90196,199 +90106,6 @@ function getFocusableElements(container) {
90196
90106
  return tabIndexedUniqueElements;
90197
90107
  }
90198
90108
 
90199
- /**
90200
- * FocusTrap manages keyboard focus within a specified container element, ensuring that focus does not leave the container when tabbing.
90201
- * It is commonly used for modal dialogs or overlays to improve accessibility by trapping focus within interactive UI components.
90202
- */
90203
- class FocusTrap {
90204
- /**
90205
- * Creates a new FocusTrap instance for the given container element.
90206
- * Initializes event listeners and prepares the container for focus management.
90207
- *
90208
- * @param {HTMLElement} container The DOM element to trap focus within.
90209
- * @param {boolean} [controlTabOrder=false] If true enables manual control of the tab order by the FocusTrap.
90210
- * @throws {Error} If the provided container is not a valid HTMLElement.
90211
- */
90212
- constructor(container, controlTabOrder = false) {
90213
- if (!container || !(container instanceof HTMLElement)) {
90214
- throw new Error("FocusTrap requires a valid HTMLElement.");
90215
- }
90216
-
90217
- this.container = container;
90218
- this.tabDirection = "forward"; // or 'backward';
90219
- this.controlTabOrder = controlTabOrder;
90220
-
90221
- this._init();
90222
- }
90223
-
90224
- /**
90225
- * Initializes the focus trap by setting up event listeners and attributes on the container.
90226
- * Prepares the container for focus management, including support for shadow DOM and inert attributes.
90227
- *
90228
- * @private
90229
- */
90230
- _init() {
90231
- // Add inert attribute to prevent focusing programmatically as well (if supported)
90232
- if ("inert" in HTMLElement.prototype) {
90233
- this.container.inert = false; // Ensure the container isn't inert
90234
- this.container.setAttribute("data-focus-trap-container", true); // Mark for identification
90235
- }
90236
-
90237
- // Track tab direction
90238
- this.container.addEventListener("keydown", this._onKeydown);
90239
- }
90240
-
90241
- /**
90242
- * Gets an array of currently active (focused) elements in the document and shadow DOM.
90243
- * @returns {Array<HTMLElement>} An array of focusable elements within the container.
90244
- * @private
90245
- */
90246
- _getActiveElements() {
90247
- // Get the active element(s) in the document and shadow root
90248
- // This will include the active element in the shadow DOM if it exists
90249
- // Active element may be inside the shadow DOM depending on delegatesFocus, so we need to check both
90250
- let { activeElement } = document;
90251
- const actives = [activeElement];
90252
- while (activeElement?.shadowRoot?.activeElement) {
90253
- actives.push(activeElement.shadowRoot.activeElement);
90254
- activeElement = activeElement.shadowRoot.activeElement;
90255
- }
90256
- return actives;
90257
- }
90258
-
90259
- /**
90260
- * Gets the next focus index based on the current index and focusable elements.
90261
- * @param {number} currentIndex The current index of the focused element.
90262
- * @param {Array<HTMLElement>} focusables The array of focusable elements.
90263
- * @returns {number|null} The next focus index or null if not determined.
90264
- */
90265
- _getNextFocusIndex(currentIndex, focusables, actives) {
90266
- if (this.controlTabOrder) {
90267
- // Calculate the new index based on the current index and tab direction
90268
- let newFocusIndex =
90269
- currentIndex + (this.tabDirection === "forward" ? 1 : -1);
90270
-
90271
- // Wrap-around logic
90272
- if (newFocusIndex < 0) newFocusIndex = focusables.length - 1;
90273
- if (newFocusIndex >= focusables.length) newFocusIndex = 0;
90274
-
90275
- // Early return with the new index
90276
- return newFocusIndex;
90277
- }
90278
-
90279
- // Determine if we need to wrap
90280
- const atFirst =
90281
- actives.includes(focusables[0]) || actives.includes(this.container);
90282
- const atLast = actives.includes(focusables[focusables.length - 1]);
90283
-
90284
- // Only wrap if at the ends
90285
- if (this.tabDirection === "backward" && atFirst) {
90286
- return focusables.length - 1;
90287
- }
90288
-
90289
- if (this.tabDirection === "forward" && atLast) {
90290
- return 0;
90291
- }
90292
-
90293
- // No wrap, so don't change focus, return early
90294
- return null;
90295
- }
90296
-
90297
- /**
90298
- * Handles the Tab key press event to manage focus within the container.
90299
- * @param {KeyboardEvent} e The keyboard event triggered by the user.
90300
- * @returns {void}
90301
- */
90302
- _handleTabKey(e) {
90303
- // Update the focusable elements
90304
- const focusables = this._getFocusableElements();
90305
-
90306
- // If there are no focusable elements, exit
90307
- if (!focusables.length) return;
90308
-
90309
- // Set the tab direction based on the key pressed
90310
- this.tabDirection = e.shiftKey ? "backward" : "forward";
90311
-
90312
- // Get the active elements that are currently focused
90313
- const actives = this._getActiveElements();
90314
-
90315
- // If we're at either end of the focusable elements, wrap around to the other end
90316
- let focusIndex = focusables.findIndex((el) => actives.includes(el));
90317
-
90318
- // Fallback if we have no focused element
90319
- if (focusIndex === -1) focusIndex = 0;
90320
-
90321
- // Get the next focus index based on the current focus index, tab direction, and controlTabOrder setting
90322
- // Is null if no new focus index is determined
90323
- const newFocusIndex = this._getNextFocusIndex(
90324
- focusIndex,
90325
- focusables,
90326
- actives,
90327
- );
90328
-
90329
- // If we have a new focus index, set focus to that element
90330
- if (newFocusIndex !== null) {
90331
- e.preventDefault();
90332
- focusables[newFocusIndex].focus();
90333
- }
90334
- }
90335
-
90336
- /**
90337
- * Catches the keydown event
90338
- * @param {KeyboardEvent} e The keyboard event triggered by user interaction.
90339
- * @private
90340
- */
90341
- _onKeydown = (e) => {
90342
- // Handle tab
90343
- if (e.key === "Tab") this._handleTabKey(e);
90344
- };
90345
-
90346
- /**
90347
- * Retrieves all focusable elements within the container in DOM order, including those in shadow DOM and slots.
90348
- * Returns a unique, ordered array of elements that can receive focus.
90349
- *
90350
- * @returns {Array<HTMLElement>} An array of focusable elements within the container.
90351
- * @private
90352
- */
90353
- _getFocusableElements() {
90354
- // Use the imported utility function to get focusable elements
90355
- const elements = getFocusableElements(this.container);
90356
-
90357
- // Return the elements found
90358
- return elements;
90359
- }
90360
-
90361
- /**
90362
- * Moves focus to the first focusable element within the container.
90363
- * Useful for setting initial focus when activating the focus trap.
90364
- */
90365
- focusFirstElement() {
90366
- const focusables = this._getFocusableElements();
90367
- if (focusables.length) focusables[0].focus();
90368
- }
90369
-
90370
- /**
90371
- * Moves focus to the last focusable element within the container.
90372
- * Useful for setting focus when deactivating or cycling focus in reverse.
90373
- */
90374
- focusLastElement() {
90375
- const focusables = this._getFocusableElements();
90376
- if (focusables.length) focusables[focusables.length - 1].focus();
90377
- }
90378
-
90379
- /**
90380
- * Removes event listeners and attributes added by the focus trap.
90381
- * Call this method to clean up when the focus trap is no longer needed.
90382
- */
90383
- disconnect() {
90384
- if (this.container.hasAttribute("data-focus-trap-container")) {
90385
- this.container.removeAttribute("data-focus-trap-container");
90386
- }
90387
-
90388
- this.container.removeEventListener("keydown", this._onKeydown);
90389
- }
90390
- }
90391
-
90392
90109
  // Copyright (c) Alaska Air. All right reserved. Licensed under the Apache-2.0 license
90393
90110
  // See LICENSE in the project root for license information.
90394
90111
 
@@ -90886,7 +90603,7 @@ class AuroDropdownBib extends i$3 {
90886
90603
  classes[`shape-${this.shape}`] = true;
90887
90604
 
90888
90605
  return u$c`
90889
- <dialog class="${e$2(classes)}" part="bibContainer" role="${o$4(this.dialogRole)}" aria-labelledby="${o$4(this.dialogLabel ? 'dialogLabel' : undefined)}">
90606
+ <dialog tabindex="-1" class="${e$2(classes)}" part="bibContainer" role="${o$4(this.dialogRole)}" aria-labelledby="${o$4(this.dialogLabel ? 'dialogLabel' : undefined)}">
90890
90607
  ${this.dialogLabel ? u$c`<span id="dialogLabel" class="util_displayHiddenVisually">${this.dialogLabel}</span>` : ''}
90891
90608
  <slot></slot>
90892
90609
  <span id="srAnnouncement" class="util_displayHiddenVisually" aria-live="polite" role="status"></span>
@@ -91137,7 +90854,7 @@ let AuroHelpText$1 = class AuroHelpText extends i$3 {
91137
90854
  }
91138
90855
  };
91139
90856
 
91140
- var formkitVersion$1 = '202607072023';
90857
+ var formkitVersion$1 = '202607102214';
91141
90858
 
91142
90859
  class AuroElement extends i$3 {
91143
90860
  static get properties() {
@@ -91891,7 +91608,10 @@ class AuroDropdown extends AuroElement {
91891
91608
  }
91892
91609
 
91893
91610
 
91894
- if (!this.isPopoverVisible) {
91611
+ // On Tab-driven close (eventType "focusloss"), let focus advance naturally
91612
+ // — restoring to the trigger would trap the user on this dropdown, forcing
91613
+ // an extra Tab to move on. Escape and outside-click still restore.
91614
+ if (!this.isPopoverVisible && eventType !== "focusloss") {
91895
91615
  // wait til the bib gets fully closed and rendered
91896
91616
  setTimeout(() => {
91897
91617
  // Skip if the bib re-opened, or if focus moved intentionally outside the dropdown (not to body).
@@ -92121,15 +91841,16 @@ class AuroDropdown extends AuroElement {
92121
91841
  }
92122
91842
  });
92123
91843
  } else {
92124
- // Normal desktop: use FocusTrap on the bib element.
92125
- // Defer focusFirstElement to the next frame because the popover
92126
- // is positioned asynchronously by Floating UI — calling focus()
92127
- // synchronously here would target elements with zero dimensions
92128
- // and the focus call would be silently ignored.
92129
- this.focusTrap = new FocusTrap(this.bibContent);
91844
+ // Normal desktop (non-modal): move initial focus into the bib but
91845
+ // don't trap Tab. Tab should exit the bib and let the floater's
91846
+ // handleFocusLoss close it, matching native <select>/<details>
91847
+ // behavior. Deferred one frame because Floating UI positions the
91848
+ // popover asynchronously a synchronous focus() would target
91849
+ // zero-dimension elements and be silently ignored.
92130
91850
  requestAnimationFrame(() => {
92131
- if (this.focusTrap) {
92132
- this.focusTrap.focusFirstElement();
91851
+ const focusables = getFocusableElements(this.bibContent);
91852
+ if (focusables.length) {
91853
+ focusables[0].focus();
92133
91854
  }
92134
91855
  });
92135
91856
  }
@@ -93176,7 +92897,7 @@ class AuroHelpText extends i$3 {
93176
92897
  }
93177
92898
  }
93178
92899
 
93179
- var formkitVersion = '202607072023';
92900
+ var formkitVersion = '202607102214';
93180
92901
 
93181
92902
  var styleCss = i$6`.util_displayInline{display:inline}.util_displayInlineBlock{display:inline-block}.util_displayBlock{display:block}.util_displayFlex{display:flex}.util_displayHidden{display:none}.util_displayHiddenVisually{position:absolute;overflow:hidden;clip:rect(1px, 1px, 1px, 1px);width:1px;height:1px;padding:0;border:0}.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}`;
93182
92903
 
@@ -93618,7 +93339,7 @@ class AuroSelect extends AuroElement$1 {
93618
93339
  },
93619
93340
 
93620
93341
  /**
93621
- * Value selected for the component.
93342
+ * 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.
93622
93343
  */
93623
93344
  value: {
93624
93345
  type: String,
@@ -94438,6 +94159,10 @@ class AuroSelect extends AuroElement$1 {
94438
94159
  this._observeLabelChanges();
94439
94160
  }
94440
94161
 
94162
+ /**
94163
+ * 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.
94164
+ * @param {string} value - The value to match against the menu options.
94165
+ */
94441
94166
  setMenuValue(value) {
94442
94167
  if (!this.menu) return;
94443
94168
  this.menu.selectByValue(value);