@aurodesignsystem-dev/auro-formkit 0.0.0-pr1431.2 → 0.0.0-pr1433.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 +235 -47
  6. package/components/combobox/demo/index.min.js +235 -47
  7. package/components/combobox/dist/auro-combobox.d.ts +4 -0
  8. package/components/combobox/dist/index.js +144 -24
  9. package/components/combobox/dist/registered.js +144 -24
  10. package/components/counter/demo/api.min.js +30 -2
  11. package/components/counter/demo/index.min.js +30 -2
  12. package/components/counter/dist/index.js +30 -2
  13. package/components/counter/dist/registered.js +30 -2
  14. package/components/datepicker/demo/api.min.js +33 -3
  15. package/components/datepicker/demo/index.min.js +33 -3
  16. package/components/datepicker/dist/index.js +33 -3
  17. package/components/datepicker/dist/registered.js +33 -3
  18. package/components/dropdown/demo/api.min.js +29 -1
  19. package/components/dropdown/demo/index.min.js +29 -1
  20. package/components/dropdown/dist/index.js +29 -1
  21. package/components/dropdown/dist/registered.js +29 -1
  22. package/components/form/demo/api.min.js +331 -57
  23. package/components/form/demo/index.min.js +331 -57
  24. package/components/input/demo/api.min.js +1 -1
  25. package/components/input/demo/index.min.js +1 -1
  26. package/components/input/dist/index.js +1 -1
  27. package/components/input/dist/registered.js +1 -1
  28. package/components/menu/demo/api.md +1 -1
  29. package/components/menu/demo/api.min.js +91 -23
  30. package/components/menu/demo/index.min.js +91 -23
  31. package/components/menu/dist/auro-menuoption.d.ts +2 -0
  32. package/components/menu/dist/index.js +91 -23
  33. package/components/menu/dist/registered.js +91 -23
  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 +121 -25
  39. package/components/select/demo/index.min.js +121 -25
  40. package/components/select/dist/index.js +30 -2
  41. package/components/select/dist/registered.js +30 -2
  42. package/custom-elements.json +422 -411
  43. package/package.json +2 -2
@@ -3206,6 +3206,7 @@ class AuroFloatingUI {
3206
3206
  this.focusHandler = null;
3207
3207
  this.clickHandler = null;
3208
3208
  this.keyDownHandler = null;
3209
+ this.touchHandler = null;
3209
3210
 
3210
3211
  /**
3211
3212
  * @private
@@ -3623,6 +3624,28 @@ class AuroFloatingUI {
3623
3624
  setTimeout(() => {
3624
3625
  window.addEventListener("click", this.clickHandler);
3625
3626
  }, 0);
3627
+
3628
+ // iOS Safari does not fire `click` on non-interactive elements, so
3629
+ // tapping an inert backdrop never reaches the click handler above.
3630
+ // Mirror the same outside-tap logic with a passive touchstart listener.
3631
+ this.touchHandler = (evt) => {
3632
+ const element = this.element;
3633
+ if (!element?.bib) {
3634
+ return;
3635
+ }
3636
+
3637
+ // fullscreen (modal) dialog handles its own dismissal
3638
+ if (element.bib.hasAttribute("isfullscreen")) {
3639
+ return;
3640
+ }
3641
+
3642
+ const path = evt.composedPath();
3643
+ if (!path.includes(element.trigger) && !path.includes(element.bib)) {
3644
+ this.hideBib("click");
3645
+ }
3646
+ };
3647
+
3648
+ window.addEventListener("touchstart", this.touchHandler, { passive: true });
3626
3649
  }
3627
3650
 
3628
3651
  cleanupHideHandlers() {
@@ -3638,6 +3661,11 @@ class AuroFloatingUI {
3638
3661
  this.clickHandler = null;
3639
3662
  }
3640
3663
 
3664
+ if (this.touchHandler) {
3665
+ window.removeEventListener("touchstart", this.touchHandler);
3666
+ this.touchHandler = null;
3667
+ }
3668
+
3641
3669
  if (this.keyDownHandler) {
3642
3670
  document.removeEventListener("keydown", this.keyDownHandler);
3643
3671
  this.keyDownHandler = null;
@@ -5112,7 +5140,7 @@ let AuroHelpText$2 = class AuroHelpText extends i$4 {
5112
5140
  }
5113
5141
  };
5114
5142
 
5115
- var formkitVersion$2 = '202604091435';
5143
+ var formkitVersion$2 = '202604100244';
5116
5144
 
5117
5145
  let AuroElement$2 = class AuroElement extends i$4 {
5118
5146
  static get properties() {
@@ -12876,7 +12904,7 @@ let AuroHelpText$1 = class AuroHelpText extends i$4 {
12876
12904
  }
12877
12905
  };
12878
12906
 
12879
- var formkitVersion$1 = '202604091435';
12907
+ var formkitVersion$1 = '202604100244';
12880
12908
 
12881
12909
  // Copyright (c) 2025 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
12882
12910
  // See LICENSE in the project root for license information.
@@ -13941,11 +13969,11 @@ class AuroBibtemplate extends i$4 {
13941
13969
  }
13942
13970
  }
13943
13971
 
13944
- var formkitVersion = '202604091435';
13972
+ var formkitVersion = '202604100244';
13945
13973
 
13946
13974
  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}`;
13947
13975
 
13948
- var styleEmphasizedCss = i$7`:host([layout*=emphasized][shape*=pill]) [auro-input]{--ds-auro-input-background-color: var(--ds-advanced-color-dropdown-emphasized-background, rgba(0, 39, 74, 0.1019607843));--ds-auro-input-container-color: var(--ds-advanced-color-dropdown-emphasized-background, rgba(0, 39, 74, 0.1019607843))}:host([layout*=emphasized][shape*=pill]) [auro-input]:hover{--ds-auro-input-background-color: var(--ds-advanced-color-dropdown-emphasized-background, rgba(0, 39, 74, 0.1019607843));--ds-auro-input-container-color: var(--ds-advanced-color-dropdown-emphasized-background, rgba(0, 39, 74, 0.1019607843))}:host([layout*=emphasized][shape*=pill]) [auro-input]{width:100%}:host([layout*=emphasized][shape*=pill]) [auro-input]::part(inputHelpText){display:none}:host([layout=emphasized]) [auro-dropdown]{--ds-auro-dropdown-trigger-background-color: var(--ds-advanced-color-dropdown-emphasized-background, rgba(0, 39, 74, 0.1019607843))}:host([layout=emphasized]) [auro-dropdown]:hover{--ds-auro-dropdown-trigger-hover-background-color: var(--ds-advanced-color-dropdown-emphasized-background, rgba(0, 39, 74, 0.1019607843))}:host([layout=emphasized]) [auro-dropdown][layout*=emphasized]::part(wrapper){--ds-auro-dropdown-trigger-background-color: transparent}`;
13976
+ var styleEmphasizedCss = i$7`:host([layout*=emphasized][shape*=pill]) [auro-input][slot=trigger]{--ds-auro-input-background-color: var(--ds-advanced-color-dropdown-emphasized-background, rgba(0, 39, 74, 0.1019607843));--ds-auro-input-container-color: var(--ds-advanced-color-dropdown-emphasized-background, rgba(0, 39, 74, 0.1019607843))}:host([layout*=emphasized][shape*=pill]) [auro-input][slot=trigger]:hover{--ds-auro-input-background-color: var(--ds-advanced-color-dropdown-emphasized-background, rgba(0, 39, 74, 0.1019607843));--ds-auro-input-container-color: var(--ds-advanced-color-dropdown-emphasized-background, rgba(0, 39, 74, 0.1019607843))}:host([layout*=emphasized][shape*=pill]) [auro-input][slot=trigger]{width:100%}:host([layout*=emphasized][shape*=pill]) [auro-input][slot=trigger]::part(inputHelpText){display:none}:host([layout=emphasized]) [auro-dropdown]{--ds-auro-dropdown-trigger-background-color: var(--ds-advanced-color-dropdown-emphasized-background, rgba(0, 39, 74, 0.1019607843))}:host([layout=emphasized]) [auro-dropdown]:hover{--ds-auro-dropdown-trigger-hover-background-color: var(--ds-advanced-color-dropdown-emphasized-background, rgba(0, 39, 74, 0.1019607843))}:host([layout=emphasized]) [auro-dropdown][layout*=emphasized]::part(wrapper){--ds-auro-dropdown-trigger-background-color: transparent}`;
13949
13977
 
13950
13978
  var styleSnowflakeCss = i$7`:host([layout*=snowflake][shape*=snowflake]) [auro-input]{width:100%}:host([layout*=snowflake][shape*=snowflake]) [auro-input]::part(inputHelpText){display:none}:host([layout*=snowflake][shape*=snowflake])::part(helpText){text-align:center}`;
13951
13979
 
@@ -14804,7 +14832,7 @@ class AuroCombobox extends AuroElement {
14804
14832
  * @returns {void}
14805
14833
  */
14806
14834
  activateFirstEnabledAvailableOption() {
14807
- const firstEnabledOptionIndex = this.availableOptions.findIndex((opt) => !opt.disabled && !opt.noMatch);
14835
+ const firstEnabledOptionIndex = this.availableOptions.findIndex((opt) => !opt.disabled && !opt.hasAttribute('nomatch'));
14808
14836
  this.updateActiveOption(firstEnabledOptionIndex);
14809
14837
  }
14810
14838
 
@@ -14818,7 +14846,7 @@ class AuroCombobox extends AuroElement {
14818
14846
 
14819
14847
  // Work backwards through the available options array to find the last enabled option
14820
14848
  for (let index = this.availableOptions.length - 1; index >= 0; index -= 1) {
14821
- if (!this.availableOptions[index].disabled && !this.availableOptions[index].noMatch) {
14849
+ if (!this.availableOptions[index].disabled && !this.availableOptions[index].hasAttribute('nomatch')) {
14822
14850
  lastEnabledOptionIndex = index;
14823
14851
  break;
14824
14852
  }
@@ -14903,14 +14931,18 @@ class AuroCombobox extends AuroElement {
14903
14931
  /**
14904
14932
  * Update displayValue or input.value, it's called when making a selection.
14905
14933
  * @param {string} label - The label of the selected option.
14934
+ * @param {object} [options={}] - Optional display update settings.
14935
+ * @param {boolean} [options.force=false] - Force display sync while focused.
14906
14936
  * @private
14907
14937
  */
14908
- updateTriggerTextDisplay(label) {
14938
+ updateTriggerTextDisplay(label, options = {}) {
14939
+ const { force = false } = options;
14940
+
14909
14941
  // update the input content if persistInput is false
14910
14942
  // in suggestion mode, do not override input value if no selection has been made and the input currently has focus
14911
14943
  const isInputFocusedWithNoSelection = !this.menu.value && (this.input.matches(':focus-within') || (this.inputInBib && this.inputInBib.matches(':focus-within')));
14912
14944
 
14913
- if (!this.persistInput && !(this.behavior === 'suggestion' && isInputFocusedWithNoSelection)) {
14945
+ if (!this.persistInput && (force || !(this.behavior === 'suggestion' && isInputFocusedWithNoSelection))) {
14914
14946
  this.input.value = label || this.value;
14915
14947
  }
14916
14948
 
@@ -14987,6 +15019,13 @@ class AuroCombobox extends AuroElement {
14987
15019
  * @returns {void}
14988
15020
  */
14989
15021
  showBib() {
15022
+ // Do not auto-open from programmatic value/option updates when the
15023
+ // combobox is not focused. User-driven interactions still open normally
15024
+ // once focus enters the component.
15025
+ if (!this.componentHasFocus && !this.dropdown.isPopoverVisible) {
15026
+ return;
15027
+ }
15028
+
14990
15029
  if (!this.input.value && !this.dropdown.isBibFullscreen) {
14991
15030
  this.dropdown.hide();
14992
15031
  return;
@@ -15275,6 +15314,25 @@ class AuroCombobox extends AuroElement {
15275
15314
 
15276
15315
  // Handle menu option selection like select does
15277
15316
  this.menu.addEventListener('auroMenu-selectedOption', (event) => {
15317
+ const hasMatchingOptionForValue =
15318
+ typeof this.value === 'string' &&
15319
+ this.value.length > 0 &&
15320
+ this.menu && Array.isArray(this.menu.options) &&
15321
+ this.menu.options.some((opt) => opt.value === this.value);
15322
+
15323
+ const isInitNoMatch = event.detail && event.detail.reason === 'no-match' &&
15324
+ this.menu && this.menu.options && this.menu.options.length === 0 &&
15325
+ typeof this.value === 'string' &&
15326
+ this.value.length > 0;
15327
+
15328
+ const isTransientProgrammaticNoMatch = event.detail && event.detail.reason === 'no-match' &&
15329
+ this._suppressNextEmptyInputClear &&
15330
+ hasMatchingOptionForValue;
15331
+
15332
+ if (isInitNoMatch || isTransientProgrammaticNoMatch) {
15333
+ return;
15334
+ }
15335
+
15278
15336
  // Update the optionSelected from the event details, not manually
15279
15337
  [this.optionSelected] = event.detail.options;
15280
15338
 
@@ -15450,7 +15508,18 @@ class AuroCombobox extends AuroElement {
15450
15508
  }
15451
15509
 
15452
15510
  if (!this.input.value) {
15453
- this.clear();
15511
+ const hasCommittedValue = typeof this.value === 'string' && this.value.length > 0;
15512
+ const hasCommittedSelection = Boolean(this.menu && this.menu.optionSelected);
15513
+ const isBlurSideEffect = !this.componentHasFocus && !this.dropdownOpen;
15514
+ const isTransientEmptyInputEvent = this._suppressNextEmptyInputClear && (!event || !event.detail || event.detail.value === null || event.detail.value === undefined);
15515
+
15516
+ // Preserve a committed value when an empty input event is emitted as a
15517
+ // side effect of focus leaving the combobox (e.g., clicking a swap
15518
+ // control between two comboboxes). User-driven empty input while focused
15519
+ // should still clear as before.
15520
+ if (!(isTransientEmptyInputEvent || (isBlurSideEffect && hasCommittedValue && hasCommittedSelection))) {
15521
+ this.clear();
15522
+ }
15454
15523
  }
15455
15524
  this.handleMenuOptions();
15456
15525
 
@@ -15633,6 +15702,19 @@ class AuroCombobox extends AuroElement {
15633
15702
  }
15634
15703
 
15635
15704
  updated(changedProperties) {
15705
+ if (changedProperties.has('typedValue')) {
15706
+ const nextTypedValue = this.typedValue === null || this.typedValue === undefined ? '' : this.typedValue;
15707
+ if (this.input && this.input.value !== nextTypedValue) {
15708
+ this.input.value = nextTypedValue;
15709
+ }
15710
+ if (this.inputInBib && this.inputInBib.value !== nextTypedValue) {
15711
+ this.inputInBib.value = nextTypedValue;
15712
+ }
15713
+ if (this.menu) {
15714
+ this.menu.matchWord = normalizeFilterValue(nextTypedValue);
15715
+ }
15716
+ }
15717
+
15636
15718
  // After the component is ready, send direct value changes to auro-menu.
15637
15719
  if (changedProperties.has('value')) {
15638
15720
  if (this.value && this.value.length > 0) {
@@ -15660,6 +15742,19 @@ class AuroCombobox extends AuroElement {
15660
15742
  this.clear();
15661
15743
  }
15662
15744
  }
15745
+
15746
+ // Keep trigger text synced after value/menu state has settled. Force the
15747
+ // update so external programmatic swaps reflect immediately in the UI
15748
+ // even if the input still technically holds focus during the same tick.
15749
+ if (this.value) {
15750
+ const selectedOption = this.menu && this.menu.optionSelected;
15751
+ const hasMatchingSelectedOption = selectedOption && selectedOption.value === this.value;
15752
+ const selectedOptionLabel = (selectedOption && selectedOption.getAttribute('label')) || (selectedOption && selectedOption.textContent ? selectedOption.textContent.trim() : undefined);
15753
+ const nextDisplayLabel = hasMatchingSelectedOption ? (selectedOptionLabel || this.value) : this.value;
15754
+
15755
+ this.updateTriggerTextDisplay(nextDisplayLabel, { force: true });
15756
+ }
15757
+
15663
15758
  if (this.value && !this.componentHasFocus) {
15664
15759
  // If the value got set programmatically make sure we hide the bib
15665
15760
  // when input is not taking the focus (input can be in dropdown.trigger or in bibtemplate)
@@ -15671,22 +15766,47 @@ class AuroCombobox extends AuroElement {
15671
15766
  this.menu.matchWord = normalizeFilterValue(this.input.value);
15672
15767
  }
15673
15768
 
15674
- this.dispatchEvent(new CustomEvent('input', {
15675
- bubbles: true,
15676
- cancelable: false,
15677
- composed: true,
15678
- detail: {
15679
- optionSelected: this.menu.optionSelected,
15680
- value: this.menu.value
15681
- }
15682
- }));
15769
+ // Only dispatch 'input' when the value transition is meaningful — at least one
15770
+ // of old/new must be a non-empty string. Skipping the event when both are
15771
+ // empty/undefined prevents a feedback loop during SPA navigation where Lit's
15772
+ // initial update cycle fires before the parent framework (e.g. Svelte) has
15773
+ // had a chance to set the preselected value as a property. Without this
15774
+ // guard the event arrives with el.value === undefined, the surrounding
15775
+ // framework reads it as '' and writes that back, permanently obscuring the
15776
+ // intended preselected value.
15777
+ const _oldValue = changedProperties.get('value');
15778
+ const _oldIsNonEmpty = typeof _oldValue === 'string' && _oldValue.length > 0;
15779
+ const _newIsNonEmpty = typeof this.value === 'string' && this.value.length > 0;
15780
+
15781
+ if (_newIsNonEmpty && this.menu && Array.isArray(this.menu.options) && this.menu.options.some((opt) => opt.value === this.value)) {
15782
+ this._suppressNextEmptyInputClear = true;
15783
+ clearTimeout(this._suppressNextEmptyInputClearTimeout);
15784
+ const suppressNextEmptyInputClearDelay = 300;
15785
+ this._suppressNextEmptyInputClearTimeout = setTimeout(() => {
15786
+ this._suppressNextEmptyInputClear = false;
15787
+ }, suppressNextEmptyInputClearDelay);
15788
+ } else {
15789
+ this._suppressNextEmptyInputClear = false;
15790
+ }
15683
15791
 
15684
- // Deprecated, need to be removed.
15685
- this.dispatchEvent(new CustomEvent('auroCombobox-valueSet', {
15686
- bubbles: true,
15687
- cancelable: false,
15688
- composed: true,
15689
- }));
15792
+ if (_oldIsNonEmpty || _newIsNonEmpty) {
15793
+ this.dispatchEvent(new CustomEvent('input', {
15794
+ bubbles: true,
15795
+ cancelable: false,
15796
+ composed: true,
15797
+ detail: {
15798
+ optionSelected: this.menu.optionSelected,
15799
+ value: this.menu.value
15800
+ }
15801
+ }));
15802
+
15803
+ // Deprecated, need to be removed.
15804
+ this.dispatchEvent(new CustomEvent('auroCombobox-valueSet', {
15805
+ bubbles: true,
15806
+ cancelable: false,
15807
+ composed: true,
15808
+ }));
15809
+ }
15690
15810
  }
15691
15811
 
15692
15812
  if (changedProperties.has('availableOptions')) {
@@ -16083,6 +16203,7 @@ class AuroMenuOption extends AuroElement {
16083
16203
  this.selected = false;
16084
16204
  this.noCheckmark = false;
16085
16205
  this.disabled = false;
16206
+ this.noMatch = false;
16086
16207
 
16087
16208
  /**
16088
16209
  * @private
@@ -16163,7 +16284,8 @@ class AuroMenuOption extends AuroElement {
16163
16284
  */
16164
16285
  noMatch: {
16165
16286
  type: Boolean,
16166
- reflect: true
16287
+ reflect: true,
16288
+ attribute: 'nomatch'
16167
16289
  },
16168
16290
 
16169
16291
  /**
@@ -16263,7 +16385,7 @@ class AuroMenuOption extends AuroElement {
16263
16385
  this.setAttribute('aria-selected', this.selected.toString());
16264
16386
 
16265
16387
  // Update menu service selection state if this isn't an internal update
16266
- if (this.internalUpdateInProgress !== true) {
16388
+ if (this.internalUpdateInProgress !== true && this.menuService) {
16267
16389
  this.menuService[this.selected ? 'selectOption' : 'deselectOption'](this);
16268
16390
  }
16269
16391
  }
@@ -16298,9 +16420,10 @@ class AuroMenuOption extends AuroElement {
16298
16420
  }
16299
16421
 
16300
16422
  disconnectedCallback() {
16301
- if (this.menuService) {
16302
- this.menuService.unsubscribe(this.handleMenuChange);
16303
- this.menuService.removeMenuOption(this);
16423
+ const { menuService } = this;
16424
+ if (menuService) {
16425
+ menuService.unsubscribe(this.handleMenuChange);
16426
+ menuService.removeMenuOption(this);
16304
16427
  }
16305
16428
  }
16306
16429
 
@@ -16469,9 +16592,11 @@ class AuroMenuOption extends AuroElement {
16469
16592
  * @private
16470
16593
  */
16471
16594
  handleMouseEnter() {
16472
- if (!this.disabled) {
16473
- this.menuService.setHighlightedOption(this);
16595
+ const { menuService } = this;
16596
+ if (!menuService || this.disabled) {
16597
+ return;
16474
16598
  }
16599
+ menuService.setHighlightedOption(this);
16475
16600
  }
16476
16601
 
16477
16602
  /**
@@ -16875,10 +17000,15 @@ class MenuService {
16875
17000
  return;
16876
17001
  }
16877
17002
 
17003
+ const before = this.selectedOptions || [];
16878
17004
  const optionsSet = new Set(optionsToDeselect);
16879
- this.selectedOptions = (this.selectedOptions || [])
16880
- .filter(opt => !optionsSet.has(opt));
17005
+ const after = before.filter(opt => !optionsSet.has(opt));
17006
+
17007
+ if (this.optionsArraysMatch(after, before)) {
17008
+ return;
17009
+ }
16881
17010
 
17011
+ this.selectedOptions = after;
16882
17012
  this.stageUpdate();
16883
17013
  }
16884
17014
 
@@ -16974,6 +17104,16 @@ class MenuService {
16974
17104
  return;
16975
17105
  }
16976
17106
 
17107
+ const hostValue = this.host && this.host.value;
17108
+ const hostHasValue = hostValue !== undefined &&
17109
+ hostValue !== null &&
17110
+ (!Array.isArray(hostValue) || hostValue.length > 0) &&
17111
+ (typeof hostValue !== 'string' || hostValue.trim() !== '');
17112
+
17113
+ if (hostHasValue && this._pendingValue != null) {
17114
+ return;
17115
+ }
17116
+
16977
17117
  this.clearPendingValue();
16978
17118
 
16979
17119
  if (this.selectedOptions.length > 0) {
@@ -17154,6 +17294,9 @@ class MenuService {
17154
17294
  this.notify({ type: 'optionsChange', options: this._menuOptions });
17155
17295
 
17156
17296
  if (this._pendingValue != null) {
17297
+ // Reset the retry count so a new option registration gives a fresh
17298
+ // budget — the initial retries fired before delayed options arrived.
17299
+ this._pendingRetryCount = 0;
17157
17300
  this.queuePendingValue(this._pendingValue);
17158
17301
  }
17159
17302
  }
@@ -17498,7 +17641,11 @@ class AuroMenu extends AuroElement {
17498
17641
  * @returns {string} - Returns the label of the currently selected option(s).
17499
17642
  */
17500
17643
  get currentLabel() {
17501
- return this.menuService.currentLabel;
17644
+ const { menuService } = this;
17645
+ if (!menuService) {
17646
+ return '';
17647
+ }
17648
+ return menuService.currentLabel;
17502
17649
  };
17503
17650
 
17504
17651
  /**
@@ -17521,7 +17668,12 @@ class AuroMenu extends AuroElement {
17521
17668
  * @param {number} value - Sets the index of the currently active option.
17522
17669
  */
17523
17670
  set index(value) {
17524
- this.menuService.setHighlightedIndex(value);
17671
+ const { menuService } = this;
17672
+ if (!menuService) {
17673
+ return;
17674
+ }
17675
+
17676
+ menuService.setHighlightedIndex(value);
17525
17677
  }
17526
17678
 
17527
17679
  /**
@@ -17543,7 +17695,11 @@ class AuroMenu extends AuroElement {
17543
17695
  * @returns {String|Array<String>}
17544
17696
  */
17545
17697
  get formattedValue() {
17546
- return this.menuService.currentValue;
17698
+ const { menuService } = this;
17699
+ if (!menuService) {
17700
+ return '';
17701
+ }
17702
+ return menuService.currentValue;
17547
17703
  }
17548
17704
 
17549
17705
  /**
@@ -17587,7 +17743,11 @@ class AuroMenu extends AuroElement {
17587
17743
  * @param {HTMLElement} option - The option to set as active.
17588
17744
  */
17589
17745
  updateActiveOption(option) {
17590
- this.menuService.setHighlightedOption(option);
17746
+ const { menuService } = this;
17747
+ if (!menuService) {
17748
+ return;
17749
+ }
17750
+ menuService.setHighlightedOption(option);
17591
17751
  }
17592
17752
 
17593
17753
  /**
@@ -17615,7 +17775,8 @@ class AuroMenu extends AuroElement {
17615
17775
  if (event.type === 'valueChange') {
17616
17776
 
17617
17777
  // New option is array value or first option with fallback to undefined for empty array in all cases
17618
- const newOption = this.multiSelect && event.options.length ? event.options : event.options[0] || undefined;
17778
+ const options = event.options || [];
17779
+ const newOption = this.multiSelect && options.length ? options : options[0] || undefined;
17619
17780
  const newValue = event.stringValue;
17620
17781
 
17621
17782
  // Check if the option or value has actually changed
@@ -17624,8 +17785,11 @@ class AuroMenu extends AuroElement {
17624
17785
  this.setInternalValue(newValue);
17625
17786
  }
17626
17787
 
17627
- // Notify components of selection change
17628
- this.notifySelectionChange(event);
17788
+ // Notify components of selection change (pass normalized options to avoid undefined iterability errors)
17789
+ this.notifySelectionChange({
17790
+ ...event,
17791
+ options
17792
+ });
17629
17793
  }
17630
17794
 
17631
17795
  if (event.type === 'highlightChange') {
@@ -17648,7 +17812,11 @@ class AuroMenu extends AuroElement {
17648
17812
  * @returns {Array<HTMLElement>}
17649
17813
  */
17650
17814
  get selectedOptions() {
17651
- return this.menuService ? this.menuService.selectedOptions : [];
17815
+ const { menuService } = this;
17816
+ if (!menuService) {
17817
+ return [];
17818
+ }
17819
+ return menuService.selectedOptions;
17652
17820
  }
17653
17821
 
17654
17822
  /**
@@ -17656,7 +17824,11 @@ class AuroMenu extends AuroElement {
17656
17824
  * @returns {HTMLElement|null}
17657
17825
  */
17658
17826
  get selectedOption() {
17659
- return this.menuService ? this.menuService.selectedOptions[0] : null;
17827
+ const { menuService } = this;
17828
+ if (!menuService) {
17829
+ return null;
17830
+ }
17831
+ return menuService.selectedOptions[0] || null;
17660
17832
  }
17661
17833
 
17662
17834
  // Lifecycle Methods
@@ -17700,7 +17872,11 @@ class AuroMenu extends AuroElement {
17700
17872
  // keys are not yet resolved (framework mount-order race), selectByValue
17701
17873
  // queues a bounded retry automatically via queuePendingValue.
17702
17874
  if (changedProperties.has('value') && !this.internalUpdateInProgress) {
17703
- this.menuService.selectByValue(this.value);
17875
+ const { menuService } = this;
17876
+ if (!menuService) {
17877
+ return;
17878
+ }
17879
+ menuService.selectByValue(this.value);
17704
17880
  }
17705
17881
 
17706
17882
  // Handle loading state changes
@@ -17765,7 +17941,11 @@ class AuroMenu extends AuroElement {
17765
17941
  * @protected
17766
17942
  */
17767
17943
  makeSelection() {
17768
- this.menuService.selectHighlightedOption();
17944
+ const { menuService } = this;
17945
+ if (!menuService) {
17946
+ return;
17947
+ }
17948
+ menuService.selectHighlightedOption();
17769
17949
  }
17770
17950
 
17771
17951
  /**
@@ -17784,7 +17964,11 @@ class AuroMenu extends AuroElement {
17784
17964
  * @public
17785
17965
  */
17786
17966
  reset() {
17787
- this.menuService.reset();
17967
+ const { menuService } = this;
17968
+ if (!menuService) {
17969
+ return;
17970
+ }
17971
+ menuService.reset();
17788
17972
 
17789
17973
  // Dispatch reset event
17790
17974
  dispatchMenuEvent(this, 'auroMenu-selectValueReset');
@@ -17819,10 +18003,14 @@ class AuroMenu extends AuroElement {
17819
18003
  * @protected
17820
18004
  */
17821
18005
  navigateOptions(direction) {
18006
+ const { menuService } = this;
18007
+ if (!menuService) {
18008
+ return;
18009
+ }
17822
18010
  if (direction === 'up') {
17823
- this.menuService.highlightPrevious();
18011
+ menuService.highlightPrevious();
17824
18012
  } else if (direction === 'down') {
17825
- this.menuService.highlightNext();
18013
+ menuService.highlightNext();
17826
18014
  }
17827
18015
  }
17828
18016
 
@@ -409,6 +409,8 @@ export class AuroCombobox extends AuroElement {
409
409
  /**
410
410
  * Update displayValue or input.value, it's called when making a selection.
411
411
  * @param {string} label - The label of the selected option.
412
+ * @param {object} [options={}] - Optional display update settings.
413
+ * @param {boolean} [options.force=false] - Force display sync while focused.
412
414
  * @private
413
415
  */
414
416
  private updateTriggerTextDisplay;
@@ -551,6 +553,8 @@ export class AuroCombobox extends AuroElement {
551
553
  validate(force?: boolean): void;
552
554
  updated(changedProperties: any): void;
553
555
  hasValue: boolean;
556
+ _suppressNextEmptyInputClear: boolean;
557
+ _suppressNextEmptyInputClearTimeout: NodeJS.Timeout;
554
558
  /**
555
559
  * Applies slotted nodes to a target element with a new slot name.
556
560
  * @private