@aurodesignsystem-dev/auro-formkit 0.0.0-pr1474.3 → 0.0.0-pr1475.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 (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 +2130 -1518
  83. package/package.json +2 -2
@@ -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 = '202605122144';
5214
+ var formkitVersion$2 = '202605182147';
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 = '202605122144';
13144
+ var formkitVersion$1 = '202605182147';
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 = '202605122144';
14217
+ var formkitVersion = '202605182147';
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
 
@@ -1521,7 +1521,7 @@ let AuroHelpText$1 = class AuroHelpText extends i$2 {
1521
1521
  }
1522
1522
  };
1523
1523
 
1524
- var formkitVersion$1 = '202605122144';
1524
+ var formkitVersion$1 = '202605182147';
1525
1525
 
1526
1526
  // Copyright (c) 2026 Alaska Airlines. All rights reserved. Licensed under the Apache-2.0 license
1527
1527
  // See LICENSE in the project root for license information.
@@ -5236,7 +5236,7 @@ function applyKeyboardStrategy(component, strategy, options = {}) {
5236
5236
  });
5237
5237
  }
5238
5238
 
5239
- var styleCss$2 = i$5`: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}`;
5239
+ var styleCss$2 = i$5`: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}`;
5240
5240
 
5241
5241
  var colorCss$2 = i$5`.container{background-color:var(--ds-auro-dropdownbib-container-color);box-shadow:var(--ds-auro-dropdownbib-boxshadow-color);color:var(--ds-auro-dropdownbib-text-color)}`;
5242
5242
 
@@ -5867,7 +5867,7 @@ class AuroHelpText extends i$2 {
5867
5867
  }
5868
5868
  }
5869
5869
 
5870
- var formkitVersion = '202605122144';
5870
+ var formkitVersion = '202605182147';
5871
5871
 
5872
5872
  let AuroElement$1 = class AuroElement extends i$2 {
5873
5873
  static get properties() {
@@ -6047,6 +6047,7 @@ class AuroDropdown extends AuroElement$1 {
6047
6047
  _intializeDefaults() {
6048
6048
  this.appearance = 'default';
6049
6049
  this.chevron = false;
6050
+ this.desktopModal = false;
6050
6051
  this.disabled = false;
6051
6052
  this.disableKeyboardHandling = false;
6052
6053
  this.error = false;
@@ -6227,6 +6228,14 @@ class AuroDropdown extends AuroElement$1 {
6227
6228
  reflect: true
6228
6229
  },
6229
6230
 
6231
+ /**
6232
+ * If declared, the dropdown will behave as a modal dialog when in a desktop viewport size.
6233
+ */
6234
+ desktopModal: {
6235
+ type: Boolean,
6236
+ reflect: true
6237
+ },
6238
+
6230
6239
  /**
6231
6240
  * If declared, the dropdown will only show by calling the API .show() public method.
6232
6241
  */
@@ -6514,6 +6523,15 @@ class AuroDropdown extends AuroElement$1 {
6514
6523
 
6515
6524
  disconnectedCallback() {
6516
6525
  super.disconnectedCallback();
6526
+ this._clearPageInert();
6527
+ if (this._bibTabHandler) {
6528
+ this.removeEventListener('keydown', this._bibTabHandler);
6529
+ this._bibTabHandler = undefined;
6530
+ }
6531
+ if (this.focusTrap) {
6532
+ this.focusTrap.disconnect();
6533
+ this.focusTrap = undefined;
6534
+ }
6517
6535
  if (this.floater) {
6518
6536
  this.floater.hideBib('disconnect');
6519
6537
  this.floater.disconnect();
@@ -6541,19 +6559,34 @@ class AuroDropdown extends AuroElement$1 {
6541
6559
  if (this.isPopoverVisible) {
6542
6560
  // Fullscreen: use showModal() for native accessibility (inert outside, focus trap)
6543
6561
  // Desktop: use show() for Floating UI positioning + FocusTrap for focus management
6544
- const useModal = this.isBibFullscreen;
6545
- this.bibElement.value.open(useModal);
6562
+ this.bibElement.value.open(this.isBibFullscreen);
6563
+ this.updateFocusTrap();
6564
+
6565
+ // Desktop modal: make siblings inert so content outside is not interactive
6566
+ if (this.desktopModal && !this.isBibFullscreen) {
6567
+ this._setPageInert();
6568
+ }
6546
6569
  } else {
6547
6570
  this.bibElement.value.close();
6571
+ this._clearPageInert();
6548
6572
  }
6549
6573
  }
6550
6574
 
6551
6575
  // When fullscreen strategy changes while open, re-open dialog with correct mode
6552
6576
  // (e.g. resizing from desktop → mobile while dropdown is open)
6553
6577
  if (changedProperties.has('isBibFullscreen') && this.isPopoverVisible && this.bibElement.value) {
6554
- const useModal = this.isBibFullscreen;
6555
6578
  this.bibElement.value.close();
6556
- this.bibElement.value.open(useModal);
6579
+ this.bibElement.value.open(this.isBibFullscreen);
6580
+
6581
+ // Re-initialize focus management for the new strategy
6582
+ this.updateFocusTrap();
6583
+
6584
+ // Toggle inert: desktop modal needs it, fullscreen showModal() handles it natively
6585
+ if (this.desktopModal && !this.isBibFullscreen) {
6586
+ this._setPageInert();
6587
+ } else {
6588
+ this._clearPageInert();
6589
+ }
6557
6590
  }
6558
6591
  }
6559
6592
 
@@ -6563,8 +6596,14 @@ class AuroDropdown extends AuroElement$1 {
6563
6596
  * @param {CustomEvent} event - The custom event that contains the dropdown toggle information.
6564
6597
  */
6565
6598
  handleDropdownToggle(event) {
6566
- this.updateFocusTrap();
6567
6599
  this.isPopoverVisible = event.detail.expanded;
6600
+
6601
+ // Tear down FocusTrap when closing. Creation happens in updated()
6602
+ // after the dialog is open so getFocusableElements can find content.
6603
+ if (!this.isPopoverVisible) {
6604
+ this.updateFocusTrap();
6605
+ }
6606
+
6568
6607
  const eventType = event.detail.eventType || "unknown";
6569
6608
  if (!this.isPopoverVisible && this.hasFocus && eventType === "keydown") {
6570
6609
  this.trigger.focus();
@@ -6663,19 +6702,164 @@ class AuroDropdown extends AuroElement$1 {
6663
6702
  * @private
6664
6703
  */
6665
6704
  updateFocusTrap() {
6705
+ // Always clean up existing handlers/traps before setting up new ones
6706
+ // to prevent duplicate listeners on repeated calls.
6707
+ if (this._bibTabHandler) {
6708
+ this.removeEventListener('keydown', this._bibTabHandler);
6709
+ this._bibTabHandler = undefined;
6710
+ }
6711
+
6712
+ if (this.focusTrap) {
6713
+ this.focusTrap.disconnect();
6714
+ this.focusTrap = undefined;
6715
+ }
6716
+
6666
6717
  if (this.isPopoverVisible) {
6667
6718
  if (!this.isBibFullscreen) {
6668
- // Desktop: show() doesn't trap focus, so use FocusTrap
6669
- this.focusTrap = new FocusTrap(this.bibContent);
6670
- this.focusTrap.focusFirstElement();
6719
+ if (this.desktopModal) {
6720
+ // Desktop modal: trap focus only within the bib content.
6721
+ // Can't use FocusTrap on the bib element because keydown events
6722
+ // from slotted content bubble through the dropdown host (light DOM),
6723
+ // not through the bib (shadow projection target). Using FocusTrap
6724
+ // on the dropdown would include the trigger in the tab cycle.
6725
+ // Instead, listen for Tab on the dropdown and manually wrap focus
6726
+ // within the bib's focusable elements.
6727
+ this._bibTabHandler = (event) => {
6728
+ if (event.key !== 'Tab') {
6729
+ return;
6730
+ }
6731
+
6732
+ // Collect focusable elements from the bib content.
6733
+ const focusables = getFocusableElements(this.bibContent);
6734
+
6735
+ // Fallback: try from slotted content directly
6736
+ if (!focusables.length) {
6737
+ const slot = this.shadowRoot.querySelector('.slotContent slot');
6738
+ const assignedNodes = slot ? slot.assignedNodes({ flatten: true }) : [];
6739
+
6740
+ for (const node of assignedNodes) {
6741
+ if (node.nodeType === Node.ELEMENT_NODE) {
6742
+ focusables.push(...getFocusableElements(node));
6743
+ }
6744
+ }
6745
+ }
6746
+
6747
+ if (!focusables.length) {
6748
+ return;
6749
+ }
6750
+
6751
+ event.preventDefault();
6752
+
6753
+ const direction = event.shiftKey ? -1 : 1; // eslint-disable-line no-magic-numbers
6754
+
6755
+ // Walk the active element chain through shadow roots
6756
+ const actives = this._getActiveElements();
6757
+
6758
+ let idx = focusables.findIndex((el) => actives.includes(el));
6759
+
6760
+ if (idx === -1) { // eslint-disable-line no-magic-numbers
6761
+ // Focus is not on a known element — move to first/last
6762
+ idx = direction === 1 ? -1 : focusables.length; // eslint-disable-line no-magic-numbers
6763
+ }
6764
+
6765
+ // Try each element in order, skipping any that can't receive focus
6766
+ // (e.g. hidden elements, elements in collapsed sections)
6767
+ for (let index = 0; index < focusables.length; index++) { // eslint-disable-line no-plusplus
6768
+ let nextIdx = idx + direction;
6769
+
6770
+ // Wrap around
6771
+ if (nextIdx < 0) {
6772
+ nextIdx = focusables.length - 1;
6773
+ } else if (nextIdx >= focusables.length) {
6774
+ nextIdx = 0;
6775
+ }
6776
+
6777
+ focusables[nextIdx].focus();
6778
+
6779
+ // Verify focus actually moved to the target
6780
+ const newActives = this._getActiveElements();
6781
+
6782
+ if (newActives.includes(focusables[nextIdx])) {
6783
+ return;
6784
+ }
6785
+
6786
+ // Focus didn't stick — skip this element and try the next
6787
+ idx = nextIdx;
6788
+ }
6789
+ };
6790
+ this.addEventListener('keydown', this._bibTabHandler);
6791
+ } else {
6792
+ // Normal desktop: use FocusTrap on the bib element
6793
+ this.focusTrap = new FocusTrap(this.bibContent);
6794
+ this.focusTrap.focusFirstElement();
6795
+ }
6671
6796
  }
6672
6797
  // Fullscreen: showModal() provides native focus trapping
6798
+ }
6799
+ }
6800
+
6801
+ /**
6802
+ * Returns the chain of active (focused) elements through shadow roots.
6803
+ * @private
6804
+ * @returns {Array<HTMLElement>}
6805
+ */
6806
+ _getActiveElements() {
6807
+ let { activeElement } = document;
6808
+ const actives = [activeElement];
6809
+
6810
+ while (activeElement?.shadowRoot?.activeElement) {
6811
+ activeElement = activeElement.shadowRoot.activeElement;
6812
+ actives.push(activeElement);
6813
+ }
6814
+
6815
+ return actives;
6816
+ }
6817
+
6818
+ /**
6819
+ * Sets `inert` on sibling elements of the dropdown's top-level host
6820
+ * so that content outside the dropdown is not interactive while the modal is open.
6821
+ * Walks up through shadow DOM boundaries to find the outermost host element
6822
+ * in the light DOM, then sets `inert` on that element's siblings.
6823
+ * @private
6824
+ */
6825
+ _setPageInert() {
6826
+ if (this._inertSiblings) {
6673
6827
  return;
6674
6828
  }
6675
6829
 
6676
- if (this.focusTrap) {
6677
- this.focusTrap.disconnect();
6678
- this.focusTrap = undefined;
6830
+ this._inertSiblings = [];
6831
+
6832
+ // Walk up through shadow DOM boundaries to find the topmost host
6833
+ // element in the light DOM. For example, if this dropdown is inside
6834
+ // auro-datepicker's shadow DOM, we walk up to the datepicker element
6835
+ // so we set inert on its siblings — not on the datepicker itself.
6836
+ let host = this;
6837
+ while (host.getRootNode() instanceof ShadowRoot) {
6838
+ host = host.getRootNode().host;
6839
+ }
6840
+
6841
+ const parent = host.parentElement;
6842
+
6843
+ if (parent) {
6844
+ for (const sibling of parent.children) {
6845
+ if (sibling !== host && !sibling.inert) {
6846
+ sibling.inert = true;
6847
+ this._inertSiblings.push(sibling);
6848
+ }
6849
+ }
6850
+ }
6851
+ }
6852
+
6853
+ /**
6854
+ * Restores `inert` state on siblings that were made inert by `_setPageInert`.
6855
+ * @private
6856
+ */
6857
+ _clearPageInert() {
6858
+ if (this._inertSiblings) {
6859
+ for (const sibling of this._inertSiblings) {
6860
+ sibling.inert = false;
6861
+ }
6862
+ this._inertSiblings = undefined;
6679
6863
  }
6680
6864
  }
6681
6865
 
@@ -6914,6 +7098,7 @@ class AuroDropdown extends AuroElement$1 {
6914
7098
  shape="${this.shape}"
6915
7099
  ?data-show="${this.isPopoverVisible}"
6916
7100
  ?isfullscreen="${this.isBibFullscreen}"
7101
+ ?desktopmodal="${this.desktopModal}"
6917
7102
  .dialogLabel="${this.bibDialogLabel}"
6918
7103
  ${n$1(this.bibElement)}
6919
7104
  >
@@ -7281,6 +7466,14 @@ class AuroBibtemplate extends i$2 {
7281
7466
  large: {
7282
7467
  type: Boolean,
7283
7468
  reflect: true
7469
+ },
7470
+
7471
+ /**
7472
+ * If declared, the footer slot will be rendered even when not in fullscreen mode.
7473
+ */
7474
+ showFooter: {
7475
+ type: Boolean,
7476
+ reflect: true
7284
7477
  }
7285
7478
  };
7286
7479
  }
@@ -7383,7 +7576,7 @@ class AuroBibtemplate extends i$2 {
7383
7576
  <slot></slot>
7384
7577
  </div>
7385
7578
 
7386
- ${this.isFullscreen ? u$5`
7579
+ ${this.isFullscreen || this.showFooter ? u$5`
7387
7580
  <div id="footerContainer">
7388
7581
  <slot name="footer"></slot>
7389
7582
  </div>` : null}