@aurodesignsystem-dev/auro-formkit 0.0.0-pr1346.2 → 0.0.0-pr1346.4

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 (40) hide show
  1. package/components/checkbox/demo/api.min.js +1 -1
  2. package/components/checkbox/demo/index.min.js +1 -1
  3. package/components/checkbox/dist/index.js +1 -1
  4. package/components/checkbox/dist/registered.js +1 -1
  5. package/components/combobox/demo/api.min.js +252 -65
  6. package/components/combobox/demo/index.min.js +252 -65
  7. package/components/combobox/dist/auro-combobox.d.ts +2 -1
  8. package/components/combobox/dist/index.js +245 -62
  9. package/components/combobox/dist/registered.js +245 -62
  10. package/components/counter/demo/api.min.js +124 -12
  11. package/components/counter/demo/index.min.js +124 -12
  12. package/components/counter/dist/index.js +124 -12
  13. package/components/counter/dist/registered.js +124 -12
  14. package/components/datepicker/demo/api.min.js +161 -40
  15. package/components/datepicker/demo/index.min.js +161 -40
  16. package/components/datepicker/dist/index.js +161 -40
  17. package/components/datepicker/dist/registered.js +161 -40
  18. package/components/dropdown/demo/api.min.js +122 -10
  19. package/components/dropdown/demo/index.min.js +122 -10
  20. package/components/dropdown/dist/auro-dropdownBib.d.ts +18 -2
  21. package/components/dropdown/dist/index.js +122 -10
  22. package/components/dropdown/dist/registered.js +122 -10
  23. package/components/input/demo/api.min.js +38 -29
  24. package/components/input/demo/index.min.js +38 -29
  25. package/components/input/dist/index.js +38 -29
  26. package/components/input/dist/registered.js +38 -29
  27. package/components/menu/demo/api.min.js +7 -3
  28. package/components/menu/demo/index.min.js +7 -3
  29. package/components/menu/dist/index.js +7 -3
  30. package/components/menu/dist/registered.js +7 -3
  31. package/components/radio/demo/api.min.js +1 -1
  32. package/components/radio/demo/index.min.js +1 -1
  33. package/components/radio/dist/index.js +1 -1
  34. package/components/radio/dist/registered.js +1 -1
  35. package/components/select/demo/api.min.js +159 -17
  36. package/components/select/demo/index.min.js +159 -17
  37. package/components/select/dist/index.js +152 -14
  38. package/components/select/dist/registered.js +152 -14
  39. package/custom-elements.json +35 -10
  40. package/package.json +1 -1
@@ -1442,7 +1442,7 @@ let AuroHelpText$1 = class AuroHelpText extends i$2 {
1442
1442
  }
1443
1443
  };
1444
1444
 
1445
- var formkitVersion$1 = '202602201708';
1445
+ var formkitVersion$1 = '202602260152';
1446
1446
 
1447
1447
  // Copyright (c) 2025 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
1448
1448
  // See LICENSE in the project root for license information.
@@ -1827,7 +1827,7 @@ class AuroCounter extends i$2 {
1827
1827
  aria-valuemax="${this.max}"
1828
1828
  aria-valuemin="${this.min}"
1829
1829
  aria-valuenow="${this.value}"
1830
- aria-valuetext="${this.value !== undefined ? this.value : this.min}"
1830
+ aria-valuetext="'${this.value !== undefined ? this.value : this.min}'"
1831
1831
  role="spinbutton"
1832
1832
  tabindex="${this.disabled ? '-1' : '0'}"
1833
1833
  >
@@ -4696,7 +4696,7 @@ let p$2 = class p{registerComponent(t,a){customElements.get(t)||customElements.d
4696
4696
 
4697
4697
  var iconVersion$1 = '9.1.2';
4698
4698
 
4699
- var styleCss$2 = i$5`:host{position:fixed;z-index:var(--depth-tooltip, 400);display:none;isolation:isolate}:host dialog{max-width:none;max-height:none;padding:0;border:none;margin:0;outline:none;transform:translateZ(0)}:host dialog::backdrop{background:transparent}:host(:not([isfullscreen])) dialog{position:absolute;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([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}`;
4699
+ var styleCss$2 = i$5`:host{position:fixed;z-index:var(--depth-tooltip, 400);display:none;isolation:isolate}:host dialog{max-width:none;max-height:none;padding:0;border:none;margin:0;outline:none;transform:translateZ(0)}:host dialog::backdrop{background:transparent}:host(:not([isfullscreen])) dialog{position:absolute;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([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}`;
4700
4700
 
4701
4701
  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)}`;
4702
4702
 
@@ -4704,6 +4704,8 @@ var tokensCss$1 = i$5`:host(:not([ondark])),:host(:not([appearance=inverse])){--
4704
4704
 
4705
4705
  // Copyright (c) 2020 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
4706
4706
  // See LICENSE in the project root for license information.
4707
+ /* eslint-disable max-lines */
4708
+ // ---------------------------------------------------------------------
4707
4709
 
4708
4710
 
4709
4711
  const DESIGN_TOKEN_BREAKPOINT_PREFIX = '--ds-grid-breakpoint-';
@@ -4879,22 +4881,63 @@ class AuroDropdownBib extends i$2 {
4879
4881
  // Handle ESC key via dialog's cancel event
4880
4882
  const dialog = this.shadowRoot.querySelector('dialog');
4881
4883
  dialog.addEventListener('cancel', (event) => {
4882
- event.preventDefault(); // Let parent handle closing
4884
+ // Let parent handle closing
4885
+ event.preventDefault();
4883
4886
  this.dispatchEvent(new CustomEvent('auro-bib-cancel', {
4884
4887
  bubbles: true,
4885
4888
  composed: true
4886
4889
  }));
4887
4890
  });
4888
4891
 
4889
- // Re-dispatch navigation keyboard events so they cross the shadow DOM
4890
- // boundary and reach the combobox/select key handlers.
4891
- // Only intercept keys used for menu navigation let all other keys
4892
- // (characters, Backspace, etc.) through so typing in inputs works.
4893
- const navKeys = new Set(['ArrowUp', 'ArrowDown', 'Enter', 'Escape']);
4892
+ // showModal() creates a closed focus scope keyboard events inside
4893
+ // the dialog's shadow DOM do NOT bubble out to the combobox/select
4894
+ // keydown handlers in the parent shadow DOM. This handler bridges
4895
+ // that gap by re-dispatching navigation keys so they cross the
4896
+ // shadow boundary and reach the menu navigation logic in the parent
4897
+ // component.
4898
+ //
4899
+ // The trade-off: intercepting these keys means native keyboard
4900
+ // behaviors that would normally "just work" must be manually
4901
+ // re-implemented here:
4902
+ //
4903
+ // - Enter on buttons: Custom elements (auro-button) don't get the
4904
+ // native Enter→click that <button> provides, so we call .click()
4905
+ // directly when Enter is pressed on a button-like element.
4906
+ //
4907
+ // - Tab: NOT intercepted — left to the browser's native focus trap
4908
+ // provided by showModal(), which cycles Tab between focusable
4909
+ // elements inside the dialog (e.g. the input and close button).
4910
+ // Intercepting Tab would kill the native focus trap and break
4911
+ // focus management inside the dialog.
4912
+ //
4913
+ // - Escape: The native <dialog> fires a `cancel` event on ESC
4914
+ // (handled above), so the re-dispatched Escape is a secondary
4915
+ // path for parent components that also listen for Escape keydown.
4916
+ const navKeys = new Set([
4917
+ 'ArrowUp',
4918
+ 'ArrowDown',
4919
+ 'Enter',
4920
+ 'Escape'
4921
+ ]);
4894
4922
  dialog.addEventListener('keydown', (event) => {
4895
4923
  if (!navKeys.has(event.key)) {
4896
4924
  return;
4897
4925
  }
4926
+
4927
+ // Custom elements (auro-button) don't get the native Enter→click
4928
+ // behavior that <button> has. Find the button in the composed path
4929
+ // and click it directly.
4930
+ if (event.key === 'Enter') {
4931
+ const buttonSelector = 'button, [role="button"], auro-button, [auro-button]';
4932
+ const btn = event.composedPath().find((el) => el.matches && el.matches(buttonSelector));
4933
+ if (btn) {
4934
+ event.preventDefault();
4935
+ event.stopPropagation();
4936
+ btn.click();
4937
+ return;
4938
+ }
4939
+ }
4940
+
4898
4941
  event.preventDefault();
4899
4942
  event.stopPropagation();
4900
4943
  const newEvent = new KeyboardEvent('keydown', {
@@ -4918,9 +4961,55 @@ class AuroDropdownBib extends i$2 {
4918
4961
  }
4919
4962
 
4920
4963
  /**
4921
- * Opens the dialog using showModal() for accessibility.
4922
- * @param {boolean} modal - If true, uses showModal() (default). If false, uses show().
4964
+ * Blocks touch-driven page scroll while a fullscreen modal dialog is open.
4965
+ *
4966
+ * The showModal() function places the dialog in the browser's **top layer**,
4967
+ * which is a separate rendering layer above the normal DOM. On mobile, the
4968
+ * compositor processes visual-viewport panning before top-layer touch
4969
+ * handling. This means the entire viewport — including the top-layer dialog
4970
+ * — can be panned by a touch gesture, causing the page behind the dialog to
4971
+ * scroll into view. To prevent this, we add a touchmove listener that cancels
4972
+ * the event if the touch started outside the dialog or any scrollable child within it.
4973
+ *
4974
+ * @private
4923
4975
  */
4976
+ _lockTouchScroll() {
4977
+ const dialog = this.shadowRoot.querySelector('dialog');
4978
+
4979
+ this._touchMoveHandler = (event) => {
4980
+ // Walk the composed path (which crosses shadow DOM boundaries) to
4981
+ // check whether the touch started inside a scrollable element that
4982
+ // lives within the dialog. If so, allow the scroll.
4983
+ for (const el of event.composedPath()) {
4984
+ if (el === dialog) {
4985
+ // Reached the dialog boundary without finding a scrollable child.
4986
+ break;
4987
+ }
4988
+ if (el instanceof HTMLElement && el.scrollHeight > el.clientHeight) {
4989
+ const { overflowY } = getComputedStyle(el);
4990
+ if (overflowY === 'auto' || overflowY === 'scroll') {
4991
+ return;
4992
+ }
4993
+ }
4994
+ }
4995
+
4996
+ event.preventDefault();
4997
+ };
4998
+
4999
+ document.addEventListener('touchmove', this._touchMoveHandler, { passive: false });
5000
+ }
5001
+
5002
+ /**
5003
+ * Removes the touchmove listener added by _lockTouchScroll().
5004
+ * @private
5005
+ */
5006
+ _unlockTouchScroll() {
5007
+ if (this._touchMoveHandler) {
5008
+ document.removeEventListener('touchmove', this._touchMoveHandler);
5009
+ this._touchMoveHandler = undefined;
5010
+ }
5011
+ }
5012
+
4924
5013
  open(modal = true) {
4925
5014
  const dialog = this.shadowRoot.querySelector('dialog');
4926
5015
  if (dialog && !dialog.open) {
@@ -4937,6 +5026,8 @@ class AuroDropdownBib extends i$2 {
4937
5026
 
4938
5027
  documentElement.style.overflow = prevOverflow;
4939
5028
 
5029
+ this._lockTouchScroll();
5030
+
4940
5031
  } else {
4941
5032
  // Use setAttribute instead of dialog.show() to avoid the dialog
4942
5033
  // focusing steps which steal focus from the trigger and cause
@@ -4952,6 +5043,7 @@ class AuroDropdownBib extends i$2 {
4952
5043
  close() {
4953
5044
  const dialog = this.shadowRoot.querySelector('dialog');
4954
5045
  if (dialog && dialog.open) {
5046
+ this._unlockTouchScroll();
4955
5047
  dialog.close();
4956
5048
  }
4957
5049
  }
@@ -5217,7 +5309,7 @@ class AuroHelpText extends i$2 {
5217
5309
  }
5218
5310
  }
5219
5311
 
5220
- var formkitVersion = '202602201708';
5312
+ var formkitVersion = '202602260152';
5221
5313
 
5222
5314
  let AuroElement$1 = class AuroElement extends i$2 {
5223
5315
  static get properties() {
@@ -5490,6 +5582,18 @@ class AuroDropdown extends AuroElement$1 {
5490
5582
  */
5491
5583
  show() {
5492
5584
  this.floater.showBib();
5585
+
5586
+ // Open dialog synchronously so callers remain in the user gesture
5587
+ // chain. This is critical for mobile browsers (iOS Safari) to keep
5588
+ // the virtual keyboard open when transitioning from the trigger
5589
+ // input to an input inside the fullscreen dialog. Without this,
5590
+ // showModal() fires asynchronously via Lit's update cycle, which
5591
+ // falls outside the user activation window and causes iOS to
5592
+ // dismiss the keyboard.
5593
+ if (this.isBibFullscreen && this.bibElement && this.bibElement.value) {
5594
+ const useModal = !this.disableFocusTrap;
5595
+ this.bibElement.value.open(useModal);
5596
+ }
5493
5597
  }
5494
5598
 
5495
5599
  /**
@@ -5876,6 +5980,14 @@ class AuroDropdown extends AuroElement$1 {
5876
5980
  this.bibElement.value.close();
5877
5981
  }
5878
5982
  }
5983
+
5984
+ // When fullscreen strategy changes while open, re-open dialog with correct mode
5985
+ // (e.g. resizing from desktop → mobile while dropdown is open)
5986
+ if (changedProperties.has('isBibFullscreen') && this.isPopoverVisible && this.bibElement.value) {
5987
+ const useModal = this.isBibFullscreen && !this.disableFocusTrap;
5988
+ this.bibElement.value.close();
5989
+ this.bibElement.value.open(useModal);
5990
+ }
5879
5991
  }
5880
5992
 
5881
5993
  /**
@@ -1442,7 +1442,7 @@ let AuroHelpText$1 = class AuroHelpText extends i$2 {
1442
1442
  }
1443
1443
  };
1444
1444
 
1445
- var formkitVersion$1 = '202602201708';
1445
+ var formkitVersion$1 = '202602260152';
1446
1446
 
1447
1447
  // Copyright (c) 2025 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
1448
1448
  // See LICENSE in the project root for license information.
@@ -1827,7 +1827,7 @@ class AuroCounter extends i$2 {
1827
1827
  aria-valuemax="${this.max}"
1828
1828
  aria-valuemin="${this.min}"
1829
1829
  aria-valuenow="${this.value}"
1830
- aria-valuetext="${this.value !== undefined ? this.value : this.min}"
1830
+ aria-valuetext="'${this.value !== undefined ? this.value : this.min}'"
1831
1831
  role="spinbutton"
1832
1832
  tabindex="${this.disabled ? '-1' : '0'}"
1833
1833
  >
@@ -4696,7 +4696,7 @@ let p$2 = class p{registerComponent(t,a){customElements.get(t)||customElements.d
4696
4696
 
4697
4697
  var iconVersion$1 = '9.1.2';
4698
4698
 
4699
- var styleCss$2 = i$5`:host{position:fixed;z-index:var(--depth-tooltip, 400);display:none;isolation:isolate}:host dialog{max-width:none;max-height:none;padding:0;border:none;margin:0;outline:none;transform:translateZ(0)}:host dialog::backdrop{background:transparent}:host(:not([isfullscreen])) dialog{position:absolute;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([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}`;
4699
+ var styleCss$2 = i$5`:host{position:fixed;z-index:var(--depth-tooltip, 400);display:none;isolation:isolate}:host dialog{max-width:none;max-height:none;padding:0;border:none;margin:0;outline:none;transform:translateZ(0)}:host dialog::backdrop{background:transparent}:host(:not([isfullscreen])) dialog{position:absolute;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([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}`;
4700
4700
 
4701
4701
  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)}`;
4702
4702
 
@@ -4704,6 +4704,8 @@ var tokensCss$1 = i$5`:host(:not([ondark])),:host(:not([appearance=inverse])){--
4704
4704
 
4705
4705
  // Copyright (c) 2020 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
4706
4706
  // See LICENSE in the project root for license information.
4707
+ /* eslint-disable max-lines */
4708
+ // ---------------------------------------------------------------------
4707
4709
 
4708
4710
 
4709
4711
  const DESIGN_TOKEN_BREAKPOINT_PREFIX = '--ds-grid-breakpoint-';
@@ -4879,22 +4881,63 @@ class AuroDropdownBib extends i$2 {
4879
4881
  // Handle ESC key via dialog's cancel event
4880
4882
  const dialog = this.shadowRoot.querySelector('dialog');
4881
4883
  dialog.addEventListener('cancel', (event) => {
4882
- event.preventDefault(); // Let parent handle closing
4884
+ // Let parent handle closing
4885
+ event.preventDefault();
4883
4886
  this.dispatchEvent(new CustomEvent('auro-bib-cancel', {
4884
4887
  bubbles: true,
4885
4888
  composed: true
4886
4889
  }));
4887
4890
  });
4888
4891
 
4889
- // Re-dispatch navigation keyboard events so they cross the shadow DOM
4890
- // boundary and reach the combobox/select key handlers.
4891
- // Only intercept keys used for menu navigation let all other keys
4892
- // (characters, Backspace, etc.) through so typing in inputs works.
4893
- const navKeys = new Set(['ArrowUp', 'ArrowDown', 'Enter', 'Escape']);
4892
+ // showModal() creates a closed focus scope keyboard events inside
4893
+ // the dialog's shadow DOM do NOT bubble out to the combobox/select
4894
+ // keydown handlers in the parent shadow DOM. This handler bridges
4895
+ // that gap by re-dispatching navigation keys so they cross the
4896
+ // shadow boundary and reach the menu navigation logic in the parent
4897
+ // component.
4898
+ //
4899
+ // The trade-off: intercepting these keys means native keyboard
4900
+ // behaviors that would normally "just work" must be manually
4901
+ // re-implemented here:
4902
+ //
4903
+ // - Enter on buttons: Custom elements (auro-button) don't get the
4904
+ // native Enter→click that <button> provides, so we call .click()
4905
+ // directly when Enter is pressed on a button-like element.
4906
+ //
4907
+ // - Tab: NOT intercepted — left to the browser's native focus trap
4908
+ // provided by showModal(), which cycles Tab between focusable
4909
+ // elements inside the dialog (e.g. the input and close button).
4910
+ // Intercepting Tab would kill the native focus trap and break
4911
+ // focus management inside the dialog.
4912
+ //
4913
+ // - Escape: The native <dialog> fires a `cancel` event on ESC
4914
+ // (handled above), so the re-dispatched Escape is a secondary
4915
+ // path for parent components that also listen for Escape keydown.
4916
+ const navKeys = new Set([
4917
+ 'ArrowUp',
4918
+ 'ArrowDown',
4919
+ 'Enter',
4920
+ 'Escape'
4921
+ ]);
4894
4922
  dialog.addEventListener('keydown', (event) => {
4895
4923
  if (!navKeys.has(event.key)) {
4896
4924
  return;
4897
4925
  }
4926
+
4927
+ // Custom elements (auro-button) don't get the native Enter→click
4928
+ // behavior that <button> has. Find the button in the composed path
4929
+ // and click it directly.
4930
+ if (event.key === 'Enter') {
4931
+ const buttonSelector = 'button, [role="button"], auro-button, [auro-button]';
4932
+ const btn = event.composedPath().find((el) => el.matches && el.matches(buttonSelector));
4933
+ if (btn) {
4934
+ event.preventDefault();
4935
+ event.stopPropagation();
4936
+ btn.click();
4937
+ return;
4938
+ }
4939
+ }
4940
+
4898
4941
  event.preventDefault();
4899
4942
  event.stopPropagation();
4900
4943
  const newEvent = new KeyboardEvent('keydown', {
@@ -4918,9 +4961,55 @@ class AuroDropdownBib extends i$2 {
4918
4961
  }
4919
4962
 
4920
4963
  /**
4921
- * Opens the dialog using showModal() for accessibility.
4922
- * @param {boolean} modal - If true, uses showModal() (default). If false, uses show().
4964
+ * Blocks touch-driven page scroll while a fullscreen modal dialog is open.
4965
+ *
4966
+ * The showModal() function places the dialog in the browser's **top layer**,
4967
+ * which is a separate rendering layer above the normal DOM. On mobile, the
4968
+ * compositor processes visual-viewport panning before top-layer touch
4969
+ * handling. This means the entire viewport — including the top-layer dialog
4970
+ * — can be panned by a touch gesture, causing the page behind the dialog to
4971
+ * scroll into view. To prevent this, we add a touchmove listener that cancels
4972
+ * the event if the touch started outside the dialog or any scrollable child within it.
4973
+ *
4974
+ * @private
4923
4975
  */
4976
+ _lockTouchScroll() {
4977
+ const dialog = this.shadowRoot.querySelector('dialog');
4978
+
4979
+ this._touchMoveHandler = (event) => {
4980
+ // Walk the composed path (which crosses shadow DOM boundaries) to
4981
+ // check whether the touch started inside a scrollable element that
4982
+ // lives within the dialog. If so, allow the scroll.
4983
+ for (const el of event.composedPath()) {
4984
+ if (el === dialog) {
4985
+ // Reached the dialog boundary without finding a scrollable child.
4986
+ break;
4987
+ }
4988
+ if (el instanceof HTMLElement && el.scrollHeight > el.clientHeight) {
4989
+ const { overflowY } = getComputedStyle(el);
4990
+ if (overflowY === 'auto' || overflowY === 'scroll') {
4991
+ return;
4992
+ }
4993
+ }
4994
+ }
4995
+
4996
+ event.preventDefault();
4997
+ };
4998
+
4999
+ document.addEventListener('touchmove', this._touchMoveHandler, { passive: false });
5000
+ }
5001
+
5002
+ /**
5003
+ * Removes the touchmove listener added by _lockTouchScroll().
5004
+ * @private
5005
+ */
5006
+ _unlockTouchScroll() {
5007
+ if (this._touchMoveHandler) {
5008
+ document.removeEventListener('touchmove', this._touchMoveHandler);
5009
+ this._touchMoveHandler = undefined;
5010
+ }
5011
+ }
5012
+
4924
5013
  open(modal = true) {
4925
5014
  const dialog = this.shadowRoot.querySelector('dialog');
4926
5015
  if (dialog && !dialog.open) {
@@ -4937,6 +5026,8 @@ class AuroDropdownBib extends i$2 {
4937
5026
 
4938
5027
  documentElement.style.overflow = prevOverflow;
4939
5028
 
5029
+ this._lockTouchScroll();
5030
+
4940
5031
  } else {
4941
5032
  // Use setAttribute instead of dialog.show() to avoid the dialog
4942
5033
  // focusing steps which steal focus from the trigger and cause
@@ -4952,6 +5043,7 @@ class AuroDropdownBib extends i$2 {
4952
5043
  close() {
4953
5044
  const dialog = this.shadowRoot.querySelector('dialog');
4954
5045
  if (dialog && dialog.open) {
5046
+ this._unlockTouchScroll();
4955
5047
  dialog.close();
4956
5048
  }
4957
5049
  }
@@ -5217,7 +5309,7 @@ class AuroHelpText extends i$2 {
5217
5309
  }
5218
5310
  }
5219
5311
 
5220
- var formkitVersion = '202602201708';
5312
+ var formkitVersion = '202602260152';
5221
5313
 
5222
5314
  let AuroElement$1 = class AuroElement extends i$2 {
5223
5315
  static get properties() {
@@ -5490,6 +5582,18 @@ class AuroDropdown extends AuroElement$1 {
5490
5582
  */
5491
5583
  show() {
5492
5584
  this.floater.showBib();
5585
+
5586
+ // Open dialog synchronously so callers remain in the user gesture
5587
+ // chain. This is critical for mobile browsers (iOS Safari) to keep
5588
+ // the virtual keyboard open when transitioning from the trigger
5589
+ // input to an input inside the fullscreen dialog. Without this,
5590
+ // showModal() fires asynchronously via Lit's update cycle, which
5591
+ // falls outside the user activation window and causes iOS to
5592
+ // dismiss the keyboard.
5593
+ if (this.isBibFullscreen && this.bibElement && this.bibElement.value) {
5594
+ const useModal = !this.disableFocusTrap;
5595
+ this.bibElement.value.open(useModal);
5596
+ }
5493
5597
  }
5494
5598
 
5495
5599
  /**
@@ -5876,6 +5980,14 @@ class AuroDropdown extends AuroElement$1 {
5876
5980
  this.bibElement.value.close();
5877
5981
  }
5878
5982
  }
5983
+
5984
+ // When fullscreen strategy changes while open, re-open dialog with correct mode
5985
+ // (e.g. resizing from desktop → mobile while dropdown is open)
5986
+ if (changedProperties.has('isBibFullscreen') && this.isPopoverVisible && this.bibElement.value) {
5987
+ const useModal = this.isBibFullscreen && !this.disableFocusTrap;
5988
+ this.bibElement.value.close();
5989
+ this.bibElement.value.open(useModal);
5990
+ }
5879
5991
  }
5880
5992
 
5881
5993
  /**