@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
@@ -0,0 +1,127 @@
1
+ <auro-header level="1" id="overview">Counter & Counter Group - Keyboard Behavior</auro-header>
2
+ <div class="contentWrapper">
3
+ <div class="mainContent">
4
+ <div class="scrollWrapper">
5
+ <auro-header level="2" id="tabBehavior">Tab Behavior</auro-header>
6
+ <auro-header level="3" id="tabBehaviorCounter">Counter</auro-header>
7
+ <p>The counter component is itself a focusable element. There are no sub-parts that are separately focusable.</p>
8
+ <auro-header level="3" id="tabBehaviorCounterGroup">Counter Group</auro-header>
9
+ <p>When multiple counters are placed inside a counter group the component behaves as an auro-dropdown. The trigger element renders a counter group label and a summary of all counter labels and current values. The dropdown bib renders all counters inside of the group.</p>
10
+ <!-- AURO-GENERATED-CONTENT:START (FILE:src=./../../dropdown/docs/partials/tabindex.md) -->
11
+ <!-- The below content is automatically added from ./../../dropdown/docs/partials/tabindex.md -->
12
+ <p>The trigger is a focusable element and participates in the standard tab order, responding to <code>Tab</code> and <code>Shift+Tab</code> key events per <auro-hyperlink href="https://developer.mozilla.org/en-US/docs/Web/HTML/Reference/Global_attributes/tabindex">native browser behavior, i.e., these keys step through the browser tabindex sequence.</auro-hyperlink></p>
13
+ <p>When the component is <code>disabled</code> it is removed from the <code>tabindex</code> sequence. VoiceOver's virtual cursor <em>(swipe navigation)</em> can still encounter the component, but standard keyboard <code>Tab</code> navigation skips it.</p>
14
+ <p>When the bib is collapsed, the bib content is excluded from the tab sequence. When <strong>expanded</strong>, focusable elements within the bib content are included in the natural tab order. In fullscreen mode, focus is trapped within the bib, and the tab sequence cycles through the bib content focusable elements until the bib is closed or the viewport no longer meets the fullscreen condition and is rendered as a popover.</p>
15
+ <!-- AURO-GENERATED-CONTENT:END -->
16
+ <auro-header level="2" id="keyEvents">Key Events</auro-header>
17
+ <auro-header level="3" id="keyEventsCounter">Counter</auro-header>
18
+ <!-- AURO-GENERATED-CONTENT:START (FILE:src=./../docs/partials/keyEvents-counter.md) -->
19
+ <!-- The below content is automatically added from ./../docs/partials/keyEvents-counter.md -->
20
+ <table>
21
+ <thead>
22
+ <tr>
23
+ <th>Key</th>
24
+ <th>Modifier</th>
25
+ <th>Current State</th>
26
+ <th>Focus Element</th>
27
+ <th>Behavior</th>
28
+ </tr>
29
+ </thead>
30
+ <tbody>
31
+ <tr>
32
+ <td>ArrowDown</td>
33
+ <td>-</td>
34
+ <td>*</td>
35
+ <td>
36
+ Trigger element.
37
+ </td>
38
+ <td>Decrements the counter value by 1.</td>
39
+ </tr>
40
+ <tr>
41
+ <td>ArrowUp</td>
42
+ <td>-</td>
43
+ <td>*</td>
44
+ <td>
45
+ Trigger element.
46
+ </td>
47
+ <td>Increments the counter value by 1.</td>
48
+ </tr>
49
+ </tbody>
50
+ </table>
51
+ <!-- AURO-GENERATED-CONTENT:END -->
52
+ <div class="note">
53
+ <p><strong>Note:</strong> The following keyboard behavior is unsupported at this time:</p>
54
+ <ul>
55
+ <li><strong>Home:</strong> sets the counter value to the defined minimum (default 0)</li>
56
+ <li><strong>End:</strong> sets the counter value to the defined maximum (default 9)</li>
57
+ <li><strong>PageUp:</strong> (optional) Increases the value by a larger step than Up Arrow.</li>
58
+ <li><strong>PageDown:</strong> (optional) Decreases the value by a larger step than Down Arrow.</li>
59
+ </ul>
60
+ </div>
61
+ <auro-header level="3" id="keyEventsCounterGroup">Counter Group</auro-header>
62
+ <!-- AURO-GENERATED-CONTENT:START (FILE:src=./../docs/partials/keyEvents-counterGroup.md) -->
63
+ <!-- The below content is automatically added from ./../docs/partials/keyEvents-counterGroup.md -->
64
+ <p>The counter group itself does not have any key event handlers other than those inherited from the dropdown component. However, when the counter group is <strong>expanded</strong> or <strong>opened</strong> the first counter in the bib receives <strong>focus</strong>. When the counter group is <strong>collapsed</strong> or <strong>closed</strong> by any method other than the <code>Tab</code> key (e.g., the <strong>Esc</strong> key), <strong>focus</strong> moves to the trigger element.</p>
65
+ <!-- AURO-GENERATED-CONTENT:END -->
66
+ <auro-header level="4" id="keyEventsDropdown">Key Events inherited from Auro-Dropdown</auro-header>
67
+ <!-- AURO-GENERATED-CONTENT:START (FILE:src=./../../dropdown/docs/partials/keyEvents.md) -->
68
+ <!-- The below content is automatically added from ./../../dropdown/docs/partials/keyEvents.md -->
69
+ <table>
70
+ <thead>
71
+ <tr>
72
+ <th>Key</th>
73
+ <th>Modifier</th>
74
+ <th>Current State</th>
75
+ <th>Focus Element</th>
76
+ <th>Behavior</th>
77
+ </tr>
78
+ </thead>
79
+ <tbody>
80
+ <tr>
81
+ <td rowspan="2">Enter</td>
82
+ <td>-</td>
83
+ <td>Collapsed</td>
84
+ <td>
85
+ Trigger or any <strong>focusable</strong> element within the trigger.
86
+ </td>
87
+ <td>Opens the bib.</td>
88
+ </tr>
89
+ <tr>
90
+ <td>-</td>
91
+ <td>Expanded</td>
92
+ <td>
93
+ Trigger or any <strong>focusable</strong> element within the trigger.
94
+ </td>
95
+ <td>Closes the bib.</td>
96
+ </tr>
97
+ <tr>
98
+ <td>Escape</td>
99
+ <td>-</td>
100
+ <td>Expanded</td>
101
+ <td>
102
+ Component <code>:host</code> or any <strong>focusable</strong> element within the component.
103
+ </td>
104
+ <td>Closes the bib.</td>
105
+ </tr>
106
+ <tr>
107
+ <td rowspan="2">Space</td>
108
+ <td>-</td>
109
+ <td>Collapsed</td>
110
+ <td>
111
+ Trigger or any <strong>focusable</strong> element within the trigger.
112
+ </td>
113
+ <td>Opens the bib.</td>
114
+ </tr>
115
+ <tr>
116
+ <td>-</td>
117
+ <td>Expanded</td>
118
+ <td>
119
+ Trigger or any <strong>focusable</strong> element within the trigger.
120
+ </td>
121
+ <td>Closes the bib.</td>
122
+ </tr>
123
+ </tbody>
124
+ </table>
125
+ <!-- AURO-GENERATED-CONTENT:END -->
126
+ </div>
127
+ </div>
@@ -40,7 +40,16 @@ export class AuroCounter extends LitElement {
40
40
  min: number;
41
41
  onDark: boolean;
42
42
  validity: any;
43
- value: number;
43
+ /**
44
+ * 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.
45
+ * @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.
46
+ */
47
+ set value(val: number | string | undefined | null);
48
+ /**
49
+ * Gets the current value of the counter.
50
+ * @returns {number|undefined} The current value of the counter, or undefined if the value is not set or invalid.
51
+ */
52
+ get value(): number | undefined;
44
53
  /**
45
54
  * @private
46
55
  */
@@ -59,6 +68,7 @@ export class AuroCounter extends LitElement {
59
68
  * @private
60
69
  */
61
70
  private runtimeUtils;
71
+ _value: number;
62
72
  /**
63
73
  * Increments the counter value by 1. If a value is provided, it increments by that amount.
64
74
  * @method increment
@@ -92,13 +102,6 @@ export class AuroCounter extends LitElement {
92
102
  * @param {boolean} [force=false] - Whether to force validation.
93
103
  */
94
104
  validate(force?: boolean): void;
95
- /**
96
- * Handles the keydown event for the counter component.
97
- * @param {KeyboardEvent} event - The keyboard event object.
98
- * @returns {void}
99
- * @private
100
- */
101
- private handleKeyDown;
102
105
  firstUpdated(): void;
103
106
  /**
104
107
  * Sets an attribute that matches the default tag name if the tag name is not the default.
@@ -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 = '202603261553';
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,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,26 +5027,11 @@ 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: {
4895
5034
  type: Boolean
4896
- },
4897
-
4898
- /**
4899
- * When true, the keyboard bridge allows native Tab behavior
4900
- * instead of intercepting it. Set this for bib consumers
4901
- * (e.g. counter) whose content contains real focusable elements
4902
- * that need native Tab navigation.
4903
- * @private
4904
- */
4905
- nativeFocusableContent: {
4906
- type: Boolean
4907
5035
  }
4908
5036
  };
4909
5037
  }
@@ -4973,7 +5101,7 @@ class AuroDropdownBib extends LitElement {
4973
5101
 
4974
5102
  const dialog = this.shadowRoot.querySelector('dialog');
4975
5103
  this._setupCancelHandler(dialog);
4976
- this._setupKeyboardBridge(dialog);
5104
+ applyKeyboardStrategy(dialog, createDropdownBibKeyboardStrategy());
4977
5105
 
4978
5106
  this.dispatchEvent(new CustomEvent('auro-dropdownbib-connected', {
4979
5107
  bubbles: true,
@@ -5000,98 +5128,6 @@ class AuroDropdownBib extends LitElement {
5000
5128
  });
5001
5129
  }
5002
5130
 
5003
- /**
5004
- * showModal() creates a closed focus scope — keyboard events inside
5005
- * the dialog's shadow DOM do NOT bubble out to the combobox/select
5006
- * keydown handlers in the parent shadow DOM. This handler bridges
5007
- * that gap by re-dispatching navigation keys so they cross the
5008
- * shadow boundary and reach the menu navigation logic in the parent
5009
- * component.
5010
- *
5011
- * The trade-off: intercepting these keys means native keyboard
5012
- * behaviors that would normally "just work" must be manually
5013
- * re-implemented here:
5014
- *
5015
- * - Enter on buttons: Custom elements (auro-button) don't get the
5016
- * native Enter→click that <button> provides, so we call .click()
5017
- * directly when Enter is pressed on a button-like element.
5018
- *
5019
- * - Tab: Intercepted and re-dispatched so parent components
5020
- * (select/combobox) can select the active option and close the
5021
- * dialog. The <dialog> provides containment and isolation
5022
- * (inert background, VoiceOver focus trapping, top layer), while
5023
- * the content inside is a role="listbox" navigated via
5024
- * aria-activedescendant (options are not focusable). Tab keyboard
5025
- * behavior follows listbox conventions (select + close) because
5026
- * the dialog's native Tab trap only cycles between the close
5027
- * button and browser chrome.
5028
- *
5029
- * - Escape: The native <dialog> fires a `cancel` event on ESC
5030
- * (handled by _setupCancelHandler), so the re-dispatched Escape
5031
- * is a secondary path for parent components that also listen for
5032
- * Escape keydown.
5033
- *
5034
- * @param {HTMLDialogElement} dialog - The dialog element to attach the keyboard bridge to.
5035
- * @private
5036
- */
5037
- _setupKeyboardBridge(dialog) {
5038
- const navKeys = new Set([
5039
- 'ArrowUp',
5040
- 'ArrowDown',
5041
- 'Enter',
5042
- 'Escape',
5043
- 'Tab'
5044
- ]);
5045
-
5046
- dialog.addEventListener('keydown', (event) => {
5047
- if (!navKeys.has(event.key)) {
5048
- return;
5049
- }
5050
-
5051
- // Custom elements (auro-button) don't get the native Enter→click
5052
- // behavior that <button> has. Find the button in the composed path
5053
- // and click it directly — but only when no menu option is
5054
- // highlighted. In fullscreen mode focus stays on the close button
5055
- // while arrow keys move the active-descendant highlight through
5056
- // the listbox. If the user presses Enter with an option
5057
- // highlighted, the intent is to select that option, not to click
5058
- // the close button. In that case we fall through and bridge the
5059
- // Enter key to the parent component's keyboard strategy.
5060
- if (event.key === 'Enter') {
5061
- if (!this.hasActiveDescendant) {
5062
- const buttonSelector = 'button, [role="button"], auro-button, [auro-button]';
5063
- const btn = event.composedPath().find((el) => el.matches && el.matches(buttonSelector));
5064
- if (btn) {
5065
- event.preventDefault();
5066
- event.stopPropagation();
5067
- btn.click();
5068
- return;
5069
- }
5070
- }
5071
- }
5072
-
5073
- // Allow native Tab when the bib contains focusable content
5074
- // (e.g. counter buttons) that needs normal Tab navigation.
5075
- if (event.key === 'Tab' && this.nativeFocusableContent) {
5076
- return;
5077
- }
5078
-
5079
- event.preventDefault();
5080
- event.stopPropagation();
5081
- const newEvent = new KeyboardEvent('keydown', {
5082
- key: event.key,
5083
- code: event.code,
5084
- shiftKey: event.shiftKey,
5085
- altKey: event.altKey,
5086
- ctrlKey: event.ctrlKey,
5087
- metaKey: event.metaKey,
5088
- bubbles: true,
5089
- composed: true,
5090
- cancelable: true
5091
- });
5092
- this.dispatchEvent(newEvent);
5093
- });
5094
- }
5095
5131
 
5096
5132
  /**
5097
5133
  * Blocks touch-driven page scroll while a fullscreen modal dialog is open.
@@ -5466,7 +5502,7 @@ class AuroHelpText extends LitElement {
5466
5502
  }
5467
5503
  }
5468
5504
 
5469
- var formkitVersion = '202603261553';
5505
+ var formkitVersion = '202604012043';
5470
5506
 
5471
5507
  let AuroElement$1 = class AuroElement extends LitElement {
5472
5508
  static get properties() {
@@ -5647,7 +5683,6 @@ class AuroDropdown extends AuroElement$1 {
5647
5683
  this.appearance = 'default';
5648
5684
  this.chevron = false;
5649
5685
  this.disabled = false;
5650
- this.disableFocusTrap = false;
5651
5686
  this.error = false;
5652
5687
  this.tabIndex = 0;
5653
5688
  this.noToggle = false;
@@ -5745,9 +5780,8 @@ class AuroDropdown extends AuroElement$1 {
5745
5780
  // showModal() fires asynchronously via Lit's update cycle, which
5746
5781
  // falls outside the user activation window and causes iOS to
5747
5782
  // dismiss the keyboard.
5748
- if (this.isBibFullscreen && this.bibElement && this.bibElement.value) {
5749
- const useModal = !this.disableFocusTrap;
5750
- this.bibElement.value.open(useModal);
5783
+ if (this.bibElement && this.bibElement.value) {
5784
+ this.bibElement.value.open(this.isBibFullscreen);
5751
5785
  }
5752
5786
  }
5753
5787
 
@@ -5860,14 +5894,6 @@ class AuroDropdown extends AuroElement$1 {
5860
5894
  reflect: true
5861
5895
  },
5862
5896
 
5863
- /**
5864
- * If declared, the focus trap inside of bib will be turned off.
5865
- */
5866
- disableFocusTrap: {
5867
- type: Boolean,
5868
- reflect: true
5869
- },
5870
-
5871
5897
  /**
5872
5898
  * @private
5873
5899
  */
@@ -6141,7 +6167,7 @@ class AuroDropdown extends AuroElement$1 {
6141
6167
  if (this.isPopoverVisible) {
6142
6168
  // Fullscreen: use showModal() for native accessibility (inert outside, focus trap)
6143
6169
  // Desktop: use show() for Floating UI positioning + FocusTrap for focus management
6144
- const useModal = this.isBibFullscreen && !this.disableFocusTrap;
6170
+ const useModal = this.isBibFullscreen;
6145
6171
  this.bibElement.value.open(useModal);
6146
6172
  } else {
6147
6173
  this.bibElement.value.close();
@@ -6151,7 +6177,7 @@ class AuroDropdown extends AuroElement$1 {
6151
6177
  // When fullscreen strategy changes while open, re-open dialog with correct mode
6152
6178
  // (e.g. resizing from desktop → mobile while dropdown is open)
6153
6179
  if (changedProperties.has('isBibFullscreen') && this.isPopoverVisible && this.bibElement.value) {
6154
- const useModal = this.isBibFullscreen && !this.disableFocusTrap;
6180
+ const useModal = this.isBibFullscreen;
6155
6181
  this.bibElement.value.close();
6156
6182
  this.bibElement.value.open(useModal);
6157
6183
  }
@@ -6263,7 +6289,7 @@ class AuroDropdown extends AuroElement$1 {
6263
6289
  * @private
6264
6290
  */
6265
6291
  updateFocusTrap() {
6266
- if (this.isPopoverVisible && !this.disableFocusTrap) {
6292
+ if (this.isPopoverVisible) {
6267
6293
  if (!this.isBibFullscreen) {
6268
6294
  // Desktop: show() doesn't trap focus, so use FocusTrap
6269
6295
  this.focusTrap = new FocusTrap(this.bibContent);
@@ -7463,6 +7489,7 @@ class AuroCounterGroup extends AuroElement {
7463
7489
  counter.addEventListener("input", this.updateValue);
7464
7490
  counter.addEventListener("auroFormElement-validated", this.updateValidity);
7465
7491
  });
7492
+ this.updateValue();
7466
7493
  }
7467
7494
 
7468
7495
  /**
@@ -7593,6 +7620,8 @@ class AuroCounterGroup extends AuroElement {
7593
7620
  counter.addEventListener("auroFormElement-validated", this.updateValidity);
7594
7621
  });
7595
7622
 
7623
+ this.updateValue();
7624
+
7596
7625
  if (this.isDropdown) {
7597
7626
  this.configureBibtemplate();
7598
7627
  }
@@ -7612,11 +7641,6 @@ class AuroCounterGroup extends AuroElement {
7612
7641
 
7613
7642
  // Focus close button when fullscreen dialog opens
7614
7643
  this.dropdown.addEventListener('auroDropdown-toggled', () => {
7615
- // Tell the bib's keyboard bridge to allow native Tab so focus
7616
- // moves between the real focusable counter elements in the bib.
7617
- if (this.dropdown.bibContent) {
7618
- this.dropdown.bibContent.nativeFocusableContent = true;
7619
- }
7620
7644
  if (this.dropdown.isPopoverVisible && this.dropdown.isBibFullscreen) {
7621
7645
  doubleRaf(() => {
7622
7646
  this.bibtemplate.focusCloseButton();
@@ -7813,7 +7837,6 @@ class AuroCounterGroup extends AuroElement {
7813
7837
  renderCounterDropdown() {
7814
7838
  return html`
7815
7839
  <${this.dropdownTag}
7816
- noHideOnThisFocusLoss
7817
7840
  chevron
7818
7841
  part="dropdown"
7819
7842
  appearance="${this.onDark ? 'inverse' : this.appearance}"
@@ -0,0 +1,4 @@
1
+ export namespace keyboardStrategy {
2
+ function ArrowUp(component: any, _evt: any): void;
3
+ function ArrowDown(component: any, _evt: any): void;
4
+ }