@aurodesignsystem-dev/auro-formkit 0.0.0-pr1398.1 → 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 (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 +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.md +1 -1
  13. package/components/counter/demo/api.min.js +183 -160
  14. package/components/counter/demo/index.min.js +183 -160
  15. package/components/counter/demo/keyboardBehavior.html +81 -0
  16. package/components/counter/demo/keyboardBehavior.md +127 -0
  17. package/components/counter/dist/auro-counter.d.ts +11 -8
  18. package/components/counter/dist/index.js +183 -160
  19. package/components/counter/dist/keyboardStrategy.d.ts +4 -0
  20. package/components/counter/dist/registered.js +183 -160
  21. package/components/datepicker/demo/api.min.js +89 -137
  22. package/components/datepicker/demo/index.min.js +89 -137
  23. package/components/datepicker/demo/keyboardBehavior.html +81 -0
  24. package/components/datepicker/demo/keyboardBehavior.md +24 -0
  25. package/components/datepicker/dist/index.js +84 -132
  26. package/components/datepicker/dist/registered.js +84 -132
  27. package/components/dropdown/demo/api.md +0 -1
  28. package/components/dropdown/demo/api.min.js +99 -140
  29. package/components/dropdown/demo/index.md +2 -2
  30. package/components/dropdown/demo/index.min.js +99 -140
  31. package/components/dropdown/demo/keyboardBehavior.html +81 -0
  32. package/components/dropdown/demo/keyboardBehavior.md +77 -0
  33. package/components/dropdown/dist/auro-dropdown.d.ts +0 -8
  34. package/components/dropdown/dist/auro-dropdownBib.d.ts +1 -50
  35. package/components/dropdown/dist/dropdownBibKeyboardStrategy.d.ts +7 -0
  36. package/components/dropdown/dist/index.js +83 -128
  37. package/components/dropdown/dist/registered.js +83 -128
  38. package/components/form/demo/api.min.js +492 -599
  39. package/components/form/demo/index.min.js +492 -599
  40. package/components/form/demo/keyboardBehavior.md +0 -0
  41. package/components/input/demo/api.min.js +1 -1
  42. package/components/input/demo/index.min.js +1 -1
  43. package/components/input/demo/keyboardBehavior.md +0 -0
  44. package/components/input/dist/index.js +1 -1
  45. package/components/input/dist/registered.js +1 -1
  46. package/components/menu/demo/api.min.js +42 -32
  47. package/components/menu/demo/index.min.js +42 -32
  48. package/components/menu/dist/auro-menu.d.ts +3 -11
  49. package/components/menu/dist/index.js +42 -32
  50. package/components/menu/dist/registered.js +42 -32
  51. package/components/radio/demo/api.min.js +1 -1
  52. package/components/radio/demo/index.min.js +1 -1
  53. package/components/radio/dist/index.js +1 -1
  54. package/components/radio/dist/registered.js +1 -1
  55. package/components/select/demo/api.min.js +132 -167
  56. package/components/select/demo/index.min.js +132 -167
  57. package/components/select/demo/keyboardBehavior.html +81 -0
  58. package/components/select/demo/keyboardBehavior.md +246 -0
  59. package/components/select/dist/index.js +90 -135
  60. package/components/select/dist/registered.js +90 -135
  61. package/custom-elements.json +1598 -1598
  62. package/package.json +5 -3
@@ -1234,6 +1234,57 @@ class IconUtil {
1234
1234
  * SPDX-License-Identifier: BSD-3-Clause
1235
1235
  */let e$1 = class e extends i{constructor(i){if(super(i),this.it=A$2,i.type!==t.CHILD)throw Error(this.constructor.directiveName+"() can only be used in child bindings")}render(r){if(r===A$2||null==r)return this._t=void 0,this.it=r;if(r===E)return r;if("string"!=typeof r)throw Error(this.constructor.directiveName+"() called with a non-string value");if(r===this.it)return this._t;this.it=r;const s=[r];return s.raw=s,this._t={_$litType$:this.constructor.resultType,strings:s,values:[]}}};e$1.directiveName="unsafeHTML",e$1.resultType=1;
1236
1236
 
1237
+ /**
1238
+ * Computes display state once per keydown event.
1239
+ * Centralizes null-safety checks and makes the shared/modal/popover branching explicit.
1240
+ *
1241
+ * @param {HTMLElement} component - The component with a dropdown reference.
1242
+ * @param {Object} [options] - Optional config.
1243
+ * @param {HTMLElement} [options.dropdown] - Explicit dropdown reference. Falls back to component.dropdown.
1244
+ * @param {Function} [options.inputResolver] - Called with (component, ctx) to resolve the active input element.
1245
+ * @returns {{isExpanded: boolean, isModal: boolean, isPopover: boolean, activeInput: HTMLElement|null}}
1246
+ * isModal and isPopover reflect the display mode (fullscreen vs not) regardless of expanded state.
1247
+ */
1248
+ function createDisplayContext$1(component, options = {}) {
1249
+ const dd = options.dropdown || component.dropdown;
1250
+ // isPopoverVisible reflects as the `open` attribute.
1251
+ // It reports whether the bib is open in any mode (popover or modal).
1252
+ const isExpanded = Boolean(dd && dd.isPopoverVisible);
1253
+ const isFullscreen = Boolean(dd && dd.isBibFullscreen);
1254
+
1255
+ const ctx = {
1256
+ isExpanded,
1257
+ isModal: isFullscreen,
1258
+ isPopover: !isFullscreen,
1259
+ activeInput: null,
1260
+ };
1261
+
1262
+ if (options.inputResolver) {
1263
+ const resolvedInput = options.inputResolver(component, ctx);
1264
+ // Guard against resolvers returning undefined or non-HTMLElement values.
1265
+ ctx.activeInput = resolvedInput instanceof HTMLElement ? resolvedInput : null;
1266
+ }
1267
+
1268
+ return ctx;
1269
+ }
1270
+
1271
+ /**
1272
+ * Wires up a keydown listener that dispatches to strategy[evt.key] or strategy.default.
1273
+ * Handles both sync and async handlers.
1274
+ * @param {HTMLElement} component - The component to attach the listener to.
1275
+ * @param {Object} strategy - Map of key names to handler functions.
1276
+ * @param {Object} [options] - Optional config passed to createDisplayContext.
1277
+ */
1278
+ function applyKeyboardStrategy$1(component, strategy, options = {}) {
1279
+ component.addEventListener('keydown', async (evt) => {
1280
+ const handler = strategy[evt.key] || strategy.default;
1281
+ if (typeof handler === 'function') {
1282
+ const ctx = createDisplayContext$1(component, options);
1283
+ await handler(component, evt, ctx);
1284
+ }
1285
+ });
1286
+ }
1287
+
1237
1288
  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>"};
1238
1289
 
1239
1290
  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>"};
@@ -1470,7 +1521,30 @@ let AuroHelpText$1 = class AuroHelpText extends i$2 {
1470
1521
  }
1471
1522
  };
1472
1523
 
1473
- var formkitVersion$1 = '202603261553';
1524
+ var formkitVersion$1 = '202604012043';
1525
+
1526
+ // Copyright (c) 2026 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
1527
+ // See LICENSE in the project root for license information.
1528
+
1529
+ const keyboardStrategy = {
1530
+ ArrowUp(component, _evt) {
1531
+ if (component.disabled) {
1532
+ return;
1533
+ }
1534
+
1535
+ _evt.preventDefault();
1536
+ component.increment();
1537
+ },
1538
+
1539
+ ArrowDown(component, _evt) {
1540
+ if (component.disabled) {
1541
+ return;
1542
+ }
1543
+
1544
+ _evt.preventDefault();
1545
+ component.decrement();
1546
+ }
1547
+ };
1474
1548
 
1475
1549
  // Copyright (c) 2025 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
1476
1550
  // See LICENSE in the project root for license information.
@@ -1544,14 +1618,36 @@ class AuroCounter extends i$2 {
1544
1618
 
1545
1619
  connectedCallback() {
1546
1620
  super.connectedCallback();
1547
- this.addEventListener('keydown', this.handleKeyDown);
1621
+ applyKeyboardStrategy$1(this, keyboardStrategy);
1548
1622
  }
1549
1623
 
1550
1624
  disconnectedCallback() {
1551
- this.removeEventListener('keydown', this.handleKeyDown);
1552
1625
  super.disconnectedCallback();
1553
1626
  }
1554
1627
 
1628
+ /**
1629
+ * Gets the current value of the counter.
1630
+ * @returns {number|undefined} The current value of the counter, or undefined if the value is not set or invalid.
1631
+ */
1632
+ get value() {
1633
+ return this._value;
1634
+ }
1635
+
1636
+ /**
1637
+ * 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.
1638
+ * @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.
1639
+ */
1640
+ set value(val) {
1641
+ const old = this._value;
1642
+ if (val === undefined || val === null) {
1643
+ this._value = undefined;
1644
+ } else {
1645
+ const num = Number(val);
1646
+ this._value = Number.isNaN(num) ? undefined : num;
1647
+ }
1648
+ this.requestUpdate('value', old);
1649
+ }
1650
+
1555
1651
  /**
1556
1652
  * Defines reactive properties for the component.
1557
1653
  * @returns {Object} Property configuration.
@@ -1736,29 +1832,6 @@ class AuroCounter extends i$2 {
1736
1832
  this.validation.validate(this, force);
1737
1833
  }
1738
1834
 
1739
- /**
1740
- * Handles the keydown event for the counter component.
1741
- * @param {KeyboardEvent} event - The keyboard event object.
1742
- * @returns {void}
1743
- * @private
1744
- */
1745
- handleKeyDown(event) {
1746
- if (this.disabled) {
1747
- return;
1748
- }
1749
-
1750
- switch (event.key) {
1751
- case 'ArrowUp':
1752
- event.preventDefault();
1753
- this.increment();
1754
- break;
1755
- case 'ArrowDown':
1756
- event.preventDefault();
1757
- this.decrement();
1758
- break;
1759
- }
1760
- }
1761
-
1762
1835
  firstUpdated() {
1763
1836
  this.initValue();
1764
1837
  this.setTagAttribute("auro-counter");
@@ -3979,11 +4052,10 @@ class AuroFloatingUI {
3979
4052
  return;
3980
4053
  }
3981
4054
 
3982
- const { activeElement } = document;
3983
4055
  // if focus is still inside of trigger or bib, do not close
3984
4056
  if (
3985
- this.element.contains(activeElement) ||
3986
- this.element.bib?.contains(activeElement)
4057
+ this.element.matches(":focus") ||
4058
+ this.element.matches(":focus-within")
3987
4059
  ) {
3988
4060
  return;
3989
4061
  }
@@ -4822,12 +4894,83 @@ let p$2 = class p{registerComponent(t,a){customElements.get(t)||customElements.d
4822
4894
 
4823
4895
  var iconVersion$1 = '9.1.2';
4824
4896
 
4897
+ /**
4898
+ * Computes display state once per keydown event.
4899
+ * Centralizes null-safety checks and makes the shared/modal/popover branching explicit.
4900
+ *
4901
+ * @param {HTMLElement} component - The component with a dropdown reference.
4902
+ * @param {Object} [options] - Optional config.
4903
+ * @param {HTMLElement} [options.dropdown] - Explicit dropdown reference. Falls back to component.dropdown.
4904
+ * @param {Function} [options.inputResolver] - Called with (component, ctx) to resolve the active input element.
4905
+ * @returns {{isExpanded: boolean, isModal: boolean, isPopover: boolean, activeInput: HTMLElement|null}}
4906
+ * isModal and isPopover reflect the display mode (fullscreen vs not) regardless of expanded state.
4907
+ */
4908
+ function createDisplayContext(component, options = {}) {
4909
+ const dd = options.dropdown || component.dropdown;
4910
+ // isPopoverVisible reflects as the `open` attribute.
4911
+ // It reports whether the bib is open in any mode (popover or modal).
4912
+ const isExpanded = Boolean(dd && dd.isPopoverVisible);
4913
+ const isFullscreen = Boolean(dd && dd.isBibFullscreen);
4914
+
4915
+ const ctx = {
4916
+ isExpanded,
4917
+ isModal: isFullscreen,
4918
+ isPopover: !isFullscreen,
4919
+ activeInput: null,
4920
+ };
4921
+
4922
+ if (options.inputResolver) {
4923
+ const resolvedInput = options.inputResolver(component, ctx);
4924
+ // Guard against resolvers returning undefined or non-HTMLElement values.
4925
+ ctx.activeInput = resolvedInput instanceof HTMLElement ? resolvedInput : null;
4926
+ }
4927
+
4928
+ return ctx;
4929
+ }
4930
+
4931
+ /**
4932
+ * Wires up a keydown listener that dispatches to strategy[evt.key] or strategy.default.
4933
+ * Handles both sync and async handlers.
4934
+ * @param {HTMLElement} component - The component to attach the listener to.
4935
+ * @param {Object} strategy - Map of key names to handler functions.
4936
+ * @param {Object} [options] - Optional config passed to createDisplayContext.
4937
+ */
4938
+ function applyKeyboardStrategy(component, strategy, options = {}) {
4939
+ component.addEventListener('keydown', async (evt) => {
4940
+ const handler = strategy[evt.key] || strategy.default;
4941
+ if (typeof handler === 'function') {
4942
+ const ctx = createDisplayContext(component, options);
4943
+ await handler(component, evt, ctx);
4944
+ }
4945
+ });
4946
+ }
4947
+
4825
4948
  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}`;
4826
4949
 
4827
4950
  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)}`;
4828
4951
 
4829
4952
  var tokensCss$1 = i$5`: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)}`;
4830
4953
 
4954
+ /**
4955
+ * Creates a keyboard strategy for dialog-specific key handling.
4956
+ * All other keydown behavior is left to the browser's native bubbling path.
4957
+ * @param {HTMLElement} bib - The dropdown bib element.
4958
+ * @returns {Object} Keyboard handlers keyed by `event.key`.
4959
+ */
4960
+ // eslint-disable-next-line no-unused-vars
4961
+ function createDropdownBibKeyboardStrategy(bib) {
4962
+ return {
4963
+ // eslint-disable-next-line no-unused-vars
4964
+ Enter(_dialog, event) {
4965
+ // Floating UI handles Enter key to open the dropdown
4966
+ },
4967
+ // eslint-disable-next-line no-unused-vars
4968
+ Escape(_dialog, event) {
4969
+ // Floating UI handles Escape key to close the dropdown
4970
+ }
4971
+ };
4972
+ }
4973
+
4831
4974
  // Copyright (c) 2020 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
4832
4975
  // See LICENSE in the project root for license information.
4833
4976
  /* eslint-disable max-lines */
@@ -4952,26 +5095,11 @@ class AuroDropdownBib extends i$2 {
4952
5095
  },
4953
5096
 
4954
5097
  /**
4955
- * Set by auro-dropdown when a menu option is highlighted via
4956
- * aria-activedescendant. The dialog keyboard bridge checks this
4957
- * flag so that Enter selects the highlighted option instead of
4958
- * activating the focused interactive element (e.g. the trigger
4959
- * button, or the bibtemplate close button in fullscreen).
5098
+ * Tracks whether a menu option is currently highlighted.
4960
5099
  * @private
4961
5100
  */
4962
5101
  hasActiveDescendant: {
4963
5102
  type: Boolean
4964
- },
4965
-
4966
- /**
4967
- * When true, the keyboard bridge allows native Tab behavior
4968
- * instead of intercepting it. Set this for bib consumers
4969
- * (e.g. counter) whose content contains real focusable elements
4970
- * that need native Tab navigation.
4971
- * @private
4972
- */
4973
- nativeFocusableContent: {
4974
- type: Boolean
4975
5103
  }
4976
5104
  };
4977
5105
  }
@@ -5041,7 +5169,7 @@ class AuroDropdownBib extends i$2 {
5041
5169
 
5042
5170
  const dialog = this.shadowRoot.querySelector('dialog');
5043
5171
  this._setupCancelHandler(dialog);
5044
- this._setupKeyboardBridge(dialog);
5172
+ applyKeyboardStrategy(dialog, createDropdownBibKeyboardStrategy());
5045
5173
 
5046
5174
  this.dispatchEvent(new CustomEvent('auro-dropdownbib-connected', {
5047
5175
  bubbles: true,
@@ -5068,98 +5196,6 @@ class AuroDropdownBib extends i$2 {
5068
5196
  });
5069
5197
  }
5070
5198
 
5071
- /**
5072
- * showModal() creates a closed focus scope — keyboard events inside
5073
- * the dialog's shadow DOM do NOT bubble out to the combobox/select
5074
- * keydown handlers in the parent shadow DOM. This handler bridges
5075
- * that gap by re-dispatching navigation keys so they cross the
5076
- * shadow boundary and reach the menu navigation logic in the parent
5077
- * component.
5078
- *
5079
- * The trade-off: intercepting these keys means native keyboard
5080
- * behaviors that would normally "just work" must be manually
5081
- * re-implemented here:
5082
- *
5083
- * - Enter on buttons: Custom elements (auro-button) don't get the
5084
- * native Enter→click that <button> provides, so we call .click()
5085
- * directly when Enter is pressed on a button-like element.
5086
- *
5087
- * - Tab: Intercepted and re-dispatched so parent components
5088
- * (select/combobox) can select the active option and close the
5089
- * dialog. The <dialog> provides containment and isolation
5090
- * (inert background, VoiceOver focus trapping, top layer), while
5091
- * the content inside is a role="listbox" navigated via
5092
- * aria-activedescendant (options are not focusable). Tab keyboard
5093
- * behavior follows listbox conventions (select + close) because
5094
- * the dialog's native Tab trap only cycles between the close
5095
- * button and browser chrome.
5096
- *
5097
- * - Escape: The native <dialog> fires a `cancel` event on ESC
5098
- * (handled by _setupCancelHandler), so the re-dispatched Escape
5099
- * is a secondary path for parent components that also listen for
5100
- * Escape keydown.
5101
- *
5102
- * @param {HTMLDialogElement} dialog - The dialog element to attach the keyboard bridge to.
5103
- * @private
5104
- */
5105
- _setupKeyboardBridge(dialog) {
5106
- const navKeys = new Set([
5107
- 'ArrowUp',
5108
- 'ArrowDown',
5109
- 'Enter',
5110
- 'Escape',
5111
- 'Tab'
5112
- ]);
5113
-
5114
- dialog.addEventListener('keydown', (event) => {
5115
- if (!navKeys.has(event.key)) {
5116
- return;
5117
- }
5118
-
5119
- // Custom elements (auro-button) don't get the native Enter→click
5120
- // behavior that <button> has. Find the button in the composed path
5121
- // and click it directly — but only when no menu option is
5122
- // highlighted. In fullscreen mode focus stays on the close button
5123
- // while arrow keys move the active-descendant highlight through
5124
- // the listbox. If the user presses Enter with an option
5125
- // highlighted, the intent is to select that option, not to click
5126
- // the close button. In that case we fall through and bridge the
5127
- // Enter key to the parent component's keyboard strategy.
5128
- if (event.key === 'Enter') {
5129
- if (!this.hasActiveDescendant) {
5130
- const buttonSelector = 'button, [role="button"], auro-button, [auro-button]';
5131
- const btn = event.composedPath().find((el) => el.matches && el.matches(buttonSelector));
5132
- if (btn) {
5133
- event.preventDefault();
5134
- event.stopPropagation();
5135
- btn.click();
5136
- return;
5137
- }
5138
- }
5139
- }
5140
-
5141
- // Allow native Tab when the bib contains focusable content
5142
- // (e.g. counter buttons) that needs normal Tab navigation.
5143
- if (event.key === 'Tab' && this.nativeFocusableContent) {
5144
- return;
5145
- }
5146
-
5147
- event.preventDefault();
5148
- event.stopPropagation();
5149
- const newEvent = new KeyboardEvent('keydown', {
5150
- key: event.key,
5151
- code: event.code,
5152
- shiftKey: event.shiftKey,
5153
- altKey: event.altKey,
5154
- ctrlKey: event.ctrlKey,
5155
- metaKey: event.metaKey,
5156
- bubbles: true,
5157
- composed: true,
5158
- cancelable: true
5159
- });
5160
- this.dispatchEvent(newEvent);
5161
- });
5162
- }
5163
5199
 
5164
5200
  /**
5165
5201
  * Blocks touch-driven page scroll while a fullscreen modal dialog is open.
@@ -5534,7 +5570,7 @@ class AuroHelpText extends i$2 {
5534
5570
  }
5535
5571
  }
5536
5572
 
5537
- var formkitVersion = '202603261553';
5573
+ var formkitVersion = '202604012043';
5538
5574
 
5539
5575
  let AuroElement$1 = class AuroElement extends i$2 {
5540
5576
  static get properties() {
@@ -5715,7 +5751,6 @@ class AuroDropdown extends AuroElement$1 {
5715
5751
  this.appearance = 'default';
5716
5752
  this.chevron = false;
5717
5753
  this.disabled = false;
5718
- this.disableFocusTrap = false;
5719
5754
  this.error = false;
5720
5755
  this.tabIndex = 0;
5721
5756
  this.noToggle = false;
@@ -5813,9 +5848,8 @@ class AuroDropdown extends AuroElement$1 {
5813
5848
  // showModal() fires asynchronously via Lit's update cycle, which
5814
5849
  // falls outside the user activation window and causes iOS to
5815
5850
  // dismiss the keyboard.
5816
- if (this.isBibFullscreen && this.bibElement && this.bibElement.value) {
5817
- const useModal = !this.disableFocusTrap;
5818
- this.bibElement.value.open(useModal);
5851
+ if (this.bibElement && this.bibElement.value) {
5852
+ this.bibElement.value.open(this.isBibFullscreen);
5819
5853
  }
5820
5854
  }
5821
5855
 
@@ -5928,14 +5962,6 @@ class AuroDropdown extends AuroElement$1 {
5928
5962
  reflect: true
5929
5963
  },
5930
5964
 
5931
- /**
5932
- * If declared, the focus trap inside of bib will be turned off.
5933
- */
5934
- disableFocusTrap: {
5935
- type: Boolean,
5936
- reflect: true
5937
- },
5938
-
5939
5965
  /**
5940
5966
  * @private
5941
5967
  */
@@ -6209,7 +6235,7 @@ class AuroDropdown extends AuroElement$1 {
6209
6235
  if (this.isPopoverVisible) {
6210
6236
  // Fullscreen: use showModal() for native accessibility (inert outside, focus trap)
6211
6237
  // Desktop: use show() for Floating UI positioning + FocusTrap for focus management
6212
- const useModal = this.isBibFullscreen && !this.disableFocusTrap;
6238
+ const useModal = this.isBibFullscreen;
6213
6239
  this.bibElement.value.open(useModal);
6214
6240
  } else {
6215
6241
  this.bibElement.value.close();
@@ -6219,7 +6245,7 @@ class AuroDropdown extends AuroElement$1 {
6219
6245
  // When fullscreen strategy changes while open, re-open dialog with correct mode
6220
6246
  // (e.g. resizing from desktop → mobile while dropdown is open)
6221
6247
  if (changedProperties.has('isBibFullscreen') && this.isPopoverVisible && this.bibElement.value) {
6222
- const useModal = this.isBibFullscreen && !this.disableFocusTrap;
6248
+ const useModal = this.isBibFullscreen;
6223
6249
  this.bibElement.value.close();
6224
6250
  this.bibElement.value.open(useModal);
6225
6251
  }
@@ -6331,7 +6357,7 @@ class AuroDropdown extends AuroElement$1 {
6331
6357
  * @private
6332
6358
  */
6333
6359
  updateFocusTrap() {
6334
- if (this.isPopoverVisible && !this.disableFocusTrap) {
6360
+ if (this.isPopoverVisible) {
6335
6361
  if (!this.isBibFullscreen) {
6336
6362
  // Desktop: show() doesn't trap focus, so use FocusTrap
6337
6363
  this.focusTrap = new FocusTrap(this.bibContent);
@@ -7531,6 +7557,7 @@ class AuroCounterGroup extends AuroElement {
7531
7557
  counter.addEventListener("input", this.updateValue);
7532
7558
  counter.addEventListener("auroFormElement-validated", this.updateValidity);
7533
7559
  });
7560
+ this.updateValue();
7534
7561
  }
7535
7562
 
7536
7563
  /**
@@ -7661,6 +7688,8 @@ class AuroCounterGroup extends AuroElement {
7661
7688
  counter.addEventListener("auroFormElement-validated", this.updateValidity);
7662
7689
  });
7663
7690
 
7691
+ this.updateValue();
7692
+
7664
7693
  if (this.isDropdown) {
7665
7694
  this.configureBibtemplate();
7666
7695
  }
@@ -7680,11 +7709,6 @@ class AuroCounterGroup extends AuroElement {
7680
7709
 
7681
7710
  // Focus close button when fullscreen dialog opens
7682
7711
  this.dropdown.addEventListener('auroDropdown-toggled', () => {
7683
- // Tell the bib's keyboard bridge to allow native Tab so focus
7684
- // moves between the real focusable counter elements in the bib.
7685
- if (this.dropdown.bibContent) {
7686
- this.dropdown.bibContent.nativeFocusableContent = true;
7687
- }
7688
7712
  if (this.dropdown.isPopoverVisible && this.dropdown.isBibFullscreen) {
7689
7713
  doubleRaf(() => {
7690
7714
  this.bibtemplate.focusCloseButton();
@@ -7881,7 +7905,6 @@ class AuroCounterGroup extends AuroElement {
7881
7905
  renderCounterDropdown() {
7882
7906
  return u$5`
7883
7907
  <${this.dropdownTag}
7884
- noHideOnThisFocusLoss
7885
7908
  chevron
7886
7909
  part="dropdown"
7887
7910
  appearance="${this.onDark ? 'inverse' : this.appearance}"