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

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (45) 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 +46 -207
  7. package/components/combobox/demo/getting-started.min.js +46 -207
  8. package/components/combobox/demo/index.min.js +46 -207
  9. package/components/combobox/dist/index.js +46 -207
  10. package/components/combobox/dist/registered.js +46 -207
  11. package/components/counter/demo/customize.min.js +59 -222
  12. package/components/counter/demo/index.min.js +59 -222
  13. package/components/counter/dist/auro-counter.d.ts +0 -8
  14. package/components/counter/dist/index.js +59 -222
  15. package/components/counter/dist/registered.js +59 -222
  16. package/components/datepicker/demo/customize.min.js +46 -207
  17. package/components/datepicker/demo/index.min.js +46 -207
  18. package/components/datepicker/dist/index.js +46 -207
  19. package/components/datepicker/dist/registered.js +46 -207
  20. package/components/dropdown/demo/customize.min.js +44 -205
  21. package/components/dropdown/demo/getting-started.min.js +44 -205
  22. package/components/dropdown/demo/index.min.js +44 -205
  23. package/components/dropdown/dist/index.js +44 -205
  24. package/components/dropdown/dist/registered.js +44 -205
  25. package/components/form/demo/customize.min.js +199 -845
  26. package/components/form/demo/getting-started.min.js +199 -845
  27. package/components/form/demo/index.min.js +199 -845
  28. package/components/form/demo/registerDemoDeps.min.js +199 -845
  29. package/components/input/demo/customize.min.js +1 -1
  30. package/components/input/demo/getting-started.min.js +1 -1
  31. package/components/input/demo/index.min.js +1 -1
  32. package/components/input/dist/index.js +1 -1
  33. package/components/input/dist/registered.js +1 -1
  34. package/components/radio/demo/customize.min.js +1 -1
  35. package/components/radio/demo/getting-started.min.js +1 -1
  36. package/components/radio/demo/index.min.js +1 -1
  37. package/components/radio/dist/index.js +1 -1
  38. package/components/radio/dist/registered.js +1 -1
  39. package/components/select/demo/customize.min.js +45 -206
  40. package/components/select/demo/getting-started.min.js +45 -206
  41. package/components/select/demo/index.min.js +45 -206
  42. package/components/select/dist/index.js +45 -206
  43. package/components/select/dist/registered.js +45 -206
  44. package/custom-elements.json +1499 -1514
  45. package/package.json +2 -2
@@ -1275,7 +1275,7 @@ class AuroHelpText extends i$2 {
1275
1275
  }
1276
1276
  }
1277
1277
 
1278
- var formkitVersion = '202607092329';
1278
+ var formkitVersion = '202607102138';
1279
1279
 
1280
1280
  // Copyright (c) 2026 Alaska Airlines. All rights reserved. Licensed under the Apache-2.0 license
1281
1281
  // See LICENSE in the project root for license information.
@@ -1275,7 +1275,7 @@ class AuroHelpText extends i$2 {
1275
1275
  }
1276
1276
  }
1277
1277
 
1278
- var formkitVersion = '202607092329';
1278
+ var formkitVersion = '202607102138';
1279
1279
 
1280
1280
  // Copyright (c) 2026 Alaska Airlines. All rights reserved. Licensed under the Apache-2.0 license
1281
1281
  // See LICENSE in the project root for license information.
@@ -1275,7 +1275,7 @@ class AuroHelpText extends i$2 {
1275
1275
  }
1276
1276
  }
1277
1277
 
1278
- var formkitVersion = '202607092329';
1278
+ var formkitVersion = '202607102138';
1279
1279
 
1280
1280
  // Copyright (c) 2026 Alaska Airlines. All rights reserved. Licensed under the Apache-2.0 license
1281
1281
  // See LICENSE in the project root for license information.
@@ -1228,7 +1228,7 @@ class AuroHelpText extends LitElement {
1228
1228
  }
1229
1229
  }
1230
1230
 
1231
- var formkitVersion = '202607092329';
1231
+ var formkitVersion = '202607102138';
1232
1232
 
1233
1233
  // Copyright (c) 2026 Alaska Airlines. All rights reserved. Licensed under the Apache-2.0 license
1234
1234
  // See LICENSE in the project root for license information.
@@ -1228,7 +1228,7 @@ class AuroHelpText extends LitElement {
1228
1228
  }
1229
1229
  }
1230
1230
 
1231
- var formkitVersion = '202607092329';
1231
+ var formkitVersion = '202607102138';
1232
1232
 
1233
1233
  // Copyright (c) 2026 Alaska Airlines. All rights reserved. Licensed under the Apache-2.0 license
1234
1234
  // See LICENSE in the project root for license information.
@@ -3520,12 +3520,40 @@ class AuroFloatingUI {
3520
3520
  return;
3521
3521
  }
3522
3522
 
3523
+ // Chrome-specific: during popover top-layer promotion after a click on a
3524
+ // slotted focusable, :focus-within can briefly evaluate false while the
3525
+ // active element is still structurally inside the trigger/bib. Fall back
3526
+ // to a shadow-piercing ancestry walk from the deep active element before
3527
+ // treating this as a real focus loss.
3528
+ try {
3529
+ let active = document.activeElement;
3530
+ while (active && active.shadowRoot && active.shadowRoot.activeElement) {
3531
+ active = active.shadowRoot.activeElement;
3532
+ }
3533
+ const targets = [element, element.trigger, element.bib].filter(Boolean);
3534
+ let node = active;
3535
+ while (node) {
3536
+ if (targets.includes(node)) {
3537
+ return;
3538
+ }
3539
+ node =
3540
+ node.parentElement ||
3541
+ (node.getRootNode && node.getRootNode().host) ||
3542
+ null;
3543
+ }
3544
+ } catch (e) {
3545
+ // Defensive: fall through to the existing close path if traversal fails.
3546
+ }
3547
+
3523
3548
  // if fullscreen bib is in fullscreen mode, do not close
3524
3549
  if (element.bib.hasAttribute("isfullscreen")) {
3525
3550
  return;
3526
3551
  }
3527
3552
 
3528
- this.hideBib("keydown");
3553
+ // eventType "focusloss" distinguishes a Tab/click-driven close from an
3554
+ // Escape keydown close. Consumers use this to decide whether to restore
3555
+ // focus to the trigger (Escape) or let it advance naturally (Tab).
3556
+ this.hideBib("focusloss");
3529
3557
  }
3530
3558
 
3531
3559
  setupHideHandlers() {
@@ -4195,199 +4223,6 @@ function getFocusableElements(container) {
4195
4223
  return tabIndexedUniqueElements;
4196
4224
  }
4197
4225
 
4198
- /**
4199
- * FocusTrap manages keyboard focus within a specified container element, ensuring that focus does not leave the container when tabbing.
4200
- * It is commonly used for modal dialogs or overlays to improve accessibility by trapping focus within interactive UI components.
4201
- */
4202
- class FocusTrap {
4203
- /**
4204
- * Creates a new FocusTrap instance for the given container element.
4205
- * Initializes event listeners and prepares the container for focus management.
4206
- *
4207
- * @param {HTMLElement} container The DOM element to trap focus within.
4208
- * @param {boolean} [controlTabOrder=false] If true enables manual control of the tab order by the FocusTrap.
4209
- * @throws {Error} If the provided container is not a valid HTMLElement.
4210
- */
4211
- constructor(container, controlTabOrder = false) {
4212
- if (!container || !(container instanceof HTMLElement)) {
4213
- throw new Error("FocusTrap requires a valid HTMLElement.");
4214
- }
4215
-
4216
- this.container = container;
4217
- this.tabDirection = "forward"; // or 'backward';
4218
- this.controlTabOrder = controlTabOrder;
4219
-
4220
- this._init();
4221
- }
4222
-
4223
- /**
4224
- * Initializes the focus trap by setting up event listeners and attributes on the container.
4225
- * Prepares the container for focus management, including support for shadow DOM and inert attributes.
4226
- *
4227
- * @private
4228
- */
4229
- _init() {
4230
- // Add inert attribute to prevent focusing programmatically as well (if supported)
4231
- if ("inert" in HTMLElement.prototype) {
4232
- this.container.inert = false; // Ensure the container isn't inert
4233
- this.container.setAttribute("data-focus-trap-container", true); // Mark for identification
4234
- }
4235
-
4236
- // Track tab direction
4237
- this.container.addEventListener("keydown", this._onKeydown);
4238
- }
4239
-
4240
- /**
4241
- * Gets an array of currently active (focused) elements in the document and shadow DOM.
4242
- * @returns {Array<HTMLElement>} An array of focusable elements within the container.
4243
- * @private
4244
- */
4245
- _getActiveElements() {
4246
- // Get the active element(s) in the document and shadow root
4247
- // This will include the active element in the shadow DOM if it exists
4248
- // Active element may be inside the shadow DOM depending on delegatesFocus, so we need to check both
4249
- let { activeElement } = document;
4250
- const actives = [activeElement];
4251
- while (activeElement?.shadowRoot?.activeElement) {
4252
- actives.push(activeElement.shadowRoot.activeElement);
4253
- activeElement = activeElement.shadowRoot.activeElement;
4254
- }
4255
- return actives;
4256
- }
4257
-
4258
- /**
4259
- * Gets the next focus index based on the current index and focusable elements.
4260
- * @param {number} currentIndex The current index of the focused element.
4261
- * @param {Array<HTMLElement>} focusables The array of focusable elements.
4262
- * @returns {number|null} The next focus index or null if not determined.
4263
- */
4264
- _getNextFocusIndex(currentIndex, focusables, actives) {
4265
- if (this.controlTabOrder) {
4266
- // Calculate the new index based on the current index and tab direction
4267
- let newFocusIndex =
4268
- currentIndex + (this.tabDirection === "forward" ? 1 : -1);
4269
-
4270
- // Wrap-around logic
4271
- if (newFocusIndex < 0) newFocusIndex = focusables.length - 1;
4272
- if (newFocusIndex >= focusables.length) newFocusIndex = 0;
4273
-
4274
- // Early return with the new index
4275
- return newFocusIndex;
4276
- }
4277
-
4278
- // Determine if we need to wrap
4279
- const atFirst =
4280
- actives.includes(focusables[0]) || actives.includes(this.container);
4281
- const atLast = actives.includes(focusables[focusables.length - 1]);
4282
-
4283
- // Only wrap if at the ends
4284
- if (this.tabDirection === "backward" && atFirst) {
4285
- return focusables.length - 1;
4286
- }
4287
-
4288
- if (this.tabDirection === "forward" && atLast) {
4289
- return 0;
4290
- }
4291
-
4292
- // No wrap, so don't change focus, return early
4293
- return null;
4294
- }
4295
-
4296
- /**
4297
- * Handles the Tab key press event to manage focus within the container.
4298
- * @param {KeyboardEvent} e The keyboard event triggered by the user.
4299
- * @returns {void}
4300
- */
4301
- _handleTabKey(e) {
4302
- // Update the focusable elements
4303
- const focusables = this._getFocusableElements();
4304
-
4305
- // If there are no focusable elements, exit
4306
- if (!focusables.length) return;
4307
-
4308
- // Set the tab direction based on the key pressed
4309
- this.tabDirection = e.shiftKey ? "backward" : "forward";
4310
-
4311
- // Get the active elements that are currently focused
4312
- const actives = this._getActiveElements();
4313
-
4314
- // If we're at either end of the focusable elements, wrap around to the other end
4315
- let focusIndex = focusables.findIndex((el) => actives.includes(el));
4316
-
4317
- // Fallback if we have no focused element
4318
- if (focusIndex === -1) focusIndex = 0;
4319
-
4320
- // Get the next focus index based on the current focus index, tab direction, and controlTabOrder setting
4321
- // Is null if no new focus index is determined
4322
- const newFocusIndex = this._getNextFocusIndex(
4323
- focusIndex,
4324
- focusables,
4325
- actives,
4326
- );
4327
-
4328
- // If we have a new focus index, set focus to that element
4329
- if (newFocusIndex !== null) {
4330
- e.preventDefault();
4331
- focusables[newFocusIndex].focus();
4332
- }
4333
- }
4334
-
4335
- /**
4336
- * Catches the keydown event
4337
- * @param {KeyboardEvent} e The keyboard event triggered by user interaction.
4338
- * @private
4339
- */
4340
- _onKeydown = (e) => {
4341
- // Handle tab
4342
- if (e.key === "Tab") this._handleTabKey(e);
4343
- };
4344
-
4345
- /**
4346
- * Retrieves all focusable elements within the container in DOM order, including those in shadow DOM and slots.
4347
- * Returns a unique, ordered array of elements that can receive focus.
4348
- *
4349
- * @returns {Array<HTMLElement>} An array of focusable elements within the container.
4350
- * @private
4351
- */
4352
- _getFocusableElements() {
4353
- // Use the imported utility function to get focusable elements
4354
- const elements = getFocusableElements(this.container);
4355
-
4356
- // Return the elements found
4357
- return elements;
4358
- }
4359
-
4360
- /**
4361
- * Moves focus to the first focusable element within the container.
4362
- * Useful for setting initial focus when activating the focus trap.
4363
- */
4364
- focusFirstElement() {
4365
- const focusables = this._getFocusableElements();
4366
- if (focusables.length) focusables[0].focus();
4367
- }
4368
-
4369
- /**
4370
- * Moves focus to the last focusable element within the container.
4371
- * Useful for setting focus when deactivating or cycling focus in reverse.
4372
- */
4373
- focusLastElement() {
4374
- const focusables = this._getFocusableElements();
4375
- if (focusables.length) focusables[focusables.length - 1].focus();
4376
- }
4377
-
4378
- /**
4379
- * Removes event listeners and attributes added by the focus trap.
4380
- * Call this method to clean up when the focus trap is no longer needed.
4381
- */
4382
- disconnect() {
4383
- if (this.container.hasAttribute("data-focus-trap-container")) {
4384
- this.container.removeAttribute("data-focus-trap-container");
4385
- }
4386
-
4387
- this.container.removeEventListener("keydown", this._onKeydown);
4388
- }
4389
- }
4390
-
4391
4226
  // Copyright (c) Alaska Air. All right reserved. Licensed under the Apache-2.0 license
4392
4227
  // See LICENSE in the project root for license information.
4393
4228
 
@@ -4885,7 +4720,7 @@ class AuroDropdownBib extends i$3 {
4885
4720
  classes[`shape-${this.shape}`] = true;
4886
4721
 
4887
4722
  return u$7`
4888
- <dialog class="${e$2(classes)}" part="bibContainer" role="${o(this.dialogRole)}" aria-labelledby="${o(this.dialogLabel ? 'dialogLabel' : undefined)}">
4723
+ <dialog tabindex="-1" class="${e$2(classes)}" part="bibContainer" role="${o(this.dialogRole)}" aria-labelledby="${o(this.dialogLabel ? 'dialogLabel' : undefined)}">
4889
4724
  ${this.dialogLabel ? u$7`<span id="dialogLabel" class="util_displayHiddenVisually">${this.dialogLabel}</span>` : ''}
4890
4725
  <slot></slot>
4891
4726
  <span id="srAnnouncement" class="util_displayHiddenVisually" aria-live="polite" role="status"></span>
@@ -5136,7 +4971,7 @@ let AuroHelpText$2 = class AuroHelpText extends i$3 {
5136
4971
  }
5137
4972
  };
5138
4973
 
5139
- var formkitVersion$2 = '202607092329';
4974
+ var formkitVersion$2 = '202607102138';
5140
4975
 
5141
4976
  let AuroElement$2 = class AuroElement extends i$3 {
5142
4977
  static get properties() {
@@ -5890,7 +5725,10 @@ class AuroDropdown extends AuroElement$2 {
5890
5725
  }
5891
5726
 
5892
5727
 
5893
- if (!this.isPopoverVisible) {
5728
+ // On Tab-driven close (eventType "focusloss"), let focus advance naturally
5729
+ // — restoring to the trigger would trap the user on this dropdown, forcing
5730
+ // an extra Tab to move on. Escape and outside-click still restore.
5731
+ if (!this.isPopoverVisible && eventType !== "focusloss") {
5894
5732
  // wait til the bib gets fully closed and rendered
5895
5733
  setTimeout(() => {
5896
5734
  // Skip if the bib re-opened, or if focus moved intentionally outside the dropdown (not to body).
@@ -6120,15 +5958,16 @@ class AuroDropdown extends AuroElement$2 {
6120
5958
  }
6121
5959
  });
6122
5960
  } else {
6123
- // Normal desktop: use FocusTrap on the bib element.
6124
- // Defer focusFirstElement to the next frame because the popover
6125
- // is positioned asynchronously by Floating UI — calling focus()
6126
- // synchronously here would target elements with zero dimensions
6127
- // and the focus call would be silently ignored.
6128
- this.focusTrap = new FocusTrap(this.bibContent);
5961
+ // Normal desktop (non-modal): move initial focus into the bib but
5962
+ // don't trap Tab. Tab should exit the bib and let the floater's
5963
+ // handleFocusLoss close it, matching native <select>/<details>
5964
+ // behavior. Deferred one frame because Floating UI positions the
5965
+ // popover asynchronously a synchronous focus() would target
5966
+ // zero-dimension elements and be silently ignored.
6129
5967
  requestAnimationFrame(() => {
6130
- if (this.focusTrap) {
6131
- this.focusTrap.focusFirstElement();
5968
+ const focusables = getFocusableElements(this.bibContent);
5969
+ if (focusables.length) {
5970
+ focusables[0].focus();
6132
5971
  }
6133
5972
  });
6134
5973
  }
@@ -18761,7 +18600,7 @@ let AuroHelpText$1 = class AuroHelpText extends i$3 {
18761
18600
  }
18762
18601
  };
18763
18602
 
18764
- var formkitVersion$1 = '202607092329';
18603
+ var formkitVersion$1 = '202607102138';
18765
18604
 
18766
18605
  // Copyright (c) 2025 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
18767
18606
  // See LICENSE in the project root for license information.
@@ -19882,7 +19721,7 @@ class AuroBibtemplate extends i$3 {
19882
19721
  }
19883
19722
  }
19884
19723
 
19885
- var formkitVersion = '202607092329';
19724
+ var formkitVersion = '202607102138';
19886
19725
 
19887
19726
  var styleCss$3 = i$6`.util_displayInline{display:inline}.util_displayInlineBlock{display:inline-block}.util_displayBlock{display:block}.util_displayFlex{display:flex}.util_displayHidden{display:none}.util_displayHiddenVisually{position:absolute;overflow:hidden;clip:rect(1px, 1px, 1px, 1px);width:1px;height:1px;padding:0;border:0}:host{display:block;text-align:left}:host [auro-dropdown]{--ds-auro-dropdown-trigger-background-color: transparent}:host #inputInBib::part(wrapper){box-shadow:none}:host #inputInBib::part(accent-left){display:none}:host([layout*=classic]) [auro-input]{width:100%}:host([layout*=classic]) [auro-input]::part(helpText){display:none}:host([layout*=classic]) #slotHolder{display:none}`;
19888
19727
 
@@ -3520,12 +3520,40 @@ class AuroFloatingUI {
3520
3520
  return;
3521
3521
  }
3522
3522
 
3523
+ // Chrome-specific: during popover top-layer promotion after a click on a
3524
+ // slotted focusable, :focus-within can briefly evaluate false while the
3525
+ // active element is still structurally inside the trigger/bib. Fall back
3526
+ // to a shadow-piercing ancestry walk from the deep active element before
3527
+ // treating this as a real focus loss.
3528
+ try {
3529
+ let active = document.activeElement;
3530
+ while (active && active.shadowRoot && active.shadowRoot.activeElement) {
3531
+ active = active.shadowRoot.activeElement;
3532
+ }
3533
+ const targets = [element, element.trigger, element.bib].filter(Boolean);
3534
+ let node = active;
3535
+ while (node) {
3536
+ if (targets.includes(node)) {
3537
+ return;
3538
+ }
3539
+ node =
3540
+ node.parentElement ||
3541
+ (node.getRootNode && node.getRootNode().host) ||
3542
+ null;
3543
+ }
3544
+ } catch (e) {
3545
+ // Defensive: fall through to the existing close path if traversal fails.
3546
+ }
3547
+
3523
3548
  // if fullscreen bib is in fullscreen mode, do not close
3524
3549
  if (element.bib.hasAttribute("isfullscreen")) {
3525
3550
  return;
3526
3551
  }
3527
3552
 
3528
- this.hideBib("keydown");
3553
+ // eventType "focusloss" distinguishes a Tab/click-driven close from an
3554
+ // Escape keydown close. Consumers use this to decide whether to restore
3555
+ // focus to the trigger (Escape) or let it advance naturally (Tab).
3556
+ this.hideBib("focusloss");
3529
3557
  }
3530
3558
 
3531
3559
  setupHideHandlers() {
@@ -4195,199 +4223,6 @@ function getFocusableElements(container) {
4195
4223
  return tabIndexedUniqueElements;
4196
4224
  }
4197
4225
 
4198
- /**
4199
- * FocusTrap manages keyboard focus within a specified container element, ensuring that focus does not leave the container when tabbing.
4200
- * It is commonly used for modal dialogs or overlays to improve accessibility by trapping focus within interactive UI components.
4201
- */
4202
- class FocusTrap {
4203
- /**
4204
- * Creates a new FocusTrap instance for the given container element.
4205
- * Initializes event listeners and prepares the container for focus management.
4206
- *
4207
- * @param {HTMLElement} container The DOM element to trap focus within.
4208
- * @param {boolean} [controlTabOrder=false] If true enables manual control of the tab order by the FocusTrap.
4209
- * @throws {Error} If the provided container is not a valid HTMLElement.
4210
- */
4211
- constructor(container, controlTabOrder = false) {
4212
- if (!container || !(container instanceof HTMLElement)) {
4213
- throw new Error("FocusTrap requires a valid HTMLElement.");
4214
- }
4215
-
4216
- this.container = container;
4217
- this.tabDirection = "forward"; // or 'backward';
4218
- this.controlTabOrder = controlTabOrder;
4219
-
4220
- this._init();
4221
- }
4222
-
4223
- /**
4224
- * Initializes the focus trap by setting up event listeners and attributes on the container.
4225
- * Prepares the container for focus management, including support for shadow DOM and inert attributes.
4226
- *
4227
- * @private
4228
- */
4229
- _init() {
4230
- // Add inert attribute to prevent focusing programmatically as well (if supported)
4231
- if ("inert" in HTMLElement.prototype) {
4232
- this.container.inert = false; // Ensure the container isn't inert
4233
- this.container.setAttribute("data-focus-trap-container", true); // Mark for identification
4234
- }
4235
-
4236
- // Track tab direction
4237
- this.container.addEventListener("keydown", this._onKeydown);
4238
- }
4239
-
4240
- /**
4241
- * Gets an array of currently active (focused) elements in the document and shadow DOM.
4242
- * @returns {Array<HTMLElement>} An array of focusable elements within the container.
4243
- * @private
4244
- */
4245
- _getActiveElements() {
4246
- // Get the active element(s) in the document and shadow root
4247
- // This will include the active element in the shadow DOM if it exists
4248
- // Active element may be inside the shadow DOM depending on delegatesFocus, so we need to check both
4249
- let { activeElement } = document;
4250
- const actives = [activeElement];
4251
- while (activeElement?.shadowRoot?.activeElement) {
4252
- actives.push(activeElement.shadowRoot.activeElement);
4253
- activeElement = activeElement.shadowRoot.activeElement;
4254
- }
4255
- return actives;
4256
- }
4257
-
4258
- /**
4259
- * Gets the next focus index based on the current index and focusable elements.
4260
- * @param {number} currentIndex The current index of the focused element.
4261
- * @param {Array<HTMLElement>} focusables The array of focusable elements.
4262
- * @returns {number|null} The next focus index or null if not determined.
4263
- */
4264
- _getNextFocusIndex(currentIndex, focusables, actives) {
4265
- if (this.controlTabOrder) {
4266
- // Calculate the new index based on the current index and tab direction
4267
- let newFocusIndex =
4268
- currentIndex + (this.tabDirection === "forward" ? 1 : -1);
4269
-
4270
- // Wrap-around logic
4271
- if (newFocusIndex < 0) newFocusIndex = focusables.length - 1;
4272
- if (newFocusIndex >= focusables.length) newFocusIndex = 0;
4273
-
4274
- // Early return with the new index
4275
- return newFocusIndex;
4276
- }
4277
-
4278
- // Determine if we need to wrap
4279
- const atFirst =
4280
- actives.includes(focusables[0]) || actives.includes(this.container);
4281
- const atLast = actives.includes(focusables[focusables.length - 1]);
4282
-
4283
- // Only wrap if at the ends
4284
- if (this.tabDirection === "backward" && atFirst) {
4285
- return focusables.length - 1;
4286
- }
4287
-
4288
- if (this.tabDirection === "forward" && atLast) {
4289
- return 0;
4290
- }
4291
-
4292
- // No wrap, so don't change focus, return early
4293
- return null;
4294
- }
4295
-
4296
- /**
4297
- * Handles the Tab key press event to manage focus within the container.
4298
- * @param {KeyboardEvent} e The keyboard event triggered by the user.
4299
- * @returns {void}
4300
- */
4301
- _handleTabKey(e) {
4302
- // Update the focusable elements
4303
- const focusables = this._getFocusableElements();
4304
-
4305
- // If there are no focusable elements, exit
4306
- if (!focusables.length) return;
4307
-
4308
- // Set the tab direction based on the key pressed
4309
- this.tabDirection = e.shiftKey ? "backward" : "forward";
4310
-
4311
- // Get the active elements that are currently focused
4312
- const actives = this._getActiveElements();
4313
-
4314
- // If we're at either end of the focusable elements, wrap around to the other end
4315
- let focusIndex = focusables.findIndex((el) => actives.includes(el));
4316
-
4317
- // Fallback if we have no focused element
4318
- if (focusIndex === -1) focusIndex = 0;
4319
-
4320
- // Get the next focus index based on the current focus index, tab direction, and controlTabOrder setting
4321
- // Is null if no new focus index is determined
4322
- const newFocusIndex = this._getNextFocusIndex(
4323
- focusIndex,
4324
- focusables,
4325
- actives,
4326
- );
4327
-
4328
- // If we have a new focus index, set focus to that element
4329
- if (newFocusIndex !== null) {
4330
- e.preventDefault();
4331
- focusables[newFocusIndex].focus();
4332
- }
4333
- }
4334
-
4335
- /**
4336
- * Catches the keydown event
4337
- * @param {KeyboardEvent} e The keyboard event triggered by user interaction.
4338
- * @private
4339
- */
4340
- _onKeydown = (e) => {
4341
- // Handle tab
4342
- if (e.key === "Tab") this._handleTabKey(e);
4343
- };
4344
-
4345
- /**
4346
- * Retrieves all focusable elements within the container in DOM order, including those in shadow DOM and slots.
4347
- * Returns a unique, ordered array of elements that can receive focus.
4348
- *
4349
- * @returns {Array<HTMLElement>} An array of focusable elements within the container.
4350
- * @private
4351
- */
4352
- _getFocusableElements() {
4353
- // Use the imported utility function to get focusable elements
4354
- const elements = getFocusableElements(this.container);
4355
-
4356
- // Return the elements found
4357
- return elements;
4358
- }
4359
-
4360
- /**
4361
- * Moves focus to the first focusable element within the container.
4362
- * Useful for setting initial focus when activating the focus trap.
4363
- */
4364
- focusFirstElement() {
4365
- const focusables = this._getFocusableElements();
4366
- if (focusables.length) focusables[0].focus();
4367
- }
4368
-
4369
- /**
4370
- * Moves focus to the last focusable element within the container.
4371
- * Useful for setting focus when deactivating or cycling focus in reverse.
4372
- */
4373
- focusLastElement() {
4374
- const focusables = this._getFocusableElements();
4375
- if (focusables.length) focusables[focusables.length - 1].focus();
4376
- }
4377
-
4378
- /**
4379
- * Removes event listeners and attributes added by the focus trap.
4380
- * Call this method to clean up when the focus trap is no longer needed.
4381
- */
4382
- disconnect() {
4383
- if (this.container.hasAttribute("data-focus-trap-container")) {
4384
- this.container.removeAttribute("data-focus-trap-container");
4385
- }
4386
-
4387
- this.container.removeEventListener("keydown", this._onKeydown);
4388
- }
4389
- }
4390
-
4391
4226
  // Copyright (c) Alaska Air. All right reserved. Licensed under the Apache-2.0 license
4392
4227
  // See LICENSE in the project root for license information.
4393
4228
 
@@ -4885,7 +4720,7 @@ class AuroDropdownBib extends i$3 {
4885
4720
  classes[`shape-${this.shape}`] = true;
4886
4721
 
4887
4722
  return u$7`
4888
- <dialog class="${e$2(classes)}" part="bibContainer" role="${o(this.dialogRole)}" aria-labelledby="${o(this.dialogLabel ? 'dialogLabel' : undefined)}">
4723
+ <dialog tabindex="-1" class="${e$2(classes)}" part="bibContainer" role="${o(this.dialogRole)}" aria-labelledby="${o(this.dialogLabel ? 'dialogLabel' : undefined)}">
4889
4724
  ${this.dialogLabel ? u$7`<span id="dialogLabel" class="util_displayHiddenVisually">${this.dialogLabel}</span>` : ''}
4890
4725
  <slot></slot>
4891
4726
  <span id="srAnnouncement" class="util_displayHiddenVisually" aria-live="polite" role="status"></span>
@@ -5136,7 +4971,7 @@ let AuroHelpText$2 = class AuroHelpText extends i$3 {
5136
4971
  }
5137
4972
  };
5138
4973
 
5139
- var formkitVersion$2 = '202607092329';
4974
+ var formkitVersion$2 = '202607102138';
5140
4975
 
5141
4976
  let AuroElement$2 = class AuroElement extends i$3 {
5142
4977
  static get properties() {
@@ -5890,7 +5725,10 @@ class AuroDropdown extends AuroElement$2 {
5890
5725
  }
5891
5726
 
5892
5727
 
5893
- if (!this.isPopoverVisible) {
5728
+ // On Tab-driven close (eventType "focusloss"), let focus advance naturally
5729
+ // — restoring to the trigger would trap the user on this dropdown, forcing
5730
+ // an extra Tab to move on. Escape and outside-click still restore.
5731
+ if (!this.isPopoverVisible && eventType !== "focusloss") {
5894
5732
  // wait til the bib gets fully closed and rendered
5895
5733
  setTimeout(() => {
5896
5734
  // Skip if the bib re-opened, or if focus moved intentionally outside the dropdown (not to body).
@@ -6120,15 +5958,16 @@ class AuroDropdown extends AuroElement$2 {
6120
5958
  }
6121
5959
  });
6122
5960
  } else {
6123
- // Normal desktop: use FocusTrap on the bib element.
6124
- // Defer focusFirstElement to the next frame because the popover
6125
- // is positioned asynchronously by Floating UI — calling focus()
6126
- // synchronously here would target elements with zero dimensions
6127
- // and the focus call would be silently ignored.
6128
- this.focusTrap = new FocusTrap(this.bibContent);
5961
+ // Normal desktop (non-modal): move initial focus into the bib but
5962
+ // don't trap Tab. Tab should exit the bib and let the floater's
5963
+ // handleFocusLoss close it, matching native <select>/<details>
5964
+ // behavior. Deferred one frame because Floating UI positions the
5965
+ // popover asynchronously a synchronous focus() would target
5966
+ // zero-dimension elements and be silently ignored.
6129
5967
  requestAnimationFrame(() => {
6130
- if (this.focusTrap) {
6131
- this.focusTrap.focusFirstElement();
5968
+ const focusables = getFocusableElements(this.bibContent);
5969
+ if (focusables.length) {
5970
+ focusables[0].focus();
6132
5971
  }
6133
5972
  });
6134
5973
  }
@@ -18761,7 +18600,7 @@ let AuroHelpText$1 = class AuroHelpText extends i$3 {
18761
18600
  }
18762
18601
  };
18763
18602
 
18764
- var formkitVersion$1 = '202607092329';
18603
+ var formkitVersion$1 = '202607102138';
18765
18604
 
18766
18605
  // Copyright (c) 2025 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
18767
18606
  // See LICENSE in the project root for license information.
@@ -19882,7 +19721,7 @@ class AuroBibtemplate extends i$3 {
19882
19721
  }
19883
19722
  }
19884
19723
 
19885
- var formkitVersion = '202607092329';
19724
+ var formkitVersion = '202607102138';
19886
19725
 
19887
19726
  var styleCss$3 = i$6`.util_displayInline{display:inline}.util_displayInlineBlock{display:inline-block}.util_displayBlock{display:block}.util_displayFlex{display:flex}.util_displayHidden{display:none}.util_displayHiddenVisually{position:absolute;overflow:hidden;clip:rect(1px, 1px, 1px, 1px);width:1px;height:1px;padding:0;border:0}:host{display:block;text-align:left}:host [auro-dropdown]{--ds-auro-dropdown-trigger-background-color: transparent}:host #inputInBib::part(wrapper){box-shadow:none}:host #inputInBib::part(accent-left){display:none}:host([layout*=classic]) [auro-input]{width:100%}:host([layout*=classic]) [auro-input]::part(helpText){display:none}:host([layout*=classic]) #slotHolder{display:none}`;
19888
19727