@aurodesignsystem-dev/auro-formkit 0.0.0-pr1408.8 → 0.0.0-pr1411.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 (62) 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 +121 -144
  7. package/components/combobox/demo/index.min.js +121 -144
  8. package/components/combobox/demo/keyboardBehavior.html +1 -0
  9. package/components/combobox/demo/keyboardBehavior.md +21 -22
  10. package/components/combobox/dist/index.js +87 -117
  11. package/components/combobox/dist/registered.js +87 -117
  12. package/components/counter/demo/api.md +1 -1
  13. package/components/counter/demo/api.min.js +184 -148
  14. package/components/counter/demo/index.min.js +184 -148
  15. package/components/counter/demo/keyboardBehavior.html +1 -0
  16. package/components/counter/demo/keyboardBehavior.md +1 -1
  17. package/components/counter/dist/auro-counter.d.ts +11 -8
  18. package/components/counter/dist/index.js +184 -148
  19. package/components/counter/dist/keyboardStrategy.d.ts +4 -0
  20. package/components/counter/dist/registered.js +184 -148
  21. package/components/datepicker/demo/api.min.js +89 -120
  22. package/components/datepicker/demo/index.min.js +89 -120
  23. package/components/datepicker/demo/keyboardBehavior.html +1 -0
  24. package/components/datepicker/demo/keyboardBehavior.md +14 -13
  25. package/components/datepicker/dist/index.js +84 -115
  26. package/components/datepicker/dist/registered.js +84 -115
  27. package/components/dropdown/demo/api.md +0 -1
  28. package/components/dropdown/demo/api.min.js +99 -123
  29. package/components/dropdown/demo/index.md +2 -2
  30. package/components/dropdown/demo/index.min.js +99 -123
  31. package/components/dropdown/demo/keyboardBehavior.html +1 -0
  32. package/components/dropdown/dist/auro-dropdown.d.ts +0 -8
  33. package/components/dropdown/dist/auro-dropdownBib.d.ts +1 -40
  34. package/components/dropdown/dist/dropdownBibKeyboardStrategy.d.ts +7 -0
  35. package/components/dropdown/dist/index.js +83 -111
  36. package/components/dropdown/dist/registered.js +83 -111
  37. package/components/form/demo/api.min.js +542 -564
  38. package/components/form/demo/index.min.js +542 -564
  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 +34 -27
  46. package/components/menu/demo/index.min.js +34 -27
  47. package/components/menu/dist/auro-menu.d.ts +0 -6
  48. package/components/menu/dist/index.js +34 -27
  49. package/components/menu/dist/registered.js +34 -27
  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 +181 -178
  55. package/components/select/demo/index.min.js +181 -178
  56. package/components/select/demo/keyboardBehavior.html +1 -0
  57. package/components/select/demo/keyboardBehavior.md +240 -239
  58. package/components/select/dist/index.js +147 -151
  59. package/components/select/dist/registered.js +147 -151
  60. package/components/select/dist/selectKeyboardStrategy.d.ts +3 -1
  61. package/custom-elements.json +1521 -1503
  62. package/package.json +5 -3
@@ -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 = '202603310455';
1474
+ var formkitVersion$1 = '202604021512';
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,14 +1568,36 @@ 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
 
1578
+ /**
1579
+ * Gets the current value of the counter.
1580
+ * @returns {number|undefined} The current value of the counter, or undefined if the value is not set or invalid.
1581
+ */
1582
+ get value() {
1583
+ return this._value;
1584
+ }
1585
+
1586
+ /**
1587
+ * Sets the value of the counter. If the provided value is undefined, null, or cannot be converted to a number, the internal value will be set to undefined.
1588
+ * @param {number|string|undefined|null} val - The value to set for the counter. Can be a number, a string that can be converted to a number, undefined, or null.
1589
+ */
1590
+ set value(val) {
1591
+ const old = this._value;
1592
+ if (val === undefined || val === null) {
1593
+ this._value = undefined;
1594
+ } else {
1595
+ const num = Number(val);
1596
+ this._value = Number.isNaN(num) ? undefined : num;
1597
+ }
1598
+ this.requestUpdate('value', old);
1599
+ }
1600
+
1505
1601
  /**
1506
1602
  * Defines reactive properties for the component.
1507
1603
  * @returns {Object} Property configuration.
@@ -1686,29 +1782,6 @@ class AuroCounter extends LitElement {
1686
1782
  this.validation.validate(this, force);
1687
1783
  }
1688
1784
 
1689
- /**
1690
- * Handles the keydown event for the counter component.
1691
- * @param {KeyboardEvent} event - The keyboard event object.
1692
- * @returns {void}
1693
- * @private
1694
- */
1695
- handleKeyDown(event) {
1696
- if (this.disabled) {
1697
- return;
1698
- }
1699
-
1700
- switch (event.key) {
1701
- case 'ArrowUp':
1702
- event.preventDefault();
1703
- this.increment();
1704
- break;
1705
- case 'ArrowDown':
1706
- event.preventDefault();
1707
- this.decrement();
1708
- break;
1709
- }
1710
- }
1711
-
1712
1785
  firstUpdated() {
1713
1786
  this.initValue();
1714
1787
  this.setTagAttribute("auro-counter");
@@ -3911,11 +3984,10 @@ class AuroFloatingUI {
3911
3984
  return;
3912
3985
  }
3913
3986
 
3914
- const { activeElement } = document;
3915
3987
  // if focus is still inside of trigger or bib, do not close
3916
3988
  if (
3917
- this.element.contains(activeElement) ||
3918
- this.element.bib?.contains(activeElement)
3989
+ this.element.matches(":focus") ||
3990
+ this.element.matches(":focus-within")
3919
3991
  ) {
3920
3992
  return;
3921
3993
  }
@@ -4754,12 +4826,83 @@ let p$2 = class p{registerComponent(t,a){customElements.get(t)||customElements.d
4754
4826
 
4755
4827
  var iconVersion$1 = '9.1.2';
4756
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
+
4757
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}`;
4758
4881
 
4759
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)}`;
4760
4883
 
4761
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)}`;
4762
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
+
4763
4906
  // Copyright (c) 2020 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
4764
4907
  // See LICENSE in the project root for license information.
4765
4908
  /* eslint-disable max-lines */
@@ -4884,11 +5027,7 @@ class AuroDropdownBib extends LitElement {
4884
5027
  },
4885
5028
 
4886
5029
  /**
4887
- * Set by auro-dropdown when a menu option is highlighted via
4888
- * aria-activedescendant. The dialog keyboard bridge checks this
4889
- * flag so that Enter selects the highlighted option instead of
4890
- * activating the focused interactive element (e.g. the trigger
4891
- * button, or the bibtemplate close button in fullscreen).
5030
+ * Tracks whether a menu option is currently highlighted.
4892
5031
  * @private
4893
5032
  */
4894
5033
  hasActiveDescendant: {
@@ -4962,7 +5101,7 @@ class AuroDropdownBib extends LitElement {
4962
5101
 
4963
5102
  const dialog = this.shadowRoot.querySelector('dialog');
4964
5103
  this._setupCancelHandler(dialog);
4965
- this._setupKeyboardBridge(dialog);
5104
+ applyKeyboardStrategy(dialog, createDropdownBibKeyboardStrategy());
4966
5105
 
4967
5106
  this.dispatchEvent(new CustomEvent('auro-dropdownbib-connected', {
4968
5107
  bubbles: true,
@@ -4989,92 +5128,6 @@ class AuroDropdownBib extends LitElement {
4989
5128
  });
4990
5129
  }
4991
5130
 
4992
- /**
4993
- * showModal() creates a closed focus scope — keyboard events inside
4994
- * the dialog's shadow DOM do NOT bubble out to the combobox/select
4995
- * keydown handlers in the parent shadow DOM. This handler bridges
4996
- * that gap by re-dispatching navigation keys so they cross the
4997
- * shadow boundary and reach the menu navigation logic in the parent
4998
- * component.
4999
- *
5000
- * The trade-off: intercepting these keys means native keyboard
5001
- * behaviors that would normally "just work" must be manually
5002
- * re-implemented here:
5003
- *
5004
- * - Enter on buttons: Custom elements (auro-button) don't get the
5005
- * native Enter→click that <button> provides, so we call .click()
5006
- * directly when Enter is pressed on a button-like element.
5007
- *
5008
- * - Tab: Intercepted and re-dispatched so parent components
5009
- * (select/combobox) can select the active option and close the
5010
- * dialog. The <dialog> provides containment and isolation
5011
- * (inert background, VoiceOver focus trapping, top layer), while
5012
- * the content inside is a role="listbox" navigated via
5013
- * aria-activedescendant (options are not focusable). Tab keyboard
5014
- * behavior follows listbox conventions (select + close) because
5015
- * the dialog's native Tab trap only cycles between the close
5016
- * button and browser chrome.
5017
- *
5018
- * - Escape: The native <dialog> fires a `cancel` event on ESC
5019
- * (handled by _setupCancelHandler), so the re-dispatched Escape
5020
- * is a secondary path for parent components that also listen for
5021
- * Escape keydown.
5022
- *
5023
- * @param {HTMLDialogElement} dialog - The dialog element to attach the keyboard bridge to.
5024
- * @private
5025
- */
5026
- _setupKeyboardBridge(dialog) {
5027
- const navKeys = new Set([
5028
- 'ArrowUp',
5029
- 'ArrowDown',
5030
- 'Enter',
5031
- 'Escape',
5032
- 'Tab'
5033
- ]);
5034
-
5035
- dialog.addEventListener('keydown', (event) => {
5036
- if (!navKeys.has(event.key)) {
5037
- return;
5038
- }
5039
-
5040
- // Custom elements (auro-button) don't get the native Enter→click
5041
- // behavior that <button> has. Find the button in the composed path
5042
- // and click it directly — but only when no menu option is
5043
- // highlighted. In fullscreen mode focus stays on the close button
5044
- // while arrow keys move the active-descendant highlight through
5045
- // the listbox. If the user presses Enter with an option
5046
- // highlighted, the intent is to select that option, not to click
5047
- // the close button. In that case we fall through and bridge the
5048
- // Enter key to the parent component's keyboard strategy.
5049
- if (event.key === 'Enter') {
5050
- if (!this.hasActiveDescendant) {
5051
- const buttonSelector = 'button, [role="button"], auro-button, [auro-button]';
5052
- const btn = event.composedPath().find((el) => el.matches && el.matches(buttonSelector));
5053
- if (btn) {
5054
- event.preventDefault();
5055
- event.stopPropagation();
5056
- btn.click();
5057
- return;
5058
- }
5059
- }
5060
- }
5061
-
5062
- event.preventDefault();
5063
- event.stopPropagation();
5064
- const newEvent = new KeyboardEvent('keydown', {
5065
- key: event.key,
5066
- code: event.code,
5067
- shiftKey: event.shiftKey,
5068
- altKey: event.altKey,
5069
- ctrlKey: event.ctrlKey,
5070
- metaKey: event.metaKey,
5071
- bubbles: true,
5072
- composed: true,
5073
- cancelable: true
5074
- });
5075
- this.dispatchEvent(newEvent);
5076
- });
5077
- }
5078
5131
 
5079
5132
  /**
5080
5133
  * Blocks touch-driven page scroll while a fullscreen modal dialog is open.
@@ -5449,7 +5502,7 @@ class AuroHelpText extends LitElement {
5449
5502
  }
5450
5503
  }
5451
5504
 
5452
- var formkitVersion = '202603310455';
5505
+ var formkitVersion = '202604021512';
5453
5506
 
5454
5507
  let AuroElement$1 = class AuroElement extends LitElement {
5455
5508
  static get properties() {
@@ -5630,7 +5683,6 @@ class AuroDropdown extends AuroElement$1 {
5630
5683
  this.appearance = 'default';
5631
5684
  this.chevron = false;
5632
5685
  this.disabled = false;
5633
- this.disableFocusTrap = false;
5634
5686
  this.error = false;
5635
5687
  this.tabIndex = 0;
5636
5688
  this.noToggle = false;
@@ -5728,9 +5780,8 @@ class AuroDropdown extends AuroElement$1 {
5728
5780
  // showModal() fires asynchronously via Lit's update cycle, which
5729
5781
  // falls outside the user activation window and causes iOS to
5730
5782
  // dismiss the keyboard.
5731
- if (this.isBibFullscreen && this.bibElement && this.bibElement.value) {
5732
- const useModal = !this.disableFocusTrap;
5733
- this.bibElement.value.open(useModal);
5783
+ if (this.bibElement && this.bibElement.value) {
5784
+ this.bibElement.value.open(this.isBibFullscreen);
5734
5785
  }
5735
5786
  }
5736
5787
 
@@ -5843,14 +5894,6 @@ class AuroDropdown extends AuroElement$1 {
5843
5894
  reflect: true
5844
5895
  },
5845
5896
 
5846
- /**
5847
- * If declared, the focus trap inside of bib will be turned off.
5848
- */
5849
- disableFocusTrap: {
5850
- type: Boolean,
5851
- reflect: true
5852
- },
5853
-
5854
5897
  /**
5855
5898
  * @private
5856
5899
  */
@@ -6124,7 +6167,7 @@ class AuroDropdown extends AuroElement$1 {
6124
6167
  if (this.isPopoverVisible) {
6125
6168
  // Fullscreen: use showModal() for native accessibility (inert outside, focus trap)
6126
6169
  // Desktop: use show() for Floating UI positioning + FocusTrap for focus management
6127
- const useModal = this.isBibFullscreen && !this.disableFocusTrap;
6170
+ const useModal = this.isBibFullscreen;
6128
6171
  this.bibElement.value.open(useModal);
6129
6172
  } else {
6130
6173
  this.bibElement.value.close();
@@ -6134,7 +6177,7 @@ class AuroDropdown extends AuroElement$1 {
6134
6177
  // When fullscreen strategy changes while open, re-open dialog with correct mode
6135
6178
  // (e.g. resizing from desktop → mobile while dropdown is open)
6136
6179
  if (changedProperties.has('isBibFullscreen') && this.isPopoverVisible && this.bibElement.value) {
6137
- const useModal = this.isBibFullscreen && !this.disableFocusTrap;
6180
+ const useModal = this.isBibFullscreen;
6138
6181
  this.bibElement.value.close();
6139
6182
  this.bibElement.value.open(useModal);
6140
6183
  }
@@ -6246,7 +6289,7 @@ class AuroDropdown extends AuroElement$1 {
6246
6289
  * @private
6247
6290
  */
6248
6291
  updateFocusTrap() {
6249
- if (this.isPopoverVisible && !this.disableFocusTrap) {
6292
+ if (this.isPopoverVisible) {
6250
6293
  if (!this.isBibFullscreen) {
6251
6294
  // Desktop: show() doesn't trap focus, so use FocusTrap
6252
6295
  this.focusTrap = new FocusTrap(this.bibContent);
@@ -7446,6 +7489,7 @@ class AuroCounterGroup extends AuroElement {
7446
7489
  counter.addEventListener("input", this.updateValue);
7447
7490
  counter.addEventListener("auroFormElement-validated", this.updateValidity);
7448
7491
  });
7492
+ this.updateValue();
7449
7493
  }
7450
7494
 
7451
7495
  /**
@@ -7576,6 +7620,8 @@ class AuroCounterGroup extends AuroElement {
7576
7620
  counter.addEventListener("auroFormElement-validated", this.updateValidity);
7577
7621
  });
7578
7622
 
7623
+ this.updateValue();
7624
+
7579
7625
  if (this.isDropdown) {
7580
7626
  this.configureBibtemplate();
7581
7627
  }
@@ -7601,15 +7647,6 @@ class AuroCounterGroup extends AuroElement {
7601
7647
  });
7602
7648
  }
7603
7649
  });
7604
-
7605
- // Tab closes the fullscreen dialog
7606
- // The dialog event bridge intercepts Tab and re-dispatches it as a
7607
- // composed keydown; this listener catches the re-dispatched event.
7608
- this.addEventListener('keydown', (evt) => {
7609
- if (evt.key === 'Tab' && this.dropdown.isPopoverVisible && this.dropdown.isBibFullscreen) {
7610
- this.dropdown.hide();
7611
- }
7612
- });
7613
7650
  }
7614
7651
 
7615
7652
  /**
@@ -7799,8 +7836,7 @@ class AuroCounterGroup extends AuroElement {
7799
7836
  */
7800
7837
  renderCounterDropdown() {
7801
7838
  return html`
7802
- <${this.dropdownTag}
7803
- noHideOnThisFocusLoss
7839
+ <${this.dropdownTag}
7804
7840
  chevron
7805
7841
  part="dropdown"
7806
7842
  appearance="${this.onDark ? 'inverse' : this.appearance}"