@aurodesignsystem-dev/auro-formkit 0.0.0-pr1551.0 → 0.0.0-pr1552.0

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 (43) hide show
  1. package/components/checkbox/demo/customize.min.js +1 -1
  2. package/components/checkbox/demo/getting-started.min.js +1 -1
  3. package/components/checkbox/demo/index.min.js +1 -1
  4. package/components/checkbox/dist/index.js +1 -1
  5. package/components/checkbox/dist/registered.js +1 -1
  6. package/components/combobox/demo/customize.min.js +207 -46
  7. package/components/combobox/demo/getting-started.min.js +207 -46
  8. package/components/combobox/demo/index.min.js +207 -46
  9. package/components/combobox/dist/index.js +207 -46
  10. package/components/combobox/dist/registered.js +207 -46
  11. package/components/counter/demo/customize.min.js +206 -45
  12. package/components/counter/demo/index.min.js +206 -45
  13. package/components/counter/dist/index.js +206 -45
  14. package/components/counter/dist/registered.js +206 -45
  15. package/components/datepicker/demo/customize.min.js +207 -46
  16. package/components/datepicker/demo/index.min.js +207 -46
  17. package/components/datepicker/dist/index.js +207 -46
  18. package/components/datepicker/dist/registered.js +207 -46
  19. package/components/dropdown/demo/customize.min.js +205 -44
  20. package/components/dropdown/demo/getting-started.min.js +205 -44
  21. package/components/dropdown/demo/index.min.js +205 -44
  22. package/components/dropdown/dist/index.js +205 -44
  23. package/components/dropdown/dist/registered.js +205 -44
  24. package/components/form/demo/customize.min.js +829 -185
  25. package/components/form/demo/getting-started.min.js +829 -185
  26. package/components/form/demo/index.min.js +829 -185
  27. package/components/form/demo/registerDemoDeps.min.js +829 -185
  28. package/components/input/demo/customize.min.js +1 -1
  29. package/components/input/demo/getting-started.min.js +1 -1
  30. package/components/input/demo/index.min.js +1 -1
  31. package/components/input/dist/index.js +1 -1
  32. package/components/input/dist/registered.js +1 -1
  33. package/components/radio/demo/customize.min.js +1 -1
  34. package/components/radio/demo/getting-started.min.js +1 -1
  35. package/components/radio/demo/index.min.js +1 -1
  36. package/components/radio/dist/index.js +1 -1
  37. package/components/radio/dist/registered.js +1 -1
  38. package/components/select/demo/customize.min.js +206 -45
  39. package/components/select/demo/getting-started.min.js +206 -45
  40. package/components/select/demo/index.min.js +206 -45
  41. package/components/select/dist/index.js +206 -45
  42. package/components/select/dist/registered.js +206 -45
  43. package/package.json +2 -2
@@ -13669,7 +13669,7 @@ class AuroBibtemplate extends LitElement {
13669
13669
  }
13670
13670
  }
13671
13671
 
13672
- var formkitVersion$2 = '202607100029';
13672
+ var formkitVersion$2 = '202607092329';
13673
13673
 
13674
13674
  let l$1 = 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=literal`${unsafeStatic(r)}`;return customElements.get(r)||customElements.define(r,class extends a{}),i}};let d$1 = 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 = 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=css`: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}
13675
13675
  `,u$4=css`.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}}
@@ -17946,40 +17946,12 @@ class AuroFloatingUI {
17946
17946
  return;
17947
17947
  }
17948
17948
 
17949
- // Chrome-specific: during popover top-layer promotion after a click on a
17950
- // slotted focusable, :focus-within can briefly evaluate false while the
17951
- // active element is still structurally inside the trigger/bib. Fall back
17952
- // to a shadow-piercing ancestry walk from the deep active element before
17953
- // treating this as a real focus loss.
17954
- try {
17955
- let active = document.activeElement;
17956
- while (active && active.shadowRoot && active.shadowRoot.activeElement) {
17957
- active = active.shadowRoot.activeElement;
17958
- }
17959
- const targets = [element, element.trigger, element.bib].filter(Boolean);
17960
- let node = active;
17961
- while (node) {
17962
- if (targets.includes(node)) {
17963
- return;
17964
- }
17965
- node =
17966
- node.parentElement ||
17967
- (node.getRootNode && node.getRootNode().host) ||
17968
- null;
17969
- }
17970
- } catch (e) {
17971
- // Defensive: fall through to the existing close path if traversal fails.
17972
- }
17973
-
17974
17949
  // if fullscreen bib is in fullscreen mode, do not close
17975
17950
  if (element.bib.hasAttribute("isfullscreen")) {
17976
17951
  return;
17977
17952
  }
17978
17953
 
17979
- // eventType "focusloss" distinguishes a Tab/click-driven close from an
17980
- // Escape keydown close. Consumers use this to decide whether to restore
17981
- // focus to the trigger (Escape) or let it advance naturally (Tab).
17982
- this.hideBib("focusloss");
17954
+ this.hideBib("keydown");
17983
17955
  }
17984
17956
 
17985
17957
  setupHideHandlers() {
@@ -18649,6 +18621,199 @@ function getFocusableElements(container) {
18649
18621
  return tabIndexedUniqueElements;
18650
18622
  }
18651
18623
 
18624
+ /**
18625
+ * FocusTrap manages keyboard focus within a specified container element, ensuring that focus does not leave the container when tabbing.
18626
+ * It is commonly used for modal dialogs or overlays to improve accessibility by trapping focus within interactive UI components.
18627
+ */
18628
+ class FocusTrap {
18629
+ /**
18630
+ * Creates a new FocusTrap instance for the given container element.
18631
+ * Initializes event listeners and prepares the container for focus management.
18632
+ *
18633
+ * @param {HTMLElement} container The DOM element to trap focus within.
18634
+ * @param {boolean} [controlTabOrder=false] If true enables manual control of the tab order by the FocusTrap.
18635
+ * @throws {Error} If the provided container is not a valid HTMLElement.
18636
+ */
18637
+ constructor(container, controlTabOrder = false) {
18638
+ if (!container || !(container instanceof HTMLElement)) {
18639
+ throw new Error("FocusTrap requires a valid HTMLElement.");
18640
+ }
18641
+
18642
+ this.container = container;
18643
+ this.tabDirection = "forward"; // or 'backward';
18644
+ this.controlTabOrder = controlTabOrder;
18645
+
18646
+ this._init();
18647
+ }
18648
+
18649
+ /**
18650
+ * Initializes the focus trap by setting up event listeners and attributes on the container.
18651
+ * Prepares the container for focus management, including support for shadow DOM and inert attributes.
18652
+ *
18653
+ * @private
18654
+ */
18655
+ _init() {
18656
+ // Add inert attribute to prevent focusing programmatically as well (if supported)
18657
+ if ("inert" in HTMLElement.prototype) {
18658
+ this.container.inert = false; // Ensure the container isn't inert
18659
+ this.container.setAttribute("data-focus-trap-container", true); // Mark for identification
18660
+ }
18661
+
18662
+ // Track tab direction
18663
+ this.container.addEventListener("keydown", this._onKeydown);
18664
+ }
18665
+
18666
+ /**
18667
+ * Gets an array of currently active (focused) elements in the document and shadow DOM.
18668
+ * @returns {Array<HTMLElement>} An array of focusable elements within the container.
18669
+ * @private
18670
+ */
18671
+ _getActiveElements() {
18672
+ // Get the active element(s) in the document and shadow root
18673
+ // This will include the active element in the shadow DOM if it exists
18674
+ // Active element may be inside the shadow DOM depending on delegatesFocus, so we need to check both
18675
+ let { activeElement } = document;
18676
+ const actives = [activeElement];
18677
+ while (activeElement?.shadowRoot?.activeElement) {
18678
+ actives.push(activeElement.shadowRoot.activeElement);
18679
+ activeElement = activeElement.shadowRoot.activeElement;
18680
+ }
18681
+ return actives;
18682
+ }
18683
+
18684
+ /**
18685
+ * Gets the next focus index based on the current index and focusable elements.
18686
+ * @param {number} currentIndex The current index of the focused element.
18687
+ * @param {Array<HTMLElement>} focusables The array of focusable elements.
18688
+ * @returns {number|null} The next focus index or null if not determined.
18689
+ */
18690
+ _getNextFocusIndex(currentIndex, focusables, actives) {
18691
+ if (this.controlTabOrder) {
18692
+ // Calculate the new index based on the current index and tab direction
18693
+ let newFocusIndex =
18694
+ currentIndex + (this.tabDirection === "forward" ? 1 : -1);
18695
+
18696
+ // Wrap-around logic
18697
+ if (newFocusIndex < 0) newFocusIndex = focusables.length - 1;
18698
+ if (newFocusIndex >= focusables.length) newFocusIndex = 0;
18699
+
18700
+ // Early return with the new index
18701
+ return newFocusIndex;
18702
+ }
18703
+
18704
+ // Determine if we need to wrap
18705
+ const atFirst =
18706
+ actives.includes(focusables[0]) || actives.includes(this.container);
18707
+ const atLast = actives.includes(focusables[focusables.length - 1]);
18708
+
18709
+ // Only wrap if at the ends
18710
+ if (this.tabDirection === "backward" && atFirst) {
18711
+ return focusables.length - 1;
18712
+ }
18713
+
18714
+ if (this.tabDirection === "forward" && atLast) {
18715
+ return 0;
18716
+ }
18717
+
18718
+ // No wrap, so don't change focus, return early
18719
+ return null;
18720
+ }
18721
+
18722
+ /**
18723
+ * Handles the Tab key press event to manage focus within the container.
18724
+ * @param {KeyboardEvent} e The keyboard event triggered by the user.
18725
+ * @returns {void}
18726
+ */
18727
+ _handleTabKey(e) {
18728
+ // Update the focusable elements
18729
+ const focusables = this._getFocusableElements();
18730
+
18731
+ // If there are no focusable elements, exit
18732
+ if (!focusables.length) return;
18733
+
18734
+ // Set the tab direction based on the key pressed
18735
+ this.tabDirection = e.shiftKey ? "backward" : "forward";
18736
+
18737
+ // Get the active elements that are currently focused
18738
+ const actives = this._getActiveElements();
18739
+
18740
+ // If we're at either end of the focusable elements, wrap around to the other end
18741
+ let focusIndex = focusables.findIndex((el) => actives.includes(el));
18742
+
18743
+ // Fallback if we have no focused element
18744
+ if (focusIndex === -1) focusIndex = 0;
18745
+
18746
+ // Get the next focus index based on the current focus index, tab direction, and controlTabOrder setting
18747
+ // Is null if no new focus index is determined
18748
+ const newFocusIndex = this._getNextFocusIndex(
18749
+ focusIndex,
18750
+ focusables,
18751
+ actives,
18752
+ );
18753
+
18754
+ // If we have a new focus index, set focus to that element
18755
+ if (newFocusIndex !== null) {
18756
+ e.preventDefault();
18757
+ focusables[newFocusIndex].focus();
18758
+ }
18759
+ }
18760
+
18761
+ /**
18762
+ * Catches the keydown event
18763
+ * @param {KeyboardEvent} e The keyboard event triggered by user interaction.
18764
+ * @private
18765
+ */
18766
+ _onKeydown = (e) => {
18767
+ // Handle tab
18768
+ if (e.key === "Tab") this._handleTabKey(e);
18769
+ };
18770
+
18771
+ /**
18772
+ * Retrieves all focusable elements within the container in DOM order, including those in shadow DOM and slots.
18773
+ * Returns a unique, ordered array of elements that can receive focus.
18774
+ *
18775
+ * @returns {Array<HTMLElement>} An array of focusable elements within the container.
18776
+ * @private
18777
+ */
18778
+ _getFocusableElements() {
18779
+ // Use the imported utility function to get focusable elements
18780
+ const elements = getFocusableElements(this.container);
18781
+
18782
+ // Return the elements found
18783
+ return elements;
18784
+ }
18785
+
18786
+ /**
18787
+ * Moves focus to the first focusable element within the container.
18788
+ * Useful for setting initial focus when activating the focus trap.
18789
+ */
18790
+ focusFirstElement() {
18791
+ const focusables = this._getFocusableElements();
18792
+ if (focusables.length) focusables[0].focus();
18793
+ }
18794
+
18795
+ /**
18796
+ * Moves focus to the last focusable element within the container.
18797
+ * Useful for setting focus when deactivating or cycling focus in reverse.
18798
+ */
18799
+ focusLastElement() {
18800
+ const focusables = this._getFocusableElements();
18801
+ if (focusables.length) focusables[focusables.length - 1].focus();
18802
+ }
18803
+
18804
+ /**
18805
+ * Removes event listeners and attributes added by the focus trap.
18806
+ * Call this method to clean up when the focus trap is no longer needed.
18807
+ */
18808
+ disconnect() {
18809
+ if (this.container.hasAttribute("data-focus-trap-container")) {
18810
+ this.container.removeAttribute("data-focus-trap-container");
18811
+ }
18812
+
18813
+ this.container.removeEventListener("keydown", this._onKeydown);
18814
+ }
18815
+ }
18816
+
18652
18817
  // Copyright (c) Alaska Air. All right reserved. Licensed under the Apache-2.0 license
18653
18818
  // See LICENSE in the project root for license information.
18654
18819
 
@@ -19146,7 +19311,7 @@ class AuroDropdownBib extends LitElement {
19146
19311
  classes[`shape-${this.shape}`] = true;
19147
19312
 
19148
19313
  return html$1`
19149
- <dialog tabindex="-1" class="${classMap(classes)}" part="bibContainer" role="${ifDefined(this.dialogRole)}" aria-labelledby="${ifDefined(this.dialogLabel ? 'dialogLabel' : undefined)}">
19314
+ <dialog class="${classMap(classes)}" part="bibContainer" role="${ifDefined(this.dialogRole)}" aria-labelledby="${ifDefined(this.dialogLabel ? 'dialogLabel' : undefined)}">
19150
19315
  ${this.dialogLabel ? html$1`<span id="dialogLabel" class="util_displayHiddenVisually">${this.dialogLabel}</span>` : ''}
19151
19316
  <slot></slot>
19152
19317
  <span id="srAnnouncement" class="util_displayHiddenVisually" aria-live="polite" role="status"></span>
@@ -19397,7 +19562,7 @@ let AuroHelpText$2 = class AuroHelpText extends LitElement {
19397
19562
  }
19398
19563
  };
19399
19564
 
19400
- var formkitVersion$1 = '202607100029';
19565
+ var formkitVersion$1 = '202607092329';
19401
19566
 
19402
19567
  let AuroElement$2 = class AuroElement extends LitElement {
19403
19568
  static get properties() {
@@ -20151,10 +20316,7 @@ class AuroDropdown extends AuroElement$2 {
20151
20316
  }
20152
20317
 
20153
20318
 
20154
- // On Tab-driven close (eventType "focusloss"), let focus advance naturally
20155
- // — restoring to the trigger would trap the user on this dropdown, forcing
20156
- // an extra Tab to move on. Escape and outside-click still restore.
20157
- if (!this.isPopoverVisible && eventType !== "focusloss") {
20319
+ if (!this.isPopoverVisible) {
20158
20320
  // wait til the bib gets fully closed and rendered
20159
20321
  setTimeout(() => {
20160
20322
  // Skip if the bib re-opened, or if focus moved intentionally outside the dropdown (not to body).
@@ -20384,16 +20546,15 @@ class AuroDropdown extends AuroElement$2 {
20384
20546
  }
20385
20547
  });
20386
20548
  } else {
20387
- // Normal desktop (non-modal): move initial focus into the bib but
20388
- // don't trap Tab. Tab should exit the bib and let the floater's
20389
- // handleFocusLoss close it, matching native <select>/<details>
20390
- // behavior. Deferred one frame because Floating UI positions the
20391
- // popover asynchronously a synchronous focus() would target
20392
- // zero-dimension elements and be silently ignored.
20549
+ // Normal desktop: use FocusTrap on the bib element.
20550
+ // Defer focusFirstElement to the next frame because the popover
20551
+ // is positioned asynchronously by Floating UI — calling focus()
20552
+ // synchronously here would target elements with zero dimensions
20553
+ // and the focus call would be silently ignored.
20554
+ this.focusTrap = new FocusTrap(this.bibContent);
20393
20555
  requestAnimationFrame(() => {
20394
- const focusables = getFocusableElements(this.bibContent);
20395
- if (focusables.length) {
20396
- focusables[0].focus();
20556
+ if (this.focusTrap) {
20557
+ this.focusTrap.focusFirstElement();
20397
20558
  }
20398
20559
  });
20399
20560
  }
@@ -33019,7 +33180,7 @@ let AuroHelpText$1 = class AuroHelpText extends LitElement {
33019
33180
  }
33020
33181
  };
33021
33182
 
33022
- var formkitVersion = '202607100029';
33183
+ var formkitVersion = '202607092329';
33023
33184
 
33024
33185
  // Copyright (c) 2025 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
33025
33186
  // See LICENSE in the project root for license information.
@@ -2295,40 +2295,12 @@ class AuroFloatingUI {
2295
2295
  return;
2296
2296
  }
2297
2297
 
2298
- // Chrome-specific: during popover top-layer promotion after a click on a
2299
- // slotted focusable, :focus-within can briefly evaluate false while the
2300
- // active element is still structurally inside the trigger/bib. Fall back
2301
- // to a shadow-piercing ancestry walk from the deep active element before
2302
- // treating this as a real focus loss.
2303
- try {
2304
- let active = document.activeElement;
2305
- while (active && active.shadowRoot && active.shadowRoot.activeElement) {
2306
- active = active.shadowRoot.activeElement;
2307
- }
2308
- const targets = [element, element.trigger, element.bib].filter(Boolean);
2309
- let node = active;
2310
- while (node) {
2311
- if (targets.includes(node)) {
2312
- return;
2313
- }
2314
- node =
2315
- node.parentElement ||
2316
- (node.getRootNode && node.getRootNode().host) ||
2317
- null;
2318
- }
2319
- } catch (e) {
2320
- // Defensive: fall through to the existing close path if traversal fails.
2321
- }
2322
-
2323
2298
  // if fullscreen bib is in fullscreen mode, do not close
2324
2299
  if (element.bib.hasAttribute("isfullscreen")) {
2325
2300
  return;
2326
2301
  }
2327
2302
 
2328
- // eventType "focusloss" distinguishes a Tab/click-driven close from an
2329
- // Escape keydown close. Consumers use this to decide whether to restore
2330
- // focus to the trigger (Escape) or let it advance naturally (Tab).
2331
- this.hideBib("focusloss");
2303
+ this.hideBib("keydown");
2332
2304
  }
2333
2305
 
2334
2306
  setupHideHandlers() {
@@ -2998,6 +2970,199 @@ function getFocusableElements(container) {
2998
2970
  return tabIndexedUniqueElements;
2999
2971
  }
3000
2972
 
2973
+ /**
2974
+ * FocusTrap manages keyboard focus within a specified container element, ensuring that focus does not leave the container when tabbing.
2975
+ * It is commonly used for modal dialogs or overlays to improve accessibility by trapping focus within interactive UI components.
2976
+ */
2977
+ class FocusTrap {
2978
+ /**
2979
+ * Creates a new FocusTrap instance for the given container element.
2980
+ * Initializes event listeners and prepares the container for focus management.
2981
+ *
2982
+ * @param {HTMLElement} container The DOM element to trap focus within.
2983
+ * @param {boolean} [controlTabOrder=false] If true enables manual control of the tab order by the FocusTrap.
2984
+ * @throws {Error} If the provided container is not a valid HTMLElement.
2985
+ */
2986
+ constructor(container, controlTabOrder = false) {
2987
+ if (!container || !(container instanceof HTMLElement)) {
2988
+ throw new Error("FocusTrap requires a valid HTMLElement.");
2989
+ }
2990
+
2991
+ this.container = container;
2992
+ this.tabDirection = "forward"; // or 'backward';
2993
+ this.controlTabOrder = controlTabOrder;
2994
+
2995
+ this._init();
2996
+ }
2997
+
2998
+ /**
2999
+ * Initializes the focus trap by setting up event listeners and attributes on the container.
3000
+ * Prepares the container for focus management, including support for shadow DOM and inert attributes.
3001
+ *
3002
+ * @private
3003
+ */
3004
+ _init() {
3005
+ // Add inert attribute to prevent focusing programmatically as well (if supported)
3006
+ if ("inert" in HTMLElement.prototype) {
3007
+ this.container.inert = false; // Ensure the container isn't inert
3008
+ this.container.setAttribute("data-focus-trap-container", true); // Mark for identification
3009
+ }
3010
+
3011
+ // Track tab direction
3012
+ this.container.addEventListener("keydown", this._onKeydown);
3013
+ }
3014
+
3015
+ /**
3016
+ * Gets an array of currently active (focused) elements in the document and shadow DOM.
3017
+ * @returns {Array<HTMLElement>} An array of focusable elements within the container.
3018
+ * @private
3019
+ */
3020
+ _getActiveElements() {
3021
+ // Get the active element(s) in the document and shadow root
3022
+ // This will include the active element in the shadow DOM if it exists
3023
+ // Active element may be inside the shadow DOM depending on delegatesFocus, so we need to check both
3024
+ let { activeElement } = document;
3025
+ const actives = [activeElement];
3026
+ while (activeElement?.shadowRoot?.activeElement) {
3027
+ actives.push(activeElement.shadowRoot.activeElement);
3028
+ activeElement = activeElement.shadowRoot.activeElement;
3029
+ }
3030
+ return actives;
3031
+ }
3032
+
3033
+ /**
3034
+ * Gets the next focus index based on the current index and focusable elements.
3035
+ * @param {number} currentIndex The current index of the focused element.
3036
+ * @param {Array<HTMLElement>} focusables The array of focusable elements.
3037
+ * @returns {number|null} The next focus index or null if not determined.
3038
+ */
3039
+ _getNextFocusIndex(currentIndex, focusables, actives) {
3040
+ if (this.controlTabOrder) {
3041
+ // Calculate the new index based on the current index and tab direction
3042
+ let newFocusIndex =
3043
+ currentIndex + (this.tabDirection === "forward" ? 1 : -1);
3044
+
3045
+ // Wrap-around logic
3046
+ if (newFocusIndex < 0) newFocusIndex = focusables.length - 1;
3047
+ if (newFocusIndex >= focusables.length) newFocusIndex = 0;
3048
+
3049
+ // Early return with the new index
3050
+ return newFocusIndex;
3051
+ }
3052
+
3053
+ // Determine if we need to wrap
3054
+ const atFirst =
3055
+ actives.includes(focusables[0]) || actives.includes(this.container);
3056
+ const atLast = actives.includes(focusables[focusables.length - 1]);
3057
+
3058
+ // Only wrap if at the ends
3059
+ if (this.tabDirection === "backward" && atFirst) {
3060
+ return focusables.length - 1;
3061
+ }
3062
+
3063
+ if (this.tabDirection === "forward" && atLast) {
3064
+ return 0;
3065
+ }
3066
+
3067
+ // No wrap, so don't change focus, return early
3068
+ return null;
3069
+ }
3070
+
3071
+ /**
3072
+ * Handles the Tab key press event to manage focus within the container.
3073
+ * @param {KeyboardEvent} e The keyboard event triggered by the user.
3074
+ * @returns {void}
3075
+ */
3076
+ _handleTabKey(e) {
3077
+ // Update the focusable elements
3078
+ const focusables = this._getFocusableElements();
3079
+
3080
+ // If there are no focusable elements, exit
3081
+ if (!focusables.length) return;
3082
+
3083
+ // Set the tab direction based on the key pressed
3084
+ this.tabDirection = e.shiftKey ? "backward" : "forward";
3085
+
3086
+ // Get the active elements that are currently focused
3087
+ const actives = this._getActiveElements();
3088
+
3089
+ // If we're at either end of the focusable elements, wrap around to the other end
3090
+ let focusIndex = focusables.findIndex((el) => actives.includes(el));
3091
+
3092
+ // Fallback if we have no focused element
3093
+ if (focusIndex === -1) focusIndex = 0;
3094
+
3095
+ // Get the next focus index based on the current focus index, tab direction, and controlTabOrder setting
3096
+ // Is null if no new focus index is determined
3097
+ const newFocusIndex = this._getNextFocusIndex(
3098
+ focusIndex,
3099
+ focusables,
3100
+ actives,
3101
+ );
3102
+
3103
+ // If we have a new focus index, set focus to that element
3104
+ if (newFocusIndex !== null) {
3105
+ e.preventDefault();
3106
+ focusables[newFocusIndex].focus();
3107
+ }
3108
+ }
3109
+
3110
+ /**
3111
+ * Catches the keydown event
3112
+ * @param {KeyboardEvent} e The keyboard event triggered by user interaction.
3113
+ * @private
3114
+ */
3115
+ _onKeydown = (e) => {
3116
+ // Handle tab
3117
+ if (e.key === "Tab") this._handleTabKey(e);
3118
+ };
3119
+
3120
+ /**
3121
+ * Retrieves all focusable elements within the container in DOM order, including those in shadow DOM and slots.
3122
+ * Returns a unique, ordered array of elements that can receive focus.
3123
+ *
3124
+ * @returns {Array<HTMLElement>} An array of focusable elements within the container.
3125
+ * @private
3126
+ */
3127
+ _getFocusableElements() {
3128
+ // Use the imported utility function to get focusable elements
3129
+ const elements = getFocusableElements(this.container);
3130
+
3131
+ // Return the elements found
3132
+ return elements;
3133
+ }
3134
+
3135
+ /**
3136
+ * Moves focus to the first focusable element within the container.
3137
+ * Useful for setting initial focus when activating the focus trap.
3138
+ */
3139
+ focusFirstElement() {
3140
+ const focusables = this._getFocusableElements();
3141
+ if (focusables.length) focusables[0].focus();
3142
+ }
3143
+
3144
+ /**
3145
+ * Moves focus to the last focusable element within the container.
3146
+ * Useful for setting focus when deactivating or cycling focus in reverse.
3147
+ */
3148
+ focusLastElement() {
3149
+ const focusables = this._getFocusableElements();
3150
+ if (focusables.length) focusables[focusables.length - 1].focus();
3151
+ }
3152
+
3153
+ /**
3154
+ * Removes event listeners and attributes added by the focus trap.
3155
+ * Call this method to clean up when the focus trap is no longer needed.
3156
+ */
3157
+ disconnect() {
3158
+ if (this.container.hasAttribute("data-focus-trap-container")) {
3159
+ this.container.removeAttribute("data-focus-trap-container");
3160
+ }
3161
+
3162
+ this.container.removeEventListener("keydown", this._onKeydown);
3163
+ }
3164
+ }
3165
+
3001
3166
  // Copyright (c) Alaska Air. All right reserved. Licensed under the Apache-2.0 license
3002
3167
  // See LICENSE in the project root for license information.
3003
3168
 
@@ -3526,7 +3691,7 @@ class AuroDropdownBib extends i {
3526
3691
  classes[`shape-${this.shape}`] = true;
3527
3692
 
3528
3693
  return u$2`
3529
- <dialog tabindex="-1" class="${e$4(classes)}" part="bibContainer" role="${o(this.dialogRole)}" aria-labelledby="${o(this.dialogLabel ? 'dialogLabel' : undefined)}">
3694
+ <dialog class="${e$4(classes)}" part="bibContainer" role="${o(this.dialogRole)}" aria-labelledby="${o(this.dialogLabel ? 'dialogLabel' : undefined)}">
3530
3695
  ${this.dialogLabel ? u$2`<span id="dialogLabel" class="util_displayHiddenVisually">${this.dialogLabel}</span>` : ''}
3531
3696
  <slot></slot>
3532
3697
  <span id="srAnnouncement" class="util_displayHiddenVisually" aria-live="polite" role="status"></span>
@@ -3777,7 +3942,7 @@ class AuroHelpText extends i {
3777
3942
  }
3778
3943
  }
3779
3944
 
3780
- var formkitVersion = '202607100029';
3945
+ var formkitVersion = '202607092329';
3781
3946
 
3782
3947
  class AuroElement extends i {
3783
3948
  static get properties() {
@@ -4531,10 +4696,7 @@ class AuroDropdown extends AuroElement {
4531
4696
  }
4532
4697
 
4533
4698
 
4534
- // On Tab-driven close (eventType "focusloss"), let focus advance naturally
4535
- // — restoring to the trigger would trap the user on this dropdown, forcing
4536
- // an extra Tab to move on. Escape and outside-click still restore.
4537
- if (!this.isPopoverVisible && eventType !== "focusloss") {
4699
+ if (!this.isPopoverVisible) {
4538
4700
  // wait til the bib gets fully closed and rendered
4539
4701
  setTimeout(() => {
4540
4702
  // Skip if the bib re-opened, or if focus moved intentionally outside the dropdown (not to body).
@@ -4764,16 +4926,15 @@ class AuroDropdown extends AuroElement {
4764
4926
  }
4765
4927
  });
4766
4928
  } else {
4767
- // Normal desktop (non-modal): move initial focus into the bib but
4768
- // don't trap Tab. Tab should exit the bib and let the floater's
4769
- // handleFocusLoss close it, matching native <select>/<details>
4770
- // behavior. Deferred one frame because Floating UI positions the
4771
- // popover asynchronously a synchronous focus() would target
4772
- // zero-dimension elements and be silently ignored.
4929
+ // Normal desktop: use FocusTrap on the bib element.
4930
+ // Defer focusFirstElement to the next frame because the popover
4931
+ // is positioned asynchronously by Floating UI — calling focus()
4932
+ // synchronously here would target elements with zero dimensions
4933
+ // and the focus call would be silently ignored.
4934
+ this.focusTrap = new FocusTrap(this.bibContent);
4773
4935
  requestAnimationFrame(() => {
4774
- const focusables = getFocusableElements(this.bibContent);
4775
- if (focusables.length) {
4776
- focusables[0].focus();
4936
+ if (this.focusTrap) {
4937
+ this.focusTrap.focusFirstElement();
4777
4938
  }
4778
4939
  });
4779
4940
  }