@aurodesignsystem-dev/auro-formkit 0.0.0-pr1398.2 → 0.0.0-pr1398.3

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 (61) 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/demo/keyboardBehavior.md +0 -0
  4. package/components/checkbox/dist/index.js +1 -1
  5. package/components/checkbox/dist/registered.js +1 -1
  6. package/components/combobox/demo/api.min.js +129 -166
  7. package/components/combobox/demo/index.min.js +129 -166
  8. package/components/combobox/demo/keyboardBehavior.html +81 -0
  9. package/components/combobox/demo/keyboardBehavior.md +308 -0
  10. package/components/combobox/dist/index.js +87 -134
  11. package/components/combobox/dist/registered.js +87 -134
  12. package/components/counter/demo/api.min.js +157 -160
  13. package/components/counter/demo/index.min.js +157 -160
  14. package/components/counter/demo/keyboardBehavior.html +81 -0
  15. package/components/counter/demo/keyboardBehavior.md +127 -0
  16. package/components/counter/dist/auro-counter.d.ts +0 -7
  17. package/components/counter/dist/index.js +157 -160
  18. package/components/counter/dist/keyboardStrategy.d.ts +4 -0
  19. package/components/counter/dist/registered.js +157 -160
  20. package/components/datepicker/demo/api.min.js +89 -137
  21. package/components/datepicker/demo/index.min.js +89 -137
  22. package/components/datepicker/demo/keyboardBehavior.html +81 -0
  23. package/components/datepicker/demo/keyboardBehavior.md +24 -0
  24. package/components/datepicker/dist/index.js +84 -132
  25. package/components/datepicker/dist/registered.js +84 -132
  26. package/components/dropdown/demo/api.md +0 -1
  27. package/components/dropdown/demo/api.min.js +99 -140
  28. package/components/dropdown/demo/index.md +2 -2
  29. package/components/dropdown/demo/index.min.js +99 -140
  30. package/components/dropdown/demo/keyboardBehavior.html +81 -0
  31. package/components/dropdown/demo/keyboardBehavior.md +77 -0
  32. package/components/dropdown/dist/auro-dropdown.d.ts +0 -8
  33. package/components/dropdown/dist/auro-dropdownBib.d.ts +1 -50
  34. package/components/dropdown/dist/dropdownBibKeyboardStrategy.d.ts +7 -0
  35. package/components/dropdown/dist/index.js +83 -128
  36. package/components/dropdown/dist/registered.js +83 -128
  37. package/components/form/demo/api.min.js +466 -599
  38. package/components/form/demo/index.min.js +466 -599
  39. package/components/form/demo/keyboardBehavior.md +0 -0
  40. package/components/input/demo/api.min.js +1 -1
  41. package/components/input/demo/index.min.js +1 -1
  42. package/components/input/demo/keyboardBehavior.md +0 -0
  43. package/components/input/dist/index.js +1 -1
  44. package/components/input/dist/registered.js +1 -1
  45. package/components/menu/demo/api.min.js +42 -32
  46. package/components/menu/demo/index.min.js +42 -32
  47. package/components/menu/dist/auro-menu.d.ts +3 -11
  48. package/components/menu/dist/index.js +42 -32
  49. package/components/menu/dist/registered.js +42 -32
  50. package/components/radio/demo/api.min.js +1 -1
  51. package/components/radio/demo/index.min.js +1 -1
  52. package/components/radio/dist/index.js +1 -1
  53. package/components/radio/dist/registered.js +1 -1
  54. package/components/select/demo/api.min.js +132 -167
  55. package/components/select/demo/index.min.js +132 -167
  56. package/components/select/demo/keyboardBehavior.html +81 -0
  57. package/components/select/demo/keyboardBehavior.md +246 -0
  58. package/components/select/dist/index.js +90 -135
  59. package/components/select/dist/registered.js +90 -135
  60. package/custom-elements.json +61 -89
  61. package/package.json +2 -2
@@ -1184,6 +1184,57 @@ class IconUtil {
1184
1184
  }
1185
1185
  }
1186
1186
 
1187
+ /**
1188
+ * Computes display state once per keydown event.
1189
+ * Centralizes null-safety checks and makes the shared/modal/popover branching explicit.
1190
+ *
1191
+ * @param {HTMLElement} component - The component with a dropdown reference.
1192
+ * @param {Object} [options] - Optional config.
1193
+ * @param {HTMLElement} [options.dropdown] - Explicit dropdown reference. Falls back to component.dropdown.
1194
+ * @param {Function} [options.inputResolver] - Called with (component, ctx) to resolve the active input element.
1195
+ * @returns {{isExpanded: boolean, isModal: boolean, isPopover: boolean, activeInput: HTMLElement|null}}
1196
+ * isModal and isPopover reflect the display mode (fullscreen vs not) regardless of expanded state.
1197
+ */
1198
+ function createDisplayContext$1(component, options = {}) {
1199
+ const dd = options.dropdown || component.dropdown;
1200
+ // isPopoverVisible reflects as the `open` attribute.
1201
+ // It reports whether the bib is open in any mode (popover or modal).
1202
+ const isExpanded = Boolean(dd && dd.isPopoverVisible);
1203
+ const isFullscreen = Boolean(dd && dd.isBibFullscreen);
1204
+
1205
+ const ctx = {
1206
+ isExpanded,
1207
+ isModal: isFullscreen,
1208
+ isPopover: !isFullscreen,
1209
+ activeInput: null,
1210
+ };
1211
+
1212
+ if (options.inputResolver) {
1213
+ const resolvedInput = options.inputResolver(component, ctx);
1214
+ // Guard against resolvers returning undefined or non-HTMLElement values.
1215
+ ctx.activeInput = resolvedInput instanceof HTMLElement ? resolvedInput : null;
1216
+ }
1217
+
1218
+ return ctx;
1219
+ }
1220
+
1221
+ /**
1222
+ * Wires up a keydown listener that dispatches to strategy[evt.key] or strategy.default.
1223
+ * Handles both sync and async handlers.
1224
+ * @param {HTMLElement} component - The component to attach the listener to.
1225
+ * @param {Object} strategy - Map of key names to handler functions.
1226
+ * @param {Object} [options] - Optional config passed to createDisplayContext.
1227
+ */
1228
+ function applyKeyboardStrategy$1(component, strategy, options = {}) {
1229
+ component.addEventListener('keydown', async (evt) => {
1230
+ const handler = strategy[evt.key] || strategy.default;
1231
+ if (typeof handler === 'function') {
1232
+ const ctx = createDisplayContext$1(component, options);
1233
+ await handler(component, evt, ctx);
1234
+ }
1235
+ });
1236
+ }
1237
+
1187
1238
  var plusIcon = {"role":"img","color":"currentColor","title":"","desc":"","width":"var(--auro-size-lg, var(--ds-size-300, 1.5rem))","height":"var(--auro-size-lg, var(--ds-size-300, 1.5rem))","xmlns":"http://www.w3.org/2000/svg","xmlns_xlink":"http://www.w3.org/1999/xlink","viewBox":"0 0 24 24","path":"/icons","style":"ico_squareLarge","type":"icon","name":"plus-lg","category":"interface","svg":"<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" aria-hidden=\"true\" class=\"ico_squareLarge\" role=\"img\" style=\"min-width:var(--auro-size-lg, var(--ds-size-300, 1.5rem));height:var(--auro-size-lg, var(--ds-size-300, 1.5rem));fill:currentColor\" viewBox=\"0 0 24 24\" part=\"svg\"><title/><path d=\"M11.898 5.007 12 5a.75.75 0 0 1 .743.648l.007.102v5.5h5.5a.75.75 0 0 1 .743.648L19 12a.75.75 0 0 1-.648.743l-.102.007h-5.501l.001 5.5a.75.75 0 0 1-.648.743L12 19a.75.75 0 0 1-.743-.648l-.007-.102-.001-5.5H5.75a.75.75 0 0 1-.743-.648L5 12a.75.75 0 0 1 .648-.743l.102-.007h5.5v-5.5a.75.75 0 0 1 .648-.743L12 5z\"/></svg>"};
1188
1239
 
1189
1240
  var minusIcon = {"role":"img","color":"currentColor","title":"","desc":"","width":"var(--auro-size-lg, var(--ds-size-300, 1.5rem))","height":"var(--auro-size-lg, var(--ds-size-300, 1.5rem))","xmlns":"http://www.w3.org/2000/svg","xmlns_xlink":"http://www.w3.org/1999/xlink","viewBox":"0 0 24 24","path":"/icons","style":"ico_squareLarge","type":"icon","name":"minus-lg","category":"interface","deprecated":true,"svg":"<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" aria-hidden=\"true\" class=\"ico_squareLarge\" data-deprecated=\"true\" role=\"img\" style=\"min-width:var(--auro-size-lg, var(--ds-size-300, 1.5rem));height:var(--auro-size-lg, var(--ds-size-300, 1.5rem));fill:currentColor\" viewBox=\"0 0 24 24\" part=\"svg\"><title/><path d=\"M5.75 12.75h12.5a.75.75 0 1 0 0-1.5H5.75a.75.75 0 1 0 0 1.5\"/></svg>"};
@@ -1420,7 +1471,30 @@ let AuroHelpText$1 = class AuroHelpText extends LitElement {
1420
1471
  }
1421
1472
  };
1422
1473
 
1423
- var formkitVersion$1 = '202603271519';
1474
+ var formkitVersion$1 = '202604012043';
1475
+
1476
+ // Copyright (c) 2026 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
1477
+ // See LICENSE in the project root for license information.
1478
+
1479
+ const keyboardStrategy = {
1480
+ ArrowUp(component, _evt) {
1481
+ if (component.disabled) {
1482
+ return;
1483
+ }
1484
+
1485
+ _evt.preventDefault();
1486
+ component.increment();
1487
+ },
1488
+
1489
+ ArrowDown(component, _evt) {
1490
+ if (component.disabled) {
1491
+ return;
1492
+ }
1493
+
1494
+ _evt.preventDefault();
1495
+ component.decrement();
1496
+ }
1497
+ };
1424
1498
 
1425
1499
  // Copyright (c) 2025 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
1426
1500
  // See LICENSE in the project root for license information.
@@ -1494,11 +1568,10 @@ class AuroCounter extends LitElement {
1494
1568
 
1495
1569
  connectedCallback() {
1496
1570
  super.connectedCallback();
1497
- this.addEventListener('keydown', this.handleKeyDown);
1571
+ applyKeyboardStrategy$1(this, keyboardStrategy);
1498
1572
  }
1499
1573
 
1500
1574
  disconnectedCallback() {
1501
- this.removeEventListener('keydown', this.handleKeyDown);
1502
1575
  super.disconnectedCallback();
1503
1576
  }
1504
1577
 
@@ -1709,29 +1782,6 @@ class AuroCounter extends LitElement {
1709
1782
  this.validation.validate(this, force);
1710
1783
  }
1711
1784
 
1712
- /**
1713
- * Handles the keydown event for the counter component.
1714
- * @param {KeyboardEvent} event - The keyboard event object.
1715
- * @returns {void}
1716
- * @private
1717
- */
1718
- handleKeyDown(event) {
1719
- if (this.disabled) {
1720
- return;
1721
- }
1722
-
1723
- switch (event.key) {
1724
- case 'ArrowUp':
1725
- event.preventDefault();
1726
- this.increment();
1727
- break;
1728
- case 'ArrowDown':
1729
- event.preventDefault();
1730
- this.decrement();
1731
- break;
1732
- }
1733
- }
1734
-
1735
1785
  firstUpdated() {
1736
1786
  this.initValue();
1737
1787
  this.setTagAttribute("auro-counter");
@@ -3934,11 +3984,10 @@ class AuroFloatingUI {
3934
3984
  return;
3935
3985
  }
3936
3986
 
3937
- const { activeElement } = document;
3938
3987
  // if focus is still inside of trigger or bib, do not close
3939
3988
  if (
3940
- this.element.contains(activeElement) ||
3941
- this.element.bib?.contains(activeElement)
3989
+ this.element.matches(":focus") ||
3990
+ this.element.matches(":focus-within")
3942
3991
  ) {
3943
3992
  return;
3944
3993
  }
@@ -4777,12 +4826,83 @@ let p$2 = class p{registerComponent(t,a){customElements.get(t)||customElements.d
4777
4826
 
4778
4827
  var iconVersion$1 = '9.1.2';
4779
4828
 
4829
+ /**
4830
+ * Computes display state once per keydown event.
4831
+ * Centralizes null-safety checks and makes the shared/modal/popover branching explicit.
4832
+ *
4833
+ * @param {HTMLElement} component - The component with a dropdown reference.
4834
+ * @param {Object} [options] - Optional config.
4835
+ * @param {HTMLElement} [options.dropdown] - Explicit dropdown reference. Falls back to component.dropdown.
4836
+ * @param {Function} [options.inputResolver] - Called with (component, ctx) to resolve the active input element.
4837
+ * @returns {{isExpanded: boolean, isModal: boolean, isPopover: boolean, activeInput: HTMLElement|null}}
4838
+ * isModal and isPopover reflect the display mode (fullscreen vs not) regardless of expanded state.
4839
+ */
4840
+ function createDisplayContext(component, options = {}) {
4841
+ const dd = options.dropdown || component.dropdown;
4842
+ // isPopoverVisible reflects as the `open` attribute.
4843
+ // It reports whether the bib is open in any mode (popover or modal).
4844
+ const isExpanded = Boolean(dd && dd.isPopoverVisible);
4845
+ const isFullscreen = Boolean(dd && dd.isBibFullscreen);
4846
+
4847
+ const ctx = {
4848
+ isExpanded,
4849
+ isModal: isFullscreen,
4850
+ isPopover: !isFullscreen,
4851
+ activeInput: null,
4852
+ };
4853
+
4854
+ if (options.inputResolver) {
4855
+ const resolvedInput = options.inputResolver(component, ctx);
4856
+ // Guard against resolvers returning undefined or non-HTMLElement values.
4857
+ ctx.activeInput = resolvedInput instanceof HTMLElement ? resolvedInput : null;
4858
+ }
4859
+
4860
+ return ctx;
4861
+ }
4862
+
4863
+ /**
4864
+ * Wires up a keydown listener that dispatches to strategy[evt.key] or strategy.default.
4865
+ * Handles both sync and async handlers.
4866
+ * @param {HTMLElement} component - The component to attach the listener to.
4867
+ * @param {Object} strategy - Map of key names to handler functions.
4868
+ * @param {Object} [options] - Optional config passed to createDisplayContext.
4869
+ */
4870
+ function applyKeyboardStrategy(component, strategy, options = {}) {
4871
+ component.addEventListener('keydown', async (evt) => {
4872
+ const handler = strategy[evt.key] || strategy.default;
4873
+ if (typeof handler === 'function') {
4874
+ const ctx = createDisplayContext(component, options);
4875
+ await handler(component, evt, ctx);
4876
+ }
4877
+ });
4878
+ }
4879
+
4780
4880
  var styleCss$2 = 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}`;
4781
4881
 
4782
4882
  var colorCss$2 = 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)}`;
4783
4883
 
4784
4884
  var tokensCss$1 = css`:host(:not([ondark])),:host(:not([appearance=inverse])){--ds-auro-dropdown-label-text-color: var(--ds-basic-color-texticon-muted, #676767);--ds-auro-dropdown-trigger-background-color: var(--ds-basic-color-surface-default, #ffffff);--ds-auro-dropdown-trigger-hover-background-color: var(--ds-basic-color-surface-default, #ffffff);--ds-auro-dropdown-trigger-container-color: var(--ds-basic-color-surface-default, #ffffff);--ds-auro-dropdown-trigger-border-color: var(--ds-basic-color-border-bold, #585e67);--ds-auro-dropdown-trigger-outline-color: transparent;--ds-auro-dropdown-trigger-text-color: var(--ds-basic-color-texticon-default, #2a2a2a);--ds-auro-dropdownbib-boxshadow-color: var(--ds-elevation-200, 0px 0px 10px rgba(0, 0, 0, 0.15));--ds-auro-dropdownbib-background-color: var(--ds-basic-color-surface-default, #ffffff);--ds-auro-dropdownbib-container-color: var(--ds-basic-color-surface-default, #ffffff);--ds-auro-dropdownbib-text-color: var(--ds-basic-color-texticon-default, #2a2a2a)}:host([ondark]),:host([appearance=inverse]){--ds-auro-dropdown-label-text-color: var(--ds-basic-color-texticon-inverse-muted, #ccd2db);--ds-auro-dropdown-trigger-background-color: var(--ds-advanced-color-shared-background-inverse, rgba(255, 255, 255, 0.15));--ds-auro-dropdown-trigger-hover-background-color: var(--ds-advanced-color-shared-background-inverse, rgba(255, 255, 255, 0.15));--ds-auro-dropdown-trigger-container-color: var(--ds-advanced-color-shared-background-inverse, rgba(255, 255, 255, 0.15));--ds-auro-dropdown-trigger-border-color: var(--ds-basic-color-border-inverse, #ffffff);--ds-auro-dropdown-trigger-outline-color: transparent;--ds-auro-dropdown-trigger-text-color: var(--ds-basic-color-texticon-inverse, #ffffff);--ds-auro-dropdownbib-boxshadow-color: var(--ds-elevation-200, 0px 0px 10px rgba(0, 0, 0, 0.15));--ds-auro-dropdownbib-background-color: var(--ds-advanced-color-shared-background-inverse, rgba(255, 255, 255, 0.15));--ds-auro-dropdownbib-container-color: var(--ds-advanced-color-shared-background-inverse, rgba(255, 255, 255, 0.15));--ds-auro-dropdownbib-text-color: var(--ds-basic-color-texticon-inverse, #ffffff)}`;
4785
4885
 
4886
+ /**
4887
+ * Creates a keyboard strategy for dialog-specific key handling.
4888
+ * All other keydown behavior is left to the browser's native bubbling path.
4889
+ * @param {HTMLElement} bib - The dropdown bib element.
4890
+ * @returns {Object} Keyboard handlers keyed by `event.key`.
4891
+ */
4892
+ // eslint-disable-next-line no-unused-vars
4893
+ function createDropdownBibKeyboardStrategy(bib) {
4894
+ return {
4895
+ // eslint-disable-next-line no-unused-vars
4896
+ Enter(_dialog, event) {
4897
+ // Floating UI handles Enter key to open the dropdown
4898
+ },
4899
+ // eslint-disable-next-line no-unused-vars
4900
+ Escape(_dialog, event) {
4901
+ // Floating UI handles Escape key to close the dropdown
4902
+ }
4903
+ };
4904
+ }
4905
+
4786
4906
  // Copyright (c) 2020 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
4787
4907
  // See LICENSE in the project root for license information.
4788
4908
  /* eslint-disable max-lines */
@@ -4907,26 +5027,11 @@ class AuroDropdownBib extends LitElement {
4907
5027
  },
4908
5028
 
4909
5029
  /**
4910
- * Set by auro-dropdown when a menu option is highlighted via
4911
- * aria-activedescendant. The dialog keyboard bridge checks this
4912
- * flag so that Enter selects the highlighted option instead of
4913
- * activating the focused interactive element (e.g. the trigger
4914
- * button, or the bibtemplate close button in fullscreen).
5030
+ * Tracks whether a menu option is currently highlighted.
4915
5031
  * @private
4916
5032
  */
4917
5033
  hasActiveDescendant: {
4918
5034
  type: Boolean
4919
- },
4920
-
4921
- /**
4922
- * When true, the keyboard bridge allows native Tab behavior
4923
- * instead of intercepting it. Set this for bib consumers
4924
- * (e.g. counter) whose content contains real focusable elements
4925
- * that need native Tab navigation.
4926
- * @private
4927
- */
4928
- nativeFocusableContent: {
4929
- type: Boolean
4930
5035
  }
4931
5036
  };
4932
5037
  }
@@ -4996,7 +5101,7 @@ class AuroDropdownBib extends LitElement {
4996
5101
 
4997
5102
  const dialog = this.shadowRoot.querySelector('dialog');
4998
5103
  this._setupCancelHandler(dialog);
4999
- this._setupKeyboardBridge(dialog);
5104
+ applyKeyboardStrategy(dialog, createDropdownBibKeyboardStrategy());
5000
5105
 
5001
5106
  this.dispatchEvent(new CustomEvent('auro-dropdownbib-connected', {
5002
5107
  bubbles: true,
@@ -5023,98 +5128,6 @@ class AuroDropdownBib extends LitElement {
5023
5128
  });
5024
5129
  }
5025
5130
 
5026
- /**
5027
- * showModal() creates a closed focus scope — keyboard events inside
5028
- * the dialog's shadow DOM do NOT bubble out to the combobox/select
5029
- * keydown handlers in the parent shadow DOM. This handler bridges
5030
- * that gap by re-dispatching navigation keys so they cross the
5031
- * shadow boundary and reach the menu navigation logic in the parent
5032
- * component.
5033
- *
5034
- * The trade-off: intercepting these keys means native keyboard
5035
- * behaviors that would normally "just work" must be manually
5036
- * re-implemented here:
5037
- *
5038
- * - Enter on buttons: Custom elements (auro-button) don't get the
5039
- * native Enter→click that <button> provides, so we call .click()
5040
- * directly when Enter is pressed on a button-like element.
5041
- *
5042
- * - Tab: Intercepted and re-dispatched so parent components
5043
- * (select/combobox) can select the active option and close the
5044
- * dialog. The <dialog> provides containment and isolation
5045
- * (inert background, VoiceOver focus trapping, top layer), while
5046
- * the content inside is a role="listbox" navigated via
5047
- * aria-activedescendant (options are not focusable). Tab keyboard
5048
- * behavior follows listbox conventions (select + close) because
5049
- * the dialog's native Tab trap only cycles between the close
5050
- * button and browser chrome.
5051
- *
5052
- * - Escape: The native <dialog> fires a `cancel` event on ESC
5053
- * (handled by _setupCancelHandler), so the re-dispatched Escape
5054
- * is a secondary path for parent components that also listen for
5055
- * Escape keydown.
5056
- *
5057
- * @param {HTMLDialogElement} dialog - The dialog element to attach the keyboard bridge to.
5058
- * @private
5059
- */
5060
- _setupKeyboardBridge(dialog) {
5061
- const navKeys = new Set([
5062
- 'ArrowUp',
5063
- 'ArrowDown',
5064
- 'Enter',
5065
- 'Escape',
5066
- 'Tab'
5067
- ]);
5068
-
5069
- dialog.addEventListener('keydown', (event) => {
5070
- if (!navKeys.has(event.key)) {
5071
- return;
5072
- }
5073
-
5074
- // Custom elements (auro-button) don't get the native Enter→click
5075
- // behavior that <button> has. Find the button in the composed path
5076
- // and click it directly — but only when no menu option is
5077
- // highlighted. In fullscreen mode focus stays on the close button
5078
- // while arrow keys move the active-descendant highlight through
5079
- // the listbox. If the user presses Enter with an option
5080
- // highlighted, the intent is to select that option, not to click
5081
- // the close button. In that case we fall through and bridge the
5082
- // Enter key to the parent component's keyboard strategy.
5083
- if (event.key === 'Enter') {
5084
- if (!this.hasActiveDescendant) {
5085
- const buttonSelector = 'button, [role="button"], auro-button, [auro-button]';
5086
- const btn = event.composedPath().find((el) => el.matches && el.matches(buttonSelector));
5087
- if (btn) {
5088
- event.preventDefault();
5089
- event.stopPropagation();
5090
- btn.click();
5091
- return;
5092
- }
5093
- }
5094
- }
5095
-
5096
- // Allow native Tab when the bib contains focusable content
5097
- // (e.g. counter buttons) that needs normal Tab navigation.
5098
- if (event.key === 'Tab' && this.nativeFocusableContent) {
5099
- return;
5100
- }
5101
-
5102
- event.preventDefault();
5103
- event.stopPropagation();
5104
- const newEvent = new KeyboardEvent('keydown', {
5105
- key: event.key,
5106
- code: event.code,
5107
- shiftKey: event.shiftKey,
5108
- altKey: event.altKey,
5109
- ctrlKey: event.ctrlKey,
5110
- metaKey: event.metaKey,
5111
- bubbles: true,
5112
- composed: true,
5113
- cancelable: true
5114
- });
5115
- this.dispatchEvent(newEvent);
5116
- });
5117
- }
5118
5131
 
5119
5132
  /**
5120
5133
  * Blocks touch-driven page scroll while a fullscreen modal dialog is open.
@@ -5489,7 +5502,7 @@ class AuroHelpText extends LitElement {
5489
5502
  }
5490
5503
  }
5491
5504
 
5492
- var formkitVersion = '202603271519';
5505
+ var formkitVersion = '202604012043';
5493
5506
 
5494
5507
  let AuroElement$1 = class AuroElement extends LitElement {
5495
5508
  static get properties() {
@@ -5670,7 +5683,6 @@ class AuroDropdown extends AuroElement$1 {
5670
5683
  this.appearance = 'default';
5671
5684
  this.chevron = false;
5672
5685
  this.disabled = false;
5673
- this.disableFocusTrap = false;
5674
5686
  this.error = false;
5675
5687
  this.tabIndex = 0;
5676
5688
  this.noToggle = false;
@@ -5768,9 +5780,8 @@ class AuroDropdown extends AuroElement$1 {
5768
5780
  // showModal() fires asynchronously via Lit's update cycle, which
5769
5781
  // falls outside the user activation window and causes iOS to
5770
5782
  // dismiss the keyboard.
5771
- if (this.isBibFullscreen && this.bibElement && this.bibElement.value) {
5772
- const useModal = !this.disableFocusTrap;
5773
- this.bibElement.value.open(useModal);
5783
+ if (this.bibElement && this.bibElement.value) {
5784
+ this.bibElement.value.open(this.isBibFullscreen);
5774
5785
  }
5775
5786
  }
5776
5787
 
@@ -5883,14 +5894,6 @@ class AuroDropdown extends AuroElement$1 {
5883
5894
  reflect: true
5884
5895
  },
5885
5896
 
5886
- /**
5887
- * If declared, the focus trap inside of bib will be turned off.
5888
- */
5889
- disableFocusTrap: {
5890
- type: Boolean,
5891
- reflect: true
5892
- },
5893
-
5894
5897
  /**
5895
5898
  * @private
5896
5899
  */
@@ -6164,7 +6167,7 @@ class AuroDropdown extends AuroElement$1 {
6164
6167
  if (this.isPopoverVisible) {
6165
6168
  // Fullscreen: use showModal() for native accessibility (inert outside, focus trap)
6166
6169
  // Desktop: use show() for Floating UI positioning + FocusTrap for focus management
6167
- const useModal = this.isBibFullscreen && !this.disableFocusTrap;
6170
+ const useModal = this.isBibFullscreen;
6168
6171
  this.bibElement.value.open(useModal);
6169
6172
  } else {
6170
6173
  this.bibElement.value.close();
@@ -6174,7 +6177,7 @@ class AuroDropdown extends AuroElement$1 {
6174
6177
  // When fullscreen strategy changes while open, re-open dialog with correct mode
6175
6178
  // (e.g. resizing from desktop → mobile while dropdown is open)
6176
6179
  if (changedProperties.has('isBibFullscreen') && this.isPopoverVisible && this.bibElement.value) {
6177
- const useModal = this.isBibFullscreen && !this.disableFocusTrap;
6180
+ const useModal = this.isBibFullscreen;
6178
6181
  this.bibElement.value.close();
6179
6182
  this.bibElement.value.open(useModal);
6180
6183
  }
@@ -6286,7 +6289,7 @@ class AuroDropdown extends AuroElement$1 {
6286
6289
  * @private
6287
6290
  */
6288
6291
  updateFocusTrap() {
6289
- if (this.isPopoverVisible && !this.disableFocusTrap) {
6292
+ if (this.isPopoverVisible) {
6290
6293
  if (!this.isBibFullscreen) {
6291
6294
  // Desktop: show() doesn't trap focus, so use FocusTrap
6292
6295
  this.focusTrap = new FocusTrap(this.bibContent);
@@ -7638,11 +7641,6 @@ class AuroCounterGroup extends AuroElement {
7638
7641
 
7639
7642
  // Focus close button when fullscreen dialog opens
7640
7643
  this.dropdown.addEventListener('auroDropdown-toggled', () => {
7641
- // Tell the bib's keyboard bridge to allow native Tab so focus
7642
- // moves between the real focusable counter elements in the bib.
7643
- if (this.dropdown.bibContent) {
7644
- this.dropdown.bibContent.nativeFocusableContent = true;
7645
- }
7646
7644
  if (this.dropdown.isPopoverVisible && this.dropdown.isBibFullscreen) {
7647
7645
  doubleRaf(() => {
7648
7646
  this.bibtemplate.focusCloseButton();
@@ -7839,7 +7837,6 @@ class AuroCounterGroup extends AuroElement {
7839
7837
  renderCounterDropdown() {
7840
7838
  return html`
7841
7839
  <${this.dropdownTag}
7842
- noHideOnThisFocusLoss
7843
7840
  chevron
7844
7841
  part="dropdown"
7845
7842
  appearance="${this.onDark ? 'inverse' : this.appearance}"