@aurodesignsystem-dev/auro-formkit 0.0.0-pr1404.0 → 0.0.0-pr1405.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 (43) hide show
  1. package/components/checkbox/demo/api.min.js +1 -1
  2. package/components/checkbox/demo/index.min.js +1 -1
  3. package/components/checkbox/dist/index.js +1 -1
  4. package/components/checkbox/dist/registered.js +1 -1
  5. package/components/combobox/demo/api.min.js +114 -29
  6. package/components/combobox/demo/index.min.js +114 -29
  7. package/components/combobox/dist/auro-combobox.d.ts +2 -0
  8. package/components/combobox/dist/comboboxKeyboardStrategy.d.ts +1 -1
  9. package/components/combobox/dist/index.js +108 -17
  10. package/components/combobox/dist/registered.js +108 -17
  11. package/components/counter/demo/api.min.js +2 -2
  12. package/components/counter/demo/index.min.js +2 -2
  13. package/components/counter/dist/index.js +2 -2
  14. package/components/counter/dist/registered.js +2 -2
  15. package/components/datepicker/demo/api.min.js +3 -3
  16. package/components/datepicker/demo/index.min.js +3 -3
  17. package/components/datepicker/dist/index.js +3 -3
  18. package/components/datepicker/dist/registered.js +3 -3
  19. package/components/dropdown/demo/api.min.js +1 -1
  20. package/components/dropdown/demo/index.min.js +1 -1
  21. package/components/dropdown/dist/index.js +1 -1
  22. package/components/dropdown/dist/registered.js +1 -1
  23. package/components/form/demo/api.min.js +131 -39
  24. package/components/form/demo/index.min.js +131 -39
  25. package/components/input/demo/api.min.js +1 -1
  26. package/components/input/demo/index.min.js +1 -1
  27. package/components/input/dist/index.js +1 -1
  28. package/components/input/dist/registered.js +1 -1
  29. package/components/menu/demo/api.min.js +6 -12
  30. package/components/menu/demo/index.min.js +6 -12
  31. package/components/menu/dist/auro-menu.d.ts +1 -1
  32. package/components/menu/dist/index.js +6 -12
  33. package/components/menu/dist/registered.js +6 -12
  34. package/components/radio/demo/api.min.js +1 -1
  35. package/components/radio/demo/index.min.js +1 -1
  36. package/components/radio/dist/index.js +1 -1
  37. package/components/radio/dist/registered.js +1 -1
  38. package/components/select/demo/api.min.js +15 -14
  39. package/components/select/demo/index.min.js +15 -14
  40. package/components/select/dist/index.js +9 -2
  41. package/components/select/dist/registered.js +9 -2
  42. package/custom-elements.json +1 -1
  43. package/package.json +1 -1
@@ -1687,7 +1687,7 @@ class AuroHelpText extends i$2 {
1687
1687
  }
1688
1688
  }
1689
1689
 
1690
- var formkitVersion = '202603271802';
1690
+ var formkitVersion = '202603271850';
1691
1691
 
1692
1692
  // Copyright (c) 2026 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
1693
1693
  // See LICENSE in the project root for license information.
@@ -1679,7 +1679,7 @@ class AuroHelpText extends i$2 {
1679
1679
  }
1680
1680
  }
1681
1681
 
1682
- var formkitVersion = '202603271802';
1682
+ var formkitVersion = '202603271850';
1683
1683
 
1684
1684
  // Copyright (c) 2026 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
1685
1685
  // See LICENSE in the project root for license information.
@@ -1632,7 +1632,7 @@ class AuroHelpText extends LitElement {
1632
1632
  }
1633
1633
  }
1634
1634
 
1635
- var formkitVersion = '202603271802';
1635
+ var formkitVersion = '202603271850';
1636
1636
 
1637
1637
  // Copyright (c) 2026 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
1638
1638
  // See LICENSE in the project root for license information.
@@ -1632,7 +1632,7 @@ class AuroHelpText extends LitElement {
1632
1632
  }
1633
1633
  }
1634
1634
 
1635
- var formkitVersion = '202603271802';
1635
+ var formkitVersion = '202603271850';
1636
1636
 
1637
1637
  // Copyright (c) 2026 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
1638
1638
  // See LICENSE in the project root for license information.
@@ -1300,6 +1300,8 @@ function navigateArrow(component, direction, options = {}) {
1300
1300
  }
1301
1301
  }
1302
1302
 
1303
+ /* eslint-disable no-underscore-dangle */
1304
+
1303
1305
  /**
1304
1306
  * Returns the clear button element from the active input's shadow
1305
1307
  * DOM, if available.
@@ -1330,7 +1332,7 @@ function isClearBtnFocused(ctx, clearBtn = getClearBtn(ctx)) {
1330
1332
  }
1331
1333
 
1332
1334
  const comboboxKeyboardStrategy = {
1333
- async Enter(component, evt, ctx) {
1335
+ Enter(component, evt, ctx) {
1334
1336
  // If the clear button has focus, let the browser activate it normally.
1335
1337
  // stopPropagation prevents parent containers (e.g., forms) from treating
1336
1338
  // Enter as a submit, but we must NOT call preventDefault — that would
@@ -1341,11 +1343,15 @@ const comboboxKeyboardStrategy = {
1341
1343
  }
1342
1344
 
1343
1345
  if (ctx.isExpanded && component.optionActive) {
1344
- component.menu.makeSelection();
1345
- await component.updateComplete;
1346
1346
  evt.preventDefault();
1347
1347
  evt.stopPropagation();
1348
- component.setClearBtnFocus();
1348
+ // Set flags before makeSelection so the showBib guard and the
1349
+ // auroDropdown-toggled close handler both see them when the value
1350
+ // change propagates through Lit's microtask update cycle.
1351
+ component._focusClearBtnAfterClose = true;
1352
+ component._clearBtnFocusPending = true;
1353
+ component.menu.makeSelection();
1354
+ component.hideBib();
1349
1355
  } else {
1350
1356
  // Prevent the keypress from bubbling to parent containers (e.g., forms)
1351
1357
  // which could interpret Enter as a submit or trigger other unintended behavior.
@@ -1377,15 +1383,32 @@ const comboboxKeyboardStrategy = {
1377
1383
  if (!ctx.activeInput) {
1378
1384
  return;
1379
1385
  }
1386
+
1387
+ // Active option → select immediately and close the dialog.
1388
+ // Flag the component so the close handler focuses the trigger's
1389
+ // clear button instead of the input. Set flags before makeSelection
1390
+ // because the value change triggers showBib via Lit's updated().
1391
+ if (component.optionActive) {
1392
+ evt.preventDefault();
1393
+ component._focusClearBtnAfterClose = true;
1394
+ component._clearBtnFocusPending = true;
1395
+ component.menu.makeSelection();
1396
+ component.hideBib();
1397
+ return;
1398
+ }
1399
+
1380
1400
  const clearBtn = getClearBtn(ctx);
1381
1401
  const clearBtnHasFocus = isClearBtnFocused(ctx, clearBtn);
1382
1402
 
1383
- // Tab from input: if clear button exists and doesn't have focus, focus it
1403
+ // No active option, input has a value, clear button not focused
1404
+ // move focus to the dialog's clear button.
1384
1405
  if (clearBtn && !clearBtnHasFocus && ctx.activeInput.value) {
1406
+
1385
1407
  // Force clear button container visible to work around Safari not
1386
1408
  // propagating :focus-within through shadow DOM boundaries, which
1387
1409
  // causes .wrapper:not(:focus-within) to hide .notification.clear.
1388
1410
  const clearContainer = clearBtn.closest('.clear');
1411
+
1389
1412
  if (clearContainer) {
1390
1413
  clearContainer.style.display = 'flex';
1391
1414
  clearBtn.addEventListener('focusout', () => {
@@ -1408,18 +1431,17 @@ const comboboxKeyboardStrategy = {
1408
1431
  return;
1409
1432
  }
1410
1433
 
1411
- // Tab from clear button (or no clear button / no value) →
1412
- // select the highlighted option if any, then close
1413
- if (component.optionActive) {
1414
- component.menu.makeSelection();
1415
- }
1434
+ // No active option, no clear button (or already focused) → just close.
1416
1435
  component.hideBib();
1417
1436
  return;
1418
1437
  }
1419
1438
 
1420
1439
  // Non-fullscreen: select + close
1421
- if (component.menu.optionActive && component.menu.optionActive.value) {
1422
- component.menu.value = component.menu.optionActive.value;
1440
+ if (component.optionActive) {
1441
+ evt.preventDefault();
1442
+ component._focusClearBtnAfterClose = true;
1443
+ component._clearBtnFocusPending = true;
1444
+ component.menu.makeSelection();
1423
1445
  }
1424
1446
  component.hideBib();
1425
1447
  },
@@ -5070,7 +5092,7 @@ let AuroHelpText$2 = class AuroHelpText extends i$4 {
5070
5092
  }
5071
5093
  };
5072
5094
 
5073
- var formkitVersion$2 = '202603271802';
5095
+ var formkitVersion$2 = '202603271850';
5074
5096
 
5075
5097
  let AuroElement$2 = class AuroElement extends i$4 {
5076
5098
  static get properties() {
@@ -12834,7 +12856,7 @@ let AuroHelpText$1 = class AuroHelpText extends i$4 {
12834
12856
  }
12835
12857
  };
12836
12858
 
12837
- var formkitVersion$1 = '202603271802';
12859
+ var formkitVersion$1 = '202603271850';
12838
12860
 
12839
12861
  // Copyright (c) 2025 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
12840
12862
  // See LICENSE in the project root for license information.
@@ -13873,7 +13895,7 @@ class AuroBibtemplate extends i$4 {
13873
13895
  }
13874
13896
  }
13875
13897
 
13876
- var formkitVersion = '202603271802';
13898
+ var formkitVersion = '202603271850';
13877
13899
 
13878
13900
  var styleCss$3 = i$7`.util_displayInline{display:inline}.util_displayInlineBlock{display:inline-block}.util_displayBlock{display:block}.util_displayFlex{display:flex}.util_displayHidden{display:none}.util_displayHiddenVisually{position:absolute;overflow:hidden;clip:rect(1px, 1px, 1px, 1px);width:1px;height:1px;padding:0;border:0}:host{display:block;text-align:left}:host [auro-dropdown]{--ds-auro-dropdown-trigger-background-color: transparent}:host #inputInBib::part(wrapper){box-shadow:none}:host #inputInBib::part(accent-left){display:none}:host([layout*=classic]) [auro-input]{width:100%}:host([layout*=classic]) [auro-input]::part(helpText){display:none}:host([layout*=classic]) #slotHolder{display:none}`;
13879
13901
 
@@ -14883,6 +14905,12 @@ class AuroCombobox extends AuroElement {
14883
14905
  * @returns {void}
14884
14906
  */
14885
14907
  showBib() {
14908
+ // Suppress reopening the bib when a Tab selection is in progress —
14909
+ // the value change from makeSelection triggers availableOptions update
14910
+ // which calls showBib from updated(), but the bib should stay closed.
14911
+ if (this._clearBtnFocusPending) {
14912
+ return;
14913
+ }
14886
14914
  if (!this.input.value && !this.dropdown.isBibFullscreen) {
14887
14915
  this.dropdown.hide();
14888
14916
  return;
@@ -14953,7 +14981,49 @@ class AuroCombobox extends AuroElement {
14953
14981
  // during fullscreen open to prevent touch pass-through.
14954
14982
  this.menu.style.pointerEvents = '';
14955
14983
 
14956
- restoreTriggerAfterClose(this.dropdown, this.input);
14984
+ // Close the fullscreen dialog synchronously so the browser's native
14985
+ // focus restoration (back to document.body) happens NOW, before the
14986
+ // rAF in restoreTriggerAfterClose. Without this, dialog.close() runs
14987
+ // in Lit's async update cycle and can race with the rAF — in some
14988
+ // browsers the dialog steals focus back to body AFTER the rAF has
14989
+ // already placed it on the trigger input.
14990
+ const bibEl = this.dropdown.bibElement && this.dropdown.bibElement.value;
14991
+ if (bibEl) {
14992
+ bibEl.close();
14993
+ }
14994
+
14995
+ const shouldFocusClearBtn = this._focusClearBtnAfterClose;
14996
+ this._focusClearBtnAfterClose = false;
14997
+
14998
+ if (shouldFocusClearBtn) {
14999
+ // Set a guard so duplicate toggle events don't call
15000
+ // restoreTriggerAfterClose and steal focus from the clear button.
15001
+ this._clearBtnFocusPending = true;
15002
+
15003
+ restoreTriggerAfterClose(this.dropdown, this.input);
15004
+
15005
+ if (this.input.componentHasFocus) {
15006
+ // Desktop: input already has focus, redirect to clear button
15007
+ // after restoreTriggerAfterClose's rAF settles.
15008
+ requestAnimationFrame(() => {
15009
+ this.setClearBtnFocus();
15010
+ this._clearBtnFocusPending = false;
15011
+ });
15012
+ } else {
15013
+ // Fullscreen: input will receive focus after dialog.close().
15014
+ // Listen for that focus event then redirect to clear button.
15015
+ const onFocus = () => {
15016
+ this.input.removeEventListener('focusin', onFocus);
15017
+ requestAnimationFrame(() => {
15018
+ this.setClearBtnFocus();
15019
+ this._clearBtnFocusPending = false;
15020
+ });
15021
+ };
15022
+ this.input.addEventListener('focusin', onFocus);
15023
+ }
15024
+ } else if (!this._clearBtnFocusPending) {
15025
+ restoreTriggerAfterClose(this.dropdown, this.input);
15026
+ }
14957
15027
  }
14958
15028
 
14959
15029
  if (this.dropdownOpen) {
@@ -15044,7 +15114,28 @@ class AuroCombobox extends AuroElement {
15044
15114
  setClearBtnFocus() {
15045
15115
  const clearBtn = this.input.shadowRoot.querySelector('.clearBtn');
15046
15116
  if (clearBtn) {
15047
- clearBtn.focus();
15117
+ // Force the clear button container visible — without :focus-within
15118
+ // the CSS rule `.wrapper:not(:focus-within) .notification.clear`
15119
+ // hides the container with display:none, preventing focus.
15120
+ const clearContainer = clearBtn.closest('.clear');
15121
+
15122
+ if (clearContainer) {
15123
+ clearContainer.style.display = 'flex';
15124
+ clearBtn.addEventListener('focusout', () => {
15125
+ requestAnimationFrame(() => {
15126
+ clearContainer.style.display = '';
15127
+ });
15128
+ }, { once: true });
15129
+ }
15130
+
15131
+ // Focus the native button inside auro-button so the browser
15132
+ // treats it as a real focusable element.
15133
+ const nativeBtn = clearBtn.shadowRoot && clearBtn.shadowRoot.querySelector('button');
15134
+ if (nativeBtn) {
15135
+ nativeBtn.focus();
15136
+ } else {
15137
+ clearBtn.focus();
15138
+ }
15048
15139
  }
15049
15140
  }
15050
15141
 
@@ -17399,10 +17490,6 @@ class AuroMenu extends AuroElement {
17399
17490
  * @protected
17400
17491
  */
17401
17492
  provideContext() {
17402
- if (!this.rootMenu) {
17403
- return;
17404
- }
17405
-
17406
17493
  this.menuService = new MenuService({host: this});
17407
17494
  this.menuService.setProperties(this.propertyValues);
17408
17495
  this.menuService.subscribe(this.handleMenuChange.bind(this));
@@ -17494,10 +17581,6 @@ class AuroMenu extends AuroElement {
17494
17581
  connectedCallback() {
17495
17582
  super.connectedCallback();
17496
17583
 
17497
- if (this.parentElement && this.parentElement.closest('auro-menu, [auro-menu]')) {
17498
- this.rootMenu = false;
17499
- }
17500
-
17501
17584
  this.provideContext();
17502
17585
 
17503
17586
  this.addEventListener('keydown', this.handleKeyDown);
@@ -17589,9 +17672,9 @@ class AuroMenu extends AuroElement {
17589
17672
  if (this.multiSelect) {
17590
17673
  this.setAttribute('aria-multiselectable', 'true');
17591
17674
  }
17592
- }
17593
17675
 
17594
- this.handleNestedMenus(this);
17676
+ this.handleNestedMenus(this);
17677
+ }
17595
17678
  }
17596
17679
 
17597
17680
  /**
@@ -17635,8 +17718,6 @@ class AuroMenu extends AuroElement {
17635
17718
  if (menu.level > 0) {
17636
17719
  menu.setAttribute('role', 'group');
17637
17720
  menu.removeAttribute("root");
17638
- menu.menuService = menu.parentElement.menuService;
17639
- menu._contextProvider = menu.parentElement._contextProvider;
17640
17721
  if (!menu.hasAttribute('aria-label')) {
17641
17722
  menu.setAttribute('aria-label', 'submenu');
17642
17723
  }
@@ -17690,6 +17771,10 @@ class AuroMenu extends AuroElement {
17690
17771
  * @private
17691
17772
  */
17692
17773
  handleSlotChange() {
17774
+ if (this.parentElement && this.parentElement.closest('auro-menu, [auro-menu]')) {
17775
+ this.rootMenu = false;
17776
+ }
17777
+
17693
17778
  if (this.rootMenu) {
17694
17779
  this.initializeMenu();
17695
17780
  }
@@ -1223,6 +1223,8 @@ function navigateArrow(component, direction, options = {}) {
1223
1223
  }
1224
1224
  }
1225
1225
 
1226
+ /* eslint-disable no-underscore-dangle */
1227
+
1226
1228
  /**
1227
1229
  * Returns the clear button element from the active input's shadow
1228
1230
  * DOM, if available.
@@ -1253,7 +1255,7 @@ function isClearBtnFocused(ctx, clearBtn = getClearBtn(ctx)) {
1253
1255
  }
1254
1256
 
1255
1257
  const comboboxKeyboardStrategy = {
1256
- async Enter(component, evt, ctx) {
1258
+ Enter(component, evt, ctx) {
1257
1259
  // If the clear button has focus, let the browser activate it normally.
1258
1260
  // stopPropagation prevents parent containers (e.g., forms) from treating
1259
1261
  // Enter as a submit, but we must NOT call preventDefault — that would
@@ -1264,11 +1266,15 @@ const comboboxKeyboardStrategy = {
1264
1266
  }
1265
1267
 
1266
1268
  if (ctx.isExpanded && component.optionActive) {
1267
- component.menu.makeSelection();
1268
- await component.updateComplete;
1269
1269
  evt.preventDefault();
1270
1270
  evt.stopPropagation();
1271
- component.setClearBtnFocus();
1271
+ // Set flags before makeSelection so the showBib guard and the
1272
+ // auroDropdown-toggled close handler both see them when the value
1273
+ // change propagates through Lit's microtask update cycle.
1274
+ component._focusClearBtnAfterClose = true;
1275
+ component._clearBtnFocusPending = true;
1276
+ component.menu.makeSelection();
1277
+ component.hideBib();
1272
1278
  } else {
1273
1279
  // Prevent the keypress from bubbling to parent containers (e.g., forms)
1274
1280
  // which could interpret Enter as a submit or trigger other unintended behavior.
@@ -1300,15 +1306,32 @@ const comboboxKeyboardStrategy = {
1300
1306
  if (!ctx.activeInput) {
1301
1307
  return;
1302
1308
  }
1309
+
1310
+ // Active option → select immediately and close the dialog.
1311
+ // Flag the component so the close handler focuses the trigger's
1312
+ // clear button instead of the input. Set flags before makeSelection
1313
+ // because the value change triggers showBib via Lit's updated().
1314
+ if (component.optionActive) {
1315
+ evt.preventDefault();
1316
+ component._focusClearBtnAfterClose = true;
1317
+ component._clearBtnFocusPending = true;
1318
+ component.menu.makeSelection();
1319
+ component.hideBib();
1320
+ return;
1321
+ }
1322
+
1303
1323
  const clearBtn = getClearBtn(ctx);
1304
1324
  const clearBtnHasFocus = isClearBtnFocused(ctx, clearBtn);
1305
1325
 
1306
- // Tab from input: if clear button exists and doesn't have focus, focus it
1326
+ // No active option, input has a value, clear button not focused
1327
+ // move focus to the dialog's clear button.
1307
1328
  if (clearBtn && !clearBtnHasFocus && ctx.activeInput.value) {
1329
+
1308
1330
  // Force clear button container visible to work around Safari not
1309
1331
  // propagating :focus-within through shadow DOM boundaries, which
1310
1332
  // causes .wrapper:not(:focus-within) to hide .notification.clear.
1311
1333
  const clearContainer = clearBtn.closest('.clear');
1334
+
1312
1335
  if (clearContainer) {
1313
1336
  clearContainer.style.display = 'flex';
1314
1337
  clearBtn.addEventListener('focusout', () => {
@@ -1331,18 +1354,17 @@ const comboboxKeyboardStrategy = {
1331
1354
  return;
1332
1355
  }
1333
1356
 
1334
- // Tab from clear button (or no clear button / no value) →
1335
- // select the highlighted option if any, then close
1336
- if (component.optionActive) {
1337
- component.menu.makeSelection();
1338
- }
1357
+ // No active option, no clear button (or already focused) → just close.
1339
1358
  component.hideBib();
1340
1359
  return;
1341
1360
  }
1342
1361
 
1343
1362
  // Non-fullscreen: select + close
1344
- if (component.menu.optionActive && component.menu.optionActive.value) {
1345
- component.menu.value = component.menu.optionActive.value;
1363
+ if (component.optionActive) {
1364
+ evt.preventDefault();
1365
+ component._focusClearBtnAfterClose = true;
1366
+ component._clearBtnFocusPending = true;
1367
+ component.menu.makeSelection();
1346
1368
  }
1347
1369
  component.hideBib();
1348
1370
  },
@@ -4993,7 +5015,7 @@ let AuroHelpText$2 = class AuroHelpText extends i$4 {
4993
5015
  }
4994
5016
  };
4995
5017
 
4996
- var formkitVersion$2 = '202603271802';
5018
+ var formkitVersion$2 = '202603271850';
4997
5019
 
4998
5020
  let AuroElement$2 = class AuroElement extends i$4 {
4999
5021
  static get properties() {
@@ -12757,7 +12779,7 @@ let AuroHelpText$1 = class AuroHelpText extends i$4 {
12757
12779
  }
12758
12780
  };
12759
12781
 
12760
- var formkitVersion$1 = '202603271802';
12782
+ var formkitVersion$1 = '202603271850';
12761
12783
 
12762
12784
  // Copyright (c) 2025 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
12763
12785
  // See LICENSE in the project root for license information.
@@ -13796,7 +13818,7 @@ class AuroBibtemplate extends i$4 {
13796
13818
  }
13797
13819
  }
13798
13820
 
13799
- var formkitVersion = '202603271802';
13821
+ var formkitVersion = '202603271850';
13800
13822
 
13801
13823
  var styleCss$3 = i$7`.util_displayInline{display:inline}.util_displayInlineBlock{display:inline-block}.util_displayBlock{display:block}.util_displayFlex{display:flex}.util_displayHidden{display:none}.util_displayHiddenVisually{position:absolute;overflow:hidden;clip:rect(1px, 1px, 1px, 1px);width:1px;height:1px;padding:0;border:0}:host{display:block;text-align:left}:host [auro-dropdown]{--ds-auro-dropdown-trigger-background-color: transparent}:host #inputInBib::part(wrapper){box-shadow:none}:host #inputInBib::part(accent-left){display:none}:host([layout*=classic]) [auro-input]{width:100%}:host([layout*=classic]) [auro-input]::part(helpText){display:none}:host([layout*=classic]) #slotHolder{display:none}`;
13802
13824
 
@@ -14806,6 +14828,12 @@ class AuroCombobox extends AuroElement {
14806
14828
  * @returns {void}
14807
14829
  */
14808
14830
  showBib() {
14831
+ // Suppress reopening the bib when a Tab selection is in progress —
14832
+ // the value change from makeSelection triggers availableOptions update
14833
+ // which calls showBib from updated(), but the bib should stay closed.
14834
+ if (this._clearBtnFocusPending) {
14835
+ return;
14836
+ }
14809
14837
  if (!this.input.value && !this.dropdown.isBibFullscreen) {
14810
14838
  this.dropdown.hide();
14811
14839
  return;
@@ -14876,7 +14904,49 @@ class AuroCombobox extends AuroElement {
14876
14904
  // during fullscreen open to prevent touch pass-through.
14877
14905
  this.menu.style.pointerEvents = '';
14878
14906
 
14879
- restoreTriggerAfterClose(this.dropdown, this.input);
14907
+ // Close the fullscreen dialog synchronously so the browser's native
14908
+ // focus restoration (back to document.body) happens NOW, before the
14909
+ // rAF in restoreTriggerAfterClose. Without this, dialog.close() runs
14910
+ // in Lit's async update cycle and can race with the rAF — in some
14911
+ // browsers the dialog steals focus back to body AFTER the rAF has
14912
+ // already placed it on the trigger input.
14913
+ const bibEl = this.dropdown.bibElement && this.dropdown.bibElement.value;
14914
+ if (bibEl) {
14915
+ bibEl.close();
14916
+ }
14917
+
14918
+ const shouldFocusClearBtn = this._focusClearBtnAfterClose;
14919
+ this._focusClearBtnAfterClose = false;
14920
+
14921
+ if (shouldFocusClearBtn) {
14922
+ // Set a guard so duplicate toggle events don't call
14923
+ // restoreTriggerAfterClose and steal focus from the clear button.
14924
+ this._clearBtnFocusPending = true;
14925
+
14926
+ restoreTriggerAfterClose(this.dropdown, this.input);
14927
+
14928
+ if (this.input.componentHasFocus) {
14929
+ // Desktop: input already has focus, redirect to clear button
14930
+ // after restoreTriggerAfterClose's rAF settles.
14931
+ requestAnimationFrame(() => {
14932
+ this.setClearBtnFocus();
14933
+ this._clearBtnFocusPending = false;
14934
+ });
14935
+ } else {
14936
+ // Fullscreen: input will receive focus after dialog.close().
14937
+ // Listen for that focus event then redirect to clear button.
14938
+ const onFocus = () => {
14939
+ this.input.removeEventListener('focusin', onFocus);
14940
+ requestAnimationFrame(() => {
14941
+ this.setClearBtnFocus();
14942
+ this._clearBtnFocusPending = false;
14943
+ });
14944
+ };
14945
+ this.input.addEventListener('focusin', onFocus);
14946
+ }
14947
+ } else if (!this._clearBtnFocusPending) {
14948
+ restoreTriggerAfterClose(this.dropdown, this.input);
14949
+ }
14880
14950
  }
14881
14951
 
14882
14952
  if (this.dropdownOpen) {
@@ -14967,7 +15037,28 @@ class AuroCombobox extends AuroElement {
14967
15037
  setClearBtnFocus() {
14968
15038
  const clearBtn = this.input.shadowRoot.querySelector('.clearBtn');
14969
15039
  if (clearBtn) {
14970
- clearBtn.focus();
15040
+ // Force the clear button container visible — without :focus-within
15041
+ // the CSS rule `.wrapper:not(:focus-within) .notification.clear`
15042
+ // hides the container with display:none, preventing focus.
15043
+ const clearContainer = clearBtn.closest('.clear');
15044
+
15045
+ if (clearContainer) {
15046
+ clearContainer.style.display = 'flex';
15047
+ clearBtn.addEventListener('focusout', () => {
15048
+ requestAnimationFrame(() => {
15049
+ clearContainer.style.display = '';
15050
+ });
15051
+ }, { once: true });
15052
+ }
15053
+
15054
+ // Focus the native button inside auro-button so the browser
15055
+ // treats it as a real focusable element.
15056
+ const nativeBtn = clearBtn.shadowRoot && clearBtn.shadowRoot.querySelector('button');
15057
+ if (nativeBtn) {
15058
+ nativeBtn.focus();
15059
+ } else {
15060
+ clearBtn.focus();
15061
+ }
14971
15062
  }
14972
15063
  }
14973
15064
 
@@ -17322,10 +17413,6 @@ class AuroMenu extends AuroElement {
17322
17413
  * @protected
17323
17414
  */
17324
17415
  provideContext() {
17325
- if (!this.rootMenu) {
17326
- return;
17327
- }
17328
-
17329
17416
  this.menuService = new MenuService({host: this});
17330
17417
  this.menuService.setProperties(this.propertyValues);
17331
17418
  this.menuService.subscribe(this.handleMenuChange.bind(this));
@@ -17417,10 +17504,6 @@ class AuroMenu extends AuroElement {
17417
17504
  connectedCallback() {
17418
17505
  super.connectedCallback();
17419
17506
 
17420
- if (this.parentElement && this.parentElement.closest('auro-menu, [auro-menu]')) {
17421
- this.rootMenu = false;
17422
- }
17423
-
17424
17507
  this.provideContext();
17425
17508
 
17426
17509
  this.addEventListener('keydown', this.handleKeyDown);
@@ -17512,9 +17595,9 @@ class AuroMenu extends AuroElement {
17512
17595
  if (this.multiSelect) {
17513
17596
  this.setAttribute('aria-multiselectable', 'true');
17514
17597
  }
17515
- }
17516
17598
 
17517
- this.handleNestedMenus(this);
17599
+ this.handleNestedMenus(this);
17600
+ }
17518
17601
  }
17519
17602
 
17520
17603
  /**
@@ -17558,8 +17641,6 @@ class AuroMenu extends AuroElement {
17558
17641
  if (menu.level > 0) {
17559
17642
  menu.setAttribute('role', 'group');
17560
17643
  menu.removeAttribute("root");
17561
- menu.menuService = menu.parentElement.menuService;
17562
- menu._contextProvider = menu.parentElement._contextProvider;
17563
17644
  if (!menu.hasAttribute('aria-label')) {
17564
17645
  menu.setAttribute('aria-label', 'submenu');
17565
17646
  }
@@ -17613,6 +17694,10 @@ class AuroMenu extends AuroElement {
17613
17694
  * @private
17614
17695
  */
17615
17696
  handleSlotChange() {
17697
+ if (this.parentElement && this.parentElement.closest('auro-menu, [auro-menu]')) {
17698
+ this.rootMenu = false;
17699
+ }
17700
+
17616
17701
  if (this.rootMenu) {
17617
17702
  this.initializeMenu();
17618
17703
  }
@@ -428,6 +428,8 @@ export class AuroCombobox extends AuroElement {
428
428
  * @returns {void}
429
429
  */
430
430
  private configureDropdown;
431
+ _focusClearBtnAfterClose: boolean;
432
+ _clearBtnFocusPending: boolean;
431
433
  bibtemplate: any;
432
434
  inputInBib: any;
433
435
  /**
@@ -1,5 +1,5 @@
1
1
  export namespace comboboxKeyboardStrategy {
2
- function Enter(component: any, evt: any, ctx: any): Promise<void>;
2
+ function Enter(component: any, evt: any, ctx: any): void;
3
3
  function Tab(component: any, evt: any, ctx: any): void;
4
4
  function ArrowUp(component: any, evt: any, ctx: any): void;
5
5
  function ArrowDown(component: any, evt: any, ctx: any): void;