@aurodesignsystem-dev/auro-formkit 0.0.0-pr1474.4 → 0.0.0-pr1475.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 (83) hide show
  1. package/components/bibtemplate/dist/auro-bibtemplate.d.ts +7 -0
  2. package/components/bibtemplate/dist/index.js +9 -1
  3. package/components/bibtemplate/dist/registered.js +9 -1
  4. package/components/checkbox/demo/customize.html +2 -1
  5. package/components/checkbox/demo/customize.min.js +1 -1
  6. package/components/checkbox/demo/getting-started.min.js +1 -1
  7. package/components/checkbox/demo/index.min.js +1 -1
  8. package/components/checkbox/dist/index.js +1 -1
  9. package/components/checkbox/dist/registered.js +1 -1
  10. package/components/combobox/demo/customize.html +2 -1
  11. package/components/combobox/demo/customize.md +130 -106
  12. package/components/combobox/demo/customize.min.js +209 -16
  13. package/components/combobox/demo/getting-started.min.js +209 -16
  14. package/components/combobox/demo/index.min.js +209 -16
  15. package/components/combobox/dist/index.js +209 -16
  16. package/components/combobox/dist/registered.js +209 -16
  17. package/components/counter/demo/customize.min.js +208 -15
  18. package/components/counter/demo/index.min.js +208 -15
  19. package/components/counter/demo/keyboard-behavior.md +1 -0
  20. package/components/counter/dist/index.js +10 -2
  21. package/components/counter/dist/registered.js +10 -2
  22. package/components/datepicker/demo/accessibility.md +51 -3
  23. package/components/datepicker/demo/api.md +9 -0
  24. package/components/datepicker/demo/customize.html +2 -0
  25. package/components/datepicker/demo/customize.js +19 -0
  26. package/components/datepicker/demo/customize.md +72 -8
  27. package/components/datepicker/demo/customize.min.js +25690 -0
  28. package/components/datepicker/demo/design.md +3 -1
  29. package/components/datepicker/demo/index.js +2 -1
  30. package/components/datepicker/demo/index.md +81 -1
  31. package/components/datepicker/demo/index.min.js +1223 -101
  32. package/components/datepicker/demo/keyboard-behavior.md +201 -2
  33. package/components/datepicker/demo/voiceover.md +19 -12
  34. package/components/datepicker/dist/index.js +1155 -104
  35. package/components/datepicker/dist/registered.js +1155 -104
  36. package/components/datepicker/dist/src/auro-calendar-cell.d.ts +59 -0
  37. package/components/datepicker/dist/src/auro-calendar-month.d.ts +28 -0
  38. package/components/datepicker/dist/src/auro-calendar.d.ts +84 -0
  39. package/components/datepicker/dist/src/auro-datepicker.d.ts +80 -0
  40. package/components/datepicker/dist/src/datepickerKeyboardStrategy.d.ts +5 -3
  41. package/components/dropdown/demo/accessibility.md +11 -0
  42. package/components/dropdown/demo/api.md +1 -0
  43. package/components/dropdown/demo/customize.md +3 -0
  44. package/components/dropdown/demo/customize.min.js +198 -13
  45. package/components/dropdown/demo/getting-started.min.js +198 -13
  46. package/components/dropdown/demo/index.min.js +198 -13
  47. package/components/dropdown/demo/keyboard-behavior.md +1 -0
  48. package/components/dropdown/dist/auro-dropdown.d.ts +30 -1
  49. package/components/dropdown/dist/index.js +198 -13
  50. package/components/dropdown/dist/registered.js +198 -13
  51. package/components/form/demo/customize.html +6 -6
  52. package/components/form/demo/customize.js +0 -17
  53. package/components/form/demo/customize.md +51 -125
  54. package/components/form/demo/customize.min.js +1776 -327
  55. package/components/form/demo/getting-started.min.js +1776 -291
  56. package/components/form/demo/index.min.js +1776 -291
  57. package/components/form/demo/registerDemoDeps.min.js +1769 -139
  58. package/components/form/dist/auro-form.d.ts +5 -45
  59. package/components/form/dist/index.js +7 -152
  60. package/components/form/dist/registered.js +7 -152
  61. package/components/input/demo/customize.html +2 -1
  62. package/components/input/demo/customize.min.js +1 -1
  63. package/components/input/demo/getting-started.min.js +1 -1
  64. package/components/input/demo/index.min.js +1 -1
  65. package/components/input/dist/index.js +1 -1
  66. package/components/input/dist/registered.js +1 -1
  67. package/components/radio/demo/customize.min.js +2186 -0
  68. package/components/radio/demo/demo-support.min.js +55807 -0
  69. package/components/radio/demo/getting-started.js +1 -1
  70. package/components/radio/demo/getting-started.md +1 -1
  71. package/components/radio/demo/getting-started.min.js +2205 -0
  72. package/components/radio/demo/index.min.js +1 -1
  73. package/components/radio/dist/index.js +1 -1
  74. package/components/radio/dist/registered.js +1 -1
  75. package/components/select/demo/customize.html +2 -2
  76. package/components/select/demo/customize.min.js +208 -15
  77. package/components/select/demo/getting-started.min.js +208 -15
  78. package/components/select/demo/index.min.js +208 -15
  79. package/components/select/demo/keyboard-behavior.md +1 -0
  80. package/components/select/dist/index.js +208 -15
  81. package/components/select/dist/registered.js +208 -15
  82. package/custom-elements.json +2826 -2214
  83. package/package.json +2 -2
@@ -4662,7 +4662,7 @@ function applyKeyboardStrategy(component, strategy, options = {}) {
4662
4662
  });
4663
4663
  }
4664
4664
 
4665
- var styleCss$2$1 = i$7`:host{position:fixed;z-index:var(--depth-tooltip, 400);display:none;isolation:isolate}:host dialog{width:auto;max-width:none;height:auto;max-height:none;padding:0;border:none;margin:0;outline:none;transform:translateZ(0)}:host dialog::backdrop{background:transparent}:host(:not([isfullscreen])) dialog{position:relative;inset:unset}:host(:not([isfullscreen])) .container.shape-box{border-radius:unset}:host(:not([isfullscreen])) .container[class*=shape-pill],:host(:not([isfullscreen])) .container[class*=shape-snowflake]{border-radius:30px}:host(:not([isfullscreen])) .container[class*=shape-rounded]{border-radius:16px}:host(:not([matchWidth])) .container{min-width:fit-content}:host([isfullscreen]){position:fixed;top:0;left:0}:host([isfullscreen]) .container{width:100dvw;max-width:none;height:100dvh;max-height:none;border-radius:unset;margin-top:0;box-shadow:unset;overscroll-behavior:contain}:host([isfullscreen]) .container::backdrop{background:var(--ds-color-background-primary, #fff)}:host(:popover-open){position:fixed;overflow:visible;padding:0;border:none;margin:0;background:transparent;inset:unset;outline:none}:host([data-show]){display:flex}:host([common]:not([isfullscreen])) .container,:host([rounded]:not([isfullscreen])) .container{border-radius:var(--ds-border-radius, 0.375rem)}:host([common][isfullscreen]) .container,:host([rounded][isfullscreen]) .container{border-radius:unset;box-shadow:unset}.container{display:inline-block;overflow:auto;box-sizing:border-box;border-radius:var(--ds-border-radius, 0.375rem);margin:var(--ds-size-50, 0.25rem) 0}.util_displayHiddenVisually{position:absolute;overflow:hidden;width:1px;height:1px;padding:0;border:0;margin:-1px;clip-path:inset(50%);white-space:nowrap}`;
4665
+ var styleCss$2$1 = i$7`:host{position:fixed;z-index:var(--depth-tooltip, 400);display:none;isolation:isolate}:host dialog{width:auto;max-width:none;height:auto;max-height:none;padding:0;border:none;margin:0;outline:none;transform:translateZ(0)}:host dialog::backdrop{background:transparent}:host(:not([isfullscreen])) dialog{position:relative;inset:unset}:host(:not([isfullscreen])) .container.shape-box{border-radius:unset}:host(:not([isfullscreen])) .container[class*=shape-pill],:host(:not([isfullscreen])) .container[class*=shape-snowflake]{border-radius:30px}:host(:not([isfullscreen])) .container[class*=shape-rounded]{border-radius:16px}:host([desktopmodal]:popover-open)::backdrop{background:transparent}:host(:not([matchWidth])) .container{min-width:fit-content}:host([isfullscreen]){position:fixed;top:0;left:0}:host([isfullscreen]) .container{width:100dvw;max-width:none;height:100dvh;max-height:none;border-radius:unset;margin-top:0;box-shadow:unset;overscroll-behavior:contain}:host([isfullscreen]) .container::backdrop{background:var(--ds-color-background-primary, #fff)}:host(:popover-open){position:fixed;overflow:visible;padding:0;border:none;margin:0;background:transparent;inset:unset;outline:none}:host([data-show]){display:flex}:host([common]:not([isfullscreen])) .container,:host([rounded]:not([isfullscreen])) .container{border-radius:var(--ds-border-radius, 0.375rem)}:host([common][isfullscreen]) .container,:host([rounded][isfullscreen]) .container{border-radius:unset;box-shadow:unset}.container{display:inline-block;overflow:auto;box-sizing:border-box;border-radius:var(--ds-border-radius, 0.375rem);margin:var(--ds-size-50, 0.25rem) 0}.util_displayHiddenVisually{position:absolute;overflow:hidden;width:1px;height:1px;padding:0;border:0;margin:-1px;clip-path:inset(50%);white-space:nowrap}`;
4666
4666
 
4667
4667
  var colorCss$2$1 = i$7`.container{background-color:var(--ds-auro-dropdownbib-container-color);box-shadow:var(--ds-auro-dropdownbib-boxshadow-color);color:var(--ds-auro-dropdownbib-text-color)}`;
4668
4668
 
@@ -5293,7 +5293,7 @@ let AuroHelpText$2 = class AuroHelpText extends i$4 {
5293
5293
  }
5294
5294
  };
5295
5295
 
5296
- var formkitVersion$2 = '202605122157';
5296
+ var formkitVersion$2 = '202605182202';
5297
5297
 
5298
5298
  let AuroElement$2 = class AuroElement extends i$4 {
5299
5299
  static get properties() {
@@ -5473,6 +5473,7 @@ class AuroDropdown extends AuroElement$2 {
5473
5473
  _intializeDefaults() {
5474
5474
  this.appearance = 'default';
5475
5475
  this.chevron = false;
5476
+ this.desktopModal = false;
5476
5477
  this.disabled = false;
5477
5478
  this.disableKeyboardHandling = false;
5478
5479
  this.error = false;
@@ -5653,6 +5654,14 @@ class AuroDropdown extends AuroElement$2 {
5653
5654
  reflect: true
5654
5655
  },
5655
5656
 
5657
+ /**
5658
+ * If declared, the dropdown will behave as a modal dialog when in a desktop viewport size.
5659
+ */
5660
+ desktopModal: {
5661
+ type: Boolean,
5662
+ reflect: true
5663
+ },
5664
+
5656
5665
  /**
5657
5666
  * If declared, the dropdown will only show by calling the API .show() public method.
5658
5667
  */
@@ -5940,6 +5949,15 @@ class AuroDropdown extends AuroElement$2 {
5940
5949
 
5941
5950
  disconnectedCallback() {
5942
5951
  super.disconnectedCallback();
5952
+ this._clearPageInert();
5953
+ if (this._bibTabHandler) {
5954
+ this.removeEventListener('keydown', this._bibTabHandler);
5955
+ this._bibTabHandler = undefined;
5956
+ }
5957
+ if (this.focusTrap) {
5958
+ this.focusTrap.disconnect();
5959
+ this.focusTrap = undefined;
5960
+ }
5943
5961
  if (this.floater) {
5944
5962
  this.floater.hideBib('disconnect');
5945
5963
  this.floater.disconnect();
@@ -5967,19 +5985,34 @@ class AuroDropdown extends AuroElement$2 {
5967
5985
  if (this.isPopoverVisible) {
5968
5986
  // Fullscreen: use showModal() for native accessibility (inert outside, focus trap)
5969
5987
  // Desktop: use show() for Floating UI positioning + FocusTrap for focus management
5970
- const useModal = this.isBibFullscreen;
5971
- this.bibElement.value.open(useModal);
5988
+ this.bibElement.value.open(this.isBibFullscreen);
5989
+ this.updateFocusTrap();
5990
+
5991
+ // Desktop modal: make siblings inert so content outside is not interactive
5992
+ if (this.desktopModal && !this.isBibFullscreen) {
5993
+ this._setPageInert();
5994
+ }
5972
5995
  } else {
5973
5996
  this.bibElement.value.close();
5997
+ this._clearPageInert();
5974
5998
  }
5975
5999
  }
5976
6000
 
5977
6001
  // When fullscreen strategy changes while open, re-open dialog with correct mode
5978
6002
  // (e.g. resizing from desktop → mobile while dropdown is open)
5979
6003
  if (changedProperties.has('isBibFullscreen') && this.isPopoverVisible && this.bibElement.value) {
5980
- const useModal = this.isBibFullscreen;
5981
6004
  this.bibElement.value.close();
5982
- this.bibElement.value.open(useModal);
6005
+ this.bibElement.value.open(this.isBibFullscreen);
6006
+
6007
+ // Re-initialize focus management for the new strategy
6008
+ this.updateFocusTrap();
6009
+
6010
+ // Toggle inert: desktop modal needs it, fullscreen showModal() handles it natively
6011
+ if (this.desktopModal && !this.isBibFullscreen) {
6012
+ this._setPageInert();
6013
+ } else {
6014
+ this._clearPageInert();
6015
+ }
5983
6016
  }
5984
6017
  }
5985
6018
 
@@ -5989,8 +6022,14 @@ class AuroDropdown extends AuroElement$2 {
5989
6022
  * @param {CustomEvent} event - The custom event that contains the dropdown toggle information.
5990
6023
  */
5991
6024
  handleDropdownToggle(event) {
5992
- this.updateFocusTrap();
5993
6025
  this.isPopoverVisible = event.detail.expanded;
6026
+
6027
+ // Tear down FocusTrap when closing. Creation happens in updated()
6028
+ // after the dialog is open so getFocusableElements can find content.
6029
+ if (!this.isPopoverVisible) {
6030
+ this.updateFocusTrap();
6031
+ }
6032
+
5994
6033
  const eventType = event.detail.eventType || "unknown";
5995
6034
  if (!this.isPopoverVisible && this.hasFocus && eventType === "keydown") {
5996
6035
  this.trigger.focus();
@@ -6089,19 +6128,164 @@ class AuroDropdown extends AuroElement$2 {
6089
6128
  * @private
6090
6129
  */
6091
6130
  updateFocusTrap() {
6131
+ // Always clean up existing handlers/traps before setting up new ones
6132
+ // to prevent duplicate listeners on repeated calls.
6133
+ if (this._bibTabHandler) {
6134
+ this.removeEventListener('keydown', this._bibTabHandler);
6135
+ this._bibTabHandler = undefined;
6136
+ }
6137
+
6138
+ if (this.focusTrap) {
6139
+ this.focusTrap.disconnect();
6140
+ this.focusTrap = undefined;
6141
+ }
6142
+
6092
6143
  if (this.isPopoverVisible) {
6093
6144
  if (!this.isBibFullscreen) {
6094
- // Desktop: show() doesn't trap focus, so use FocusTrap
6095
- this.focusTrap = new FocusTrap(this.bibContent);
6096
- this.focusTrap.focusFirstElement();
6145
+ if (this.desktopModal) {
6146
+ // Desktop modal: trap focus only within the bib content.
6147
+ // Can't use FocusTrap on the bib element because keydown events
6148
+ // from slotted content bubble through the dropdown host (light DOM),
6149
+ // not through the bib (shadow projection target). Using FocusTrap
6150
+ // on the dropdown would include the trigger in the tab cycle.
6151
+ // Instead, listen for Tab on the dropdown and manually wrap focus
6152
+ // within the bib's focusable elements.
6153
+ this._bibTabHandler = (event) => {
6154
+ if (event.key !== 'Tab') {
6155
+ return;
6156
+ }
6157
+
6158
+ // Collect focusable elements from the bib content.
6159
+ const focusables = getFocusableElements(this.bibContent);
6160
+
6161
+ // Fallback: try from slotted content directly
6162
+ if (!focusables.length) {
6163
+ const slot = this.shadowRoot.querySelector('.slotContent slot');
6164
+ const assignedNodes = slot ? slot.assignedNodes({ flatten: true }) : [];
6165
+
6166
+ for (const node of assignedNodes) {
6167
+ if (node.nodeType === Node.ELEMENT_NODE) {
6168
+ focusables.push(...getFocusableElements(node));
6169
+ }
6170
+ }
6171
+ }
6172
+
6173
+ if (!focusables.length) {
6174
+ return;
6175
+ }
6176
+
6177
+ event.preventDefault();
6178
+
6179
+ const direction = event.shiftKey ? -1 : 1; // eslint-disable-line no-magic-numbers
6180
+
6181
+ // Walk the active element chain through shadow roots
6182
+ const actives = this._getActiveElements();
6183
+
6184
+ let idx = focusables.findIndex((el) => actives.includes(el));
6185
+
6186
+ if (idx === -1) { // eslint-disable-line no-magic-numbers
6187
+ // Focus is not on a known element — move to first/last
6188
+ idx = direction === 1 ? -1 : focusables.length; // eslint-disable-line no-magic-numbers
6189
+ }
6190
+
6191
+ // Try each element in order, skipping any that can't receive focus
6192
+ // (e.g. hidden elements, elements in collapsed sections)
6193
+ for (let index = 0; index < focusables.length; index++) { // eslint-disable-line no-plusplus
6194
+ let nextIdx = idx + direction;
6195
+
6196
+ // Wrap around
6197
+ if (nextIdx < 0) {
6198
+ nextIdx = focusables.length - 1;
6199
+ } else if (nextIdx >= focusables.length) {
6200
+ nextIdx = 0;
6201
+ }
6202
+
6203
+ focusables[nextIdx].focus();
6204
+
6205
+ // Verify focus actually moved to the target
6206
+ const newActives = this._getActiveElements();
6207
+
6208
+ if (newActives.includes(focusables[nextIdx])) {
6209
+ return;
6210
+ }
6211
+
6212
+ // Focus didn't stick — skip this element and try the next
6213
+ idx = nextIdx;
6214
+ }
6215
+ };
6216
+ this.addEventListener('keydown', this._bibTabHandler);
6217
+ } else {
6218
+ // Normal desktop: use FocusTrap on the bib element
6219
+ this.focusTrap = new FocusTrap(this.bibContent);
6220
+ this.focusTrap.focusFirstElement();
6221
+ }
6097
6222
  }
6098
6223
  // Fullscreen: showModal() provides native focus trapping
6224
+ }
6225
+ }
6226
+
6227
+ /**
6228
+ * Returns the chain of active (focused) elements through shadow roots.
6229
+ * @private
6230
+ * @returns {Array<HTMLElement>}
6231
+ */
6232
+ _getActiveElements() {
6233
+ let { activeElement } = document;
6234
+ const actives = [activeElement];
6235
+
6236
+ while (activeElement?.shadowRoot?.activeElement) {
6237
+ activeElement = activeElement.shadowRoot.activeElement;
6238
+ actives.push(activeElement);
6239
+ }
6240
+
6241
+ return actives;
6242
+ }
6243
+
6244
+ /**
6245
+ * Sets `inert` on sibling elements of the dropdown's top-level host
6246
+ * so that content outside the dropdown is not interactive while the modal is open.
6247
+ * Walks up through shadow DOM boundaries to find the outermost host element
6248
+ * in the light DOM, then sets `inert` on that element's siblings.
6249
+ * @private
6250
+ */
6251
+ _setPageInert() {
6252
+ if (this._inertSiblings) {
6099
6253
  return;
6100
6254
  }
6101
6255
 
6102
- if (this.focusTrap) {
6103
- this.focusTrap.disconnect();
6104
- this.focusTrap = undefined;
6256
+ this._inertSiblings = [];
6257
+
6258
+ // Walk up through shadow DOM boundaries to find the topmost host
6259
+ // element in the light DOM. For example, if this dropdown is inside
6260
+ // auro-datepicker's shadow DOM, we walk up to the datepicker element
6261
+ // so we set inert on its siblings — not on the datepicker itself.
6262
+ let host = this;
6263
+ while (host.getRootNode() instanceof ShadowRoot) {
6264
+ host = host.getRootNode().host;
6265
+ }
6266
+
6267
+ const parent = host.parentElement;
6268
+
6269
+ if (parent) {
6270
+ for (const sibling of parent.children) {
6271
+ if (sibling !== host && !sibling.inert) {
6272
+ sibling.inert = true;
6273
+ this._inertSiblings.push(sibling);
6274
+ }
6275
+ }
6276
+ }
6277
+ }
6278
+
6279
+ /**
6280
+ * Restores `inert` state on siblings that were made inert by `_setPageInert`.
6281
+ * @private
6282
+ */
6283
+ _clearPageInert() {
6284
+ if (this._inertSiblings) {
6285
+ for (const sibling of this._inertSiblings) {
6286
+ sibling.inert = false;
6287
+ }
6288
+ this._inertSiblings = undefined;
6105
6289
  }
6106
6290
  }
6107
6291
 
@@ -6340,6 +6524,7 @@ class AuroDropdown extends AuroElement$2 {
6340
6524
  shape="${this.shape}"
6341
6525
  ?data-show="${this.isPopoverVisible}"
6342
6526
  ?isfullscreen="${this.isBibFullscreen}"
6527
+ ?desktopmodal="${this.desktopModal}"
6343
6528
  .dialogLabel="${this.bibDialogLabel}"
6344
6529
  ${n$2(this.bibElement)}
6345
6530
  >
@@ -13045,7 +13230,7 @@ let AuroHelpText$1 = class AuroHelpText extends i$4 {
13045
13230
  }
13046
13231
  };
13047
13232
 
13048
- var formkitVersion$1 = '202605122157';
13233
+ var formkitVersion$1 = '202605182202';
13049
13234
 
13050
13235
  // Copyright (c) 2025 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
13051
13236
  // See LICENSE in the project root for license information.
@@ -13999,6 +14184,14 @@ class AuroBibtemplate extends i$4 {
13999
14184
  large: {
14000
14185
  type: Boolean,
14001
14186
  reflect: true
14187
+ },
14188
+
14189
+ /**
14190
+ * If declared, the footer slot will be rendered even when not in fullscreen mode.
14191
+ */
14192
+ showFooter: {
14193
+ type: Boolean,
14194
+ reflect: true
14002
14195
  }
14003
14196
  };
14004
14197
  }
@@ -14101,7 +14294,7 @@ class AuroBibtemplate extends i$4 {
14101
14294
  <slot></slot>
14102
14295
  </div>
14103
14296
 
14104
- ${this.isFullscreen ? u$7`
14297
+ ${this.isFullscreen || this.showFooter ? u$7`
14105
14298
  <div id="footerContainer">
14106
14299
  <slot name="footer"></slot>
14107
14300
  </div>` : null}
@@ -14110,7 +14303,7 @@ class AuroBibtemplate extends i$4 {
14110
14303
  }
14111
14304
  }
14112
14305
 
14113
- var formkitVersion = '202605122157';
14306
+ var formkitVersion = '202605182202';
14114
14307
 
14115
14308
  var styleCss$3 = i$7`.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}`;
14116
14309
 
@@ -4580,7 +4580,7 @@ function applyKeyboardStrategy(component, strategy, options = {}) {
4580
4580
  });
4581
4581
  }
4582
4582
 
4583
- var styleCss$2$1 = css`:host{position:fixed;z-index:var(--depth-tooltip, 400);display:none;isolation:isolate}:host dialog{width:auto;max-width:none;height:auto;max-height:none;padding:0;border:none;margin:0;outline:none;transform:translateZ(0)}:host dialog::backdrop{background:transparent}:host(:not([isfullscreen])) dialog{position:relative;inset:unset}:host(:not([isfullscreen])) .container.shape-box{border-radius:unset}:host(:not([isfullscreen])) .container[class*=shape-pill],:host(:not([isfullscreen])) .container[class*=shape-snowflake]{border-radius:30px}:host(:not([isfullscreen])) .container[class*=shape-rounded]{border-radius:16px}:host(:not([matchWidth])) .container{min-width:fit-content}:host([isfullscreen]){position:fixed;top:0;left:0}:host([isfullscreen]) .container{width:100dvw;max-width:none;height:100dvh;max-height:none;border-radius:unset;margin-top:0;box-shadow:unset;overscroll-behavior:contain}:host([isfullscreen]) .container::backdrop{background:var(--ds-color-background-primary, #fff)}:host(:popover-open){position:fixed;overflow:visible;padding:0;border:none;margin:0;background:transparent;inset:unset;outline:none}:host([data-show]){display:flex}:host([common]:not([isfullscreen])) .container,:host([rounded]:not([isfullscreen])) .container{border-radius:var(--ds-border-radius, 0.375rem)}:host([common][isfullscreen]) .container,:host([rounded][isfullscreen]) .container{border-radius:unset;box-shadow:unset}.container{display:inline-block;overflow:auto;box-sizing:border-box;border-radius:var(--ds-border-radius, 0.375rem);margin:var(--ds-size-50, 0.25rem) 0}.util_displayHiddenVisually{position:absolute;overflow:hidden;width:1px;height:1px;padding:0;border:0;margin:-1px;clip-path:inset(50%);white-space:nowrap}`;
4583
+ var styleCss$2$1 = css`:host{position:fixed;z-index:var(--depth-tooltip, 400);display:none;isolation:isolate}:host dialog{width:auto;max-width:none;height:auto;max-height:none;padding:0;border:none;margin:0;outline:none;transform:translateZ(0)}:host dialog::backdrop{background:transparent}:host(:not([isfullscreen])) dialog{position:relative;inset:unset}:host(:not([isfullscreen])) .container.shape-box{border-radius:unset}:host(:not([isfullscreen])) .container[class*=shape-pill],:host(:not([isfullscreen])) .container[class*=shape-snowflake]{border-radius:30px}:host(:not([isfullscreen])) .container[class*=shape-rounded]{border-radius:16px}:host([desktopmodal]:popover-open)::backdrop{background:transparent}:host(:not([matchWidth])) .container{min-width:fit-content}:host([isfullscreen]){position:fixed;top:0;left:0}:host([isfullscreen]) .container{width:100dvw;max-width:none;height:100dvh;max-height:none;border-radius:unset;margin-top:0;box-shadow:unset;overscroll-behavior:contain}:host([isfullscreen]) .container::backdrop{background:var(--ds-color-background-primary, #fff)}:host(:popover-open){position:fixed;overflow:visible;padding:0;border:none;margin:0;background:transparent;inset:unset;outline:none}:host([data-show]){display:flex}:host([common]:not([isfullscreen])) .container,:host([rounded]:not([isfullscreen])) .container{border-radius:var(--ds-border-radius, 0.375rem)}:host([common][isfullscreen]) .container,:host([rounded][isfullscreen]) .container{border-radius:unset;box-shadow:unset}.container{display:inline-block;overflow:auto;box-sizing:border-box;border-radius:var(--ds-border-radius, 0.375rem);margin:var(--ds-size-50, 0.25rem) 0}.util_displayHiddenVisually{position:absolute;overflow:hidden;width:1px;height:1px;padding:0;border:0;margin:-1px;clip-path:inset(50%);white-space:nowrap}`;
4584
4584
 
4585
4585
  var colorCss$2$1 = css`.container{background-color:var(--ds-auro-dropdownbib-container-color);box-shadow:var(--ds-auro-dropdownbib-boxshadow-color);color:var(--ds-auro-dropdownbib-text-color)}`;
4586
4586
 
@@ -5211,7 +5211,7 @@ let AuroHelpText$2 = class AuroHelpText extends LitElement {
5211
5211
  }
5212
5212
  };
5213
5213
 
5214
- var formkitVersion$2 = '202605122157';
5214
+ var formkitVersion$2 = '202605182202';
5215
5215
 
5216
5216
  let AuroElement$2 = class AuroElement extends LitElement {
5217
5217
  static get properties() {
@@ -5391,6 +5391,7 @@ class AuroDropdown extends AuroElement$2 {
5391
5391
  _intializeDefaults() {
5392
5392
  this.appearance = 'default';
5393
5393
  this.chevron = false;
5394
+ this.desktopModal = false;
5394
5395
  this.disabled = false;
5395
5396
  this.disableKeyboardHandling = false;
5396
5397
  this.error = false;
@@ -5571,6 +5572,14 @@ class AuroDropdown extends AuroElement$2 {
5571
5572
  reflect: true
5572
5573
  },
5573
5574
 
5575
+ /**
5576
+ * If declared, the dropdown will behave as a modal dialog when in a desktop viewport size.
5577
+ */
5578
+ desktopModal: {
5579
+ type: Boolean,
5580
+ reflect: true
5581
+ },
5582
+
5574
5583
  /**
5575
5584
  * If declared, the dropdown will only show by calling the API .show() public method.
5576
5585
  */
@@ -5858,6 +5867,15 @@ class AuroDropdown extends AuroElement$2 {
5858
5867
 
5859
5868
  disconnectedCallback() {
5860
5869
  super.disconnectedCallback();
5870
+ this._clearPageInert();
5871
+ if (this._bibTabHandler) {
5872
+ this.removeEventListener('keydown', this._bibTabHandler);
5873
+ this._bibTabHandler = undefined;
5874
+ }
5875
+ if (this.focusTrap) {
5876
+ this.focusTrap.disconnect();
5877
+ this.focusTrap = undefined;
5878
+ }
5861
5879
  if (this.floater) {
5862
5880
  this.floater.hideBib('disconnect');
5863
5881
  this.floater.disconnect();
@@ -5885,19 +5903,34 @@ class AuroDropdown extends AuroElement$2 {
5885
5903
  if (this.isPopoverVisible) {
5886
5904
  // Fullscreen: use showModal() for native accessibility (inert outside, focus trap)
5887
5905
  // Desktop: use show() for Floating UI positioning + FocusTrap for focus management
5888
- const useModal = this.isBibFullscreen;
5889
- this.bibElement.value.open(useModal);
5906
+ this.bibElement.value.open(this.isBibFullscreen);
5907
+ this.updateFocusTrap();
5908
+
5909
+ // Desktop modal: make siblings inert so content outside is not interactive
5910
+ if (this.desktopModal && !this.isBibFullscreen) {
5911
+ this._setPageInert();
5912
+ }
5890
5913
  } else {
5891
5914
  this.bibElement.value.close();
5915
+ this._clearPageInert();
5892
5916
  }
5893
5917
  }
5894
5918
 
5895
5919
  // When fullscreen strategy changes while open, re-open dialog with correct mode
5896
5920
  // (e.g. resizing from desktop → mobile while dropdown is open)
5897
5921
  if (changedProperties.has('isBibFullscreen') && this.isPopoverVisible && this.bibElement.value) {
5898
- const useModal = this.isBibFullscreen;
5899
5922
  this.bibElement.value.close();
5900
- this.bibElement.value.open(useModal);
5923
+ this.bibElement.value.open(this.isBibFullscreen);
5924
+
5925
+ // Re-initialize focus management for the new strategy
5926
+ this.updateFocusTrap();
5927
+
5928
+ // Toggle inert: desktop modal needs it, fullscreen showModal() handles it natively
5929
+ if (this.desktopModal && !this.isBibFullscreen) {
5930
+ this._setPageInert();
5931
+ } else {
5932
+ this._clearPageInert();
5933
+ }
5901
5934
  }
5902
5935
  }
5903
5936
 
@@ -5907,8 +5940,14 @@ class AuroDropdown extends AuroElement$2 {
5907
5940
  * @param {CustomEvent} event - The custom event that contains the dropdown toggle information.
5908
5941
  */
5909
5942
  handleDropdownToggle(event) {
5910
- this.updateFocusTrap();
5911
5943
  this.isPopoverVisible = event.detail.expanded;
5944
+
5945
+ // Tear down FocusTrap when closing. Creation happens in updated()
5946
+ // after the dialog is open so getFocusableElements can find content.
5947
+ if (!this.isPopoverVisible) {
5948
+ this.updateFocusTrap();
5949
+ }
5950
+
5912
5951
  const eventType = event.detail.eventType || "unknown";
5913
5952
  if (!this.isPopoverVisible && this.hasFocus && eventType === "keydown") {
5914
5953
  this.trigger.focus();
@@ -6007,19 +6046,164 @@ class AuroDropdown extends AuroElement$2 {
6007
6046
  * @private
6008
6047
  */
6009
6048
  updateFocusTrap() {
6049
+ // Always clean up existing handlers/traps before setting up new ones
6050
+ // to prevent duplicate listeners on repeated calls.
6051
+ if (this._bibTabHandler) {
6052
+ this.removeEventListener('keydown', this._bibTabHandler);
6053
+ this._bibTabHandler = undefined;
6054
+ }
6055
+
6056
+ if (this.focusTrap) {
6057
+ this.focusTrap.disconnect();
6058
+ this.focusTrap = undefined;
6059
+ }
6060
+
6010
6061
  if (this.isPopoverVisible) {
6011
6062
  if (!this.isBibFullscreen) {
6012
- // Desktop: show() doesn't trap focus, so use FocusTrap
6013
- this.focusTrap = new FocusTrap(this.bibContent);
6014
- this.focusTrap.focusFirstElement();
6063
+ if (this.desktopModal) {
6064
+ // Desktop modal: trap focus only within the bib content.
6065
+ // Can't use FocusTrap on the bib element because keydown events
6066
+ // from slotted content bubble through the dropdown host (light DOM),
6067
+ // not through the bib (shadow projection target). Using FocusTrap
6068
+ // on the dropdown would include the trigger in the tab cycle.
6069
+ // Instead, listen for Tab on the dropdown and manually wrap focus
6070
+ // within the bib's focusable elements.
6071
+ this._bibTabHandler = (event) => {
6072
+ if (event.key !== 'Tab') {
6073
+ return;
6074
+ }
6075
+
6076
+ // Collect focusable elements from the bib content.
6077
+ const focusables = getFocusableElements(this.bibContent);
6078
+
6079
+ // Fallback: try from slotted content directly
6080
+ if (!focusables.length) {
6081
+ const slot = this.shadowRoot.querySelector('.slotContent slot');
6082
+ const assignedNodes = slot ? slot.assignedNodes({ flatten: true }) : [];
6083
+
6084
+ for (const node of assignedNodes) {
6085
+ if (node.nodeType === Node.ELEMENT_NODE) {
6086
+ focusables.push(...getFocusableElements(node));
6087
+ }
6088
+ }
6089
+ }
6090
+
6091
+ if (!focusables.length) {
6092
+ return;
6093
+ }
6094
+
6095
+ event.preventDefault();
6096
+
6097
+ const direction = event.shiftKey ? -1 : 1; // eslint-disable-line no-magic-numbers
6098
+
6099
+ // Walk the active element chain through shadow roots
6100
+ const actives = this._getActiveElements();
6101
+
6102
+ let idx = focusables.findIndex((el) => actives.includes(el));
6103
+
6104
+ if (idx === -1) { // eslint-disable-line no-magic-numbers
6105
+ // Focus is not on a known element — move to first/last
6106
+ idx = direction === 1 ? -1 : focusables.length; // eslint-disable-line no-magic-numbers
6107
+ }
6108
+
6109
+ // Try each element in order, skipping any that can't receive focus
6110
+ // (e.g. hidden elements, elements in collapsed sections)
6111
+ for (let index = 0; index < focusables.length; index++) { // eslint-disable-line no-plusplus
6112
+ let nextIdx = idx + direction;
6113
+
6114
+ // Wrap around
6115
+ if (nextIdx < 0) {
6116
+ nextIdx = focusables.length - 1;
6117
+ } else if (nextIdx >= focusables.length) {
6118
+ nextIdx = 0;
6119
+ }
6120
+
6121
+ focusables[nextIdx].focus();
6122
+
6123
+ // Verify focus actually moved to the target
6124
+ const newActives = this._getActiveElements();
6125
+
6126
+ if (newActives.includes(focusables[nextIdx])) {
6127
+ return;
6128
+ }
6129
+
6130
+ // Focus didn't stick — skip this element and try the next
6131
+ idx = nextIdx;
6132
+ }
6133
+ };
6134
+ this.addEventListener('keydown', this._bibTabHandler);
6135
+ } else {
6136
+ // Normal desktop: use FocusTrap on the bib element
6137
+ this.focusTrap = new FocusTrap(this.bibContent);
6138
+ this.focusTrap.focusFirstElement();
6139
+ }
6015
6140
  }
6016
6141
  // Fullscreen: showModal() provides native focus trapping
6142
+ }
6143
+ }
6144
+
6145
+ /**
6146
+ * Returns the chain of active (focused) elements through shadow roots.
6147
+ * @private
6148
+ * @returns {Array<HTMLElement>}
6149
+ */
6150
+ _getActiveElements() {
6151
+ let { activeElement } = document;
6152
+ const actives = [activeElement];
6153
+
6154
+ while (activeElement?.shadowRoot?.activeElement) {
6155
+ activeElement = activeElement.shadowRoot.activeElement;
6156
+ actives.push(activeElement);
6157
+ }
6158
+
6159
+ return actives;
6160
+ }
6161
+
6162
+ /**
6163
+ * Sets `inert` on sibling elements of the dropdown's top-level host
6164
+ * so that content outside the dropdown is not interactive while the modal is open.
6165
+ * Walks up through shadow DOM boundaries to find the outermost host element
6166
+ * in the light DOM, then sets `inert` on that element's siblings.
6167
+ * @private
6168
+ */
6169
+ _setPageInert() {
6170
+ if (this._inertSiblings) {
6017
6171
  return;
6018
6172
  }
6019
6173
 
6020
- if (this.focusTrap) {
6021
- this.focusTrap.disconnect();
6022
- this.focusTrap = undefined;
6174
+ this._inertSiblings = [];
6175
+
6176
+ // Walk up through shadow DOM boundaries to find the topmost host
6177
+ // element in the light DOM. For example, if this dropdown is inside
6178
+ // auro-datepicker's shadow DOM, we walk up to the datepicker element
6179
+ // so we set inert on its siblings — not on the datepicker itself.
6180
+ let host = this;
6181
+ while (host.getRootNode() instanceof ShadowRoot) {
6182
+ host = host.getRootNode().host;
6183
+ }
6184
+
6185
+ const parent = host.parentElement;
6186
+
6187
+ if (parent) {
6188
+ for (const sibling of parent.children) {
6189
+ if (sibling !== host && !sibling.inert) {
6190
+ sibling.inert = true;
6191
+ this._inertSiblings.push(sibling);
6192
+ }
6193
+ }
6194
+ }
6195
+ }
6196
+
6197
+ /**
6198
+ * Restores `inert` state on siblings that were made inert by `_setPageInert`.
6199
+ * @private
6200
+ */
6201
+ _clearPageInert() {
6202
+ if (this._inertSiblings) {
6203
+ for (const sibling of this._inertSiblings) {
6204
+ sibling.inert = false;
6205
+ }
6206
+ this._inertSiblings = undefined;
6023
6207
  }
6024
6208
  }
6025
6209
 
@@ -6258,6 +6442,7 @@ class AuroDropdown extends AuroElement$2 {
6258
6442
  shape="${this.shape}"
6259
6443
  ?data-show="${this.isPopoverVisible}"
6260
6444
  ?isfullscreen="${this.isBibFullscreen}"
6445
+ ?desktopmodal="${this.desktopModal}"
6261
6446
  .dialogLabel="${this.bibDialogLabel}"
6262
6447
  ${ref(this.bibElement)}
6263
6448
  >
@@ -12956,7 +13141,7 @@ let AuroHelpText$1 = class AuroHelpText extends LitElement {
12956
13141
  }
12957
13142
  };
12958
13143
 
12959
- var formkitVersion$1 = '202605122157';
13144
+ var formkitVersion$1 = '202605182202';
12960
13145
 
12961
13146
  // Copyright (c) 2025 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
12962
13147
  // See LICENSE in the project root for license information.
@@ -13910,6 +14095,14 @@ class AuroBibtemplate extends LitElement {
13910
14095
  large: {
13911
14096
  type: Boolean,
13912
14097
  reflect: true
14098
+ },
14099
+
14100
+ /**
14101
+ * If declared, the footer slot will be rendered even when not in fullscreen mode.
14102
+ */
14103
+ showFooter: {
14104
+ type: Boolean,
14105
+ reflect: true
13913
14106
  }
13914
14107
  };
13915
14108
  }
@@ -14012,7 +14205,7 @@ class AuroBibtemplate extends LitElement {
14012
14205
  <slot></slot>
14013
14206
  </div>
14014
14207
 
14015
- ${this.isFullscreen ? html`
14208
+ ${this.isFullscreen || this.showFooter ? html`
14016
14209
  <div id="footerContainer">
14017
14210
  <slot name="footer"></slot>
14018
14211
  </div>` : null}
@@ -14021,7 +14214,7 @@ class AuroBibtemplate extends LitElement {
14021
14214
  }
14022
14215
  }
14023
14216
 
14024
- var formkitVersion = '202605122157';
14217
+ var formkitVersion = '202605182202';
14025
14218
 
14026
14219
  var styleCss$1 = css`.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}`;
14027
14220