@aurodesignsystem-dev/auro-formkit 0.0.0-pr1431.3 → 0.0.0-pr1433.1

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 +230 -44
  6. package/components/combobox/demo/index.min.js +230 -44
  7. package/components/combobox/dist/auro-combobox copy.d.ts +578 -0
  8. package/components/combobox/dist/auro-combobox.d.ts +4 -0
  9. package/components/combobox/dist/index.js +142 -22
  10. package/components/combobox/dist/registered.js +142 -22
  11. package/components/counter/demo/api.min.js +30 -2
  12. package/components/counter/demo/index.min.js +30 -2
  13. package/components/counter/dist/index.js +30 -2
  14. package/components/counter/dist/registered.js +30 -2
  15. package/components/datepicker/demo/api.min.js +33 -3
  16. package/components/datepicker/demo/index.min.js +33 -3
  17. package/components/datepicker/dist/index.js +33 -3
  18. package/components/datepicker/dist/registered.js +33 -3
  19. package/components/dropdown/demo/api.min.js +29 -1
  20. package/components/dropdown/demo/index.min.js +29 -1
  21. package/components/dropdown/dist/index.js +29 -1
  22. package/components/dropdown/dist/keyboardUtils.d.ts +18 -0
  23. package/components/dropdown/dist/registered.js +29 -1
  24. package/components/form/demo/api.min.js +326 -54
  25. package/components/form/demo/index.min.js +326 -54
  26. package/components/input/demo/api.min.js +1 -1
  27. package/components/input/demo/index.min.js +1 -1
  28. package/components/input/dist/index.js +1 -1
  29. package/components/input/dist/registered.js +1 -1
  30. package/components/menu/demo/api.min.js +88 -22
  31. package/components/menu/demo/index.min.js +88 -22
  32. package/components/menu/dist/index.js +88 -22
  33. package/components/menu/dist/registered.js +88 -22
  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 +118 -24
  39. package/components/select/demo/index.min.js +118 -24
  40. package/components/select/dist/index.js +30 -2
  41. package/components/select/dist/registered.js +30 -2
  42. package/custom-elements.json +1906 -1897
  43. package/package.json +3 -3
@@ -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 = '202604091453';
5143
+ var formkitVersion$2 = '202604101700';
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 = '202604091453';
12907
+ var formkitVersion$1 = '202604101700';
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 = '202604091453';
13972
+ var formkitVersion = '202604101700';
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
 
@@ -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')) {
@@ -16265,7 +16385,7 @@ class AuroMenuOption extends AuroElement {
16265
16385
  this.setAttribute('aria-selected', this.selected.toString());
16266
16386
 
16267
16387
  // Update menu service selection state if this isn't an internal update
16268
- if (this.internalUpdateInProgress !== true) {
16388
+ if (this.internalUpdateInProgress !== true && this.menuService) {
16269
16389
  this.menuService[this.selected ? 'selectOption' : 'deselectOption'](this);
16270
16390
  }
16271
16391
  }
@@ -16300,9 +16420,10 @@ class AuroMenuOption extends AuroElement {
16300
16420
  }
16301
16421
 
16302
16422
  disconnectedCallback() {
16303
- if (this.menuService) {
16304
- this.menuService.unsubscribe(this.handleMenuChange);
16305
- this.menuService.removeMenuOption(this);
16423
+ const { menuService } = this;
16424
+ if (menuService) {
16425
+ menuService.unsubscribe(this.handleMenuChange);
16426
+ menuService.removeMenuOption(this);
16306
16427
  }
16307
16428
  }
16308
16429
 
@@ -16471,9 +16592,11 @@ class AuroMenuOption extends AuroElement {
16471
16592
  * @private
16472
16593
  */
16473
16594
  handleMouseEnter() {
16474
- if (!this.disabled) {
16475
- this.menuService.setHighlightedOption(this);
16595
+ const { menuService } = this;
16596
+ if (!menuService || this.disabled) {
16597
+ return;
16476
16598
  }
16599
+ menuService.setHighlightedOption(this);
16477
16600
  }
16478
16601
 
16479
16602
  /**
@@ -16877,10 +17000,15 @@ class MenuService {
16877
17000
  return;
16878
17001
  }
16879
17002
 
17003
+ const before = this.selectedOptions || [];
16880
17004
  const optionsSet = new Set(optionsToDeselect);
16881
- this.selectedOptions = (this.selectedOptions || [])
16882
- .filter(opt => !optionsSet.has(opt));
17005
+ const after = before.filter(opt => !optionsSet.has(opt));
17006
+
17007
+ if (this.optionsArraysMatch(after, before)) {
17008
+ return;
17009
+ }
16883
17010
 
17011
+ this.selectedOptions = after;
16884
17012
  this.stageUpdate();
16885
17013
  }
16886
17014
 
@@ -16976,6 +17104,16 @@ class MenuService {
16976
17104
  return;
16977
17105
  }
16978
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
+
16979
17117
  this.clearPendingValue();
16980
17118
 
16981
17119
  if (this.selectedOptions.length > 0) {
@@ -17156,6 +17294,9 @@ class MenuService {
17156
17294
  this.notify({ type: 'optionsChange', options: this._menuOptions });
17157
17295
 
17158
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;
17159
17300
  this.queuePendingValue(this._pendingValue);
17160
17301
  }
17161
17302
  }
@@ -17500,7 +17641,11 @@ class AuroMenu extends AuroElement {
17500
17641
  * @returns {string} - Returns the label of the currently selected option(s).
17501
17642
  */
17502
17643
  get currentLabel() {
17503
- return this.menuService.currentLabel;
17644
+ const { menuService } = this;
17645
+ if (!menuService) {
17646
+ return '';
17647
+ }
17648
+ return menuService.currentLabel;
17504
17649
  };
17505
17650
 
17506
17651
  /**
@@ -17523,7 +17668,12 @@ class AuroMenu extends AuroElement {
17523
17668
  * @param {number} value - Sets the index of the currently active option.
17524
17669
  */
17525
17670
  set index(value) {
17526
- this.menuService.setHighlightedIndex(value);
17671
+ const { menuService } = this;
17672
+ if (!menuService) {
17673
+ return;
17674
+ }
17675
+
17676
+ menuService.setHighlightedIndex(value);
17527
17677
  }
17528
17678
 
17529
17679
  /**
@@ -17545,7 +17695,11 @@ class AuroMenu extends AuroElement {
17545
17695
  * @returns {String|Array<String>}
17546
17696
  */
17547
17697
  get formattedValue() {
17548
- return this.menuService.currentValue;
17698
+ const { menuService } = this;
17699
+ if (!menuService) {
17700
+ return '';
17701
+ }
17702
+ return menuService.currentValue;
17549
17703
  }
17550
17704
 
17551
17705
  /**
@@ -17589,7 +17743,11 @@ class AuroMenu extends AuroElement {
17589
17743
  * @param {HTMLElement} option - The option to set as active.
17590
17744
  */
17591
17745
  updateActiveOption(option) {
17592
- this.menuService.setHighlightedOption(option);
17746
+ const { menuService } = this;
17747
+ if (!menuService) {
17748
+ return;
17749
+ }
17750
+ menuService.setHighlightedOption(option);
17593
17751
  }
17594
17752
 
17595
17753
  /**
@@ -17617,7 +17775,8 @@ class AuroMenu extends AuroElement {
17617
17775
  if (event.type === 'valueChange') {
17618
17776
 
17619
17777
  // New option is array value or first option with fallback to undefined for empty array in all cases
17620
- 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;
17621
17780
  const newValue = event.stringValue;
17622
17781
 
17623
17782
  // Check if the option or value has actually changed
@@ -17626,8 +17785,11 @@ class AuroMenu extends AuroElement {
17626
17785
  this.setInternalValue(newValue);
17627
17786
  }
17628
17787
 
17629
- // Notify components of selection change
17630
- 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
+ });
17631
17793
  }
17632
17794
 
17633
17795
  if (event.type === 'highlightChange') {
@@ -17650,7 +17812,11 @@ class AuroMenu extends AuroElement {
17650
17812
  * @returns {Array<HTMLElement>}
17651
17813
  */
17652
17814
  get selectedOptions() {
17653
- return this.menuService ? this.menuService.selectedOptions : [];
17815
+ const { menuService } = this;
17816
+ if (!menuService) {
17817
+ return [];
17818
+ }
17819
+ return menuService.selectedOptions;
17654
17820
  }
17655
17821
 
17656
17822
  /**
@@ -17658,7 +17824,11 @@ class AuroMenu extends AuroElement {
17658
17824
  * @returns {HTMLElement|null}
17659
17825
  */
17660
17826
  get selectedOption() {
17661
- 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;
17662
17832
  }
17663
17833
 
17664
17834
  // Lifecycle Methods
@@ -17702,7 +17872,11 @@ class AuroMenu extends AuroElement {
17702
17872
  // keys are not yet resolved (framework mount-order race), selectByValue
17703
17873
  // queues a bounded retry automatically via queuePendingValue.
17704
17874
  if (changedProperties.has('value') && !this.internalUpdateInProgress) {
17705
- this.menuService.selectByValue(this.value);
17875
+ const { menuService } = this;
17876
+ if (!menuService) {
17877
+ return;
17878
+ }
17879
+ menuService.selectByValue(this.value);
17706
17880
  }
17707
17881
 
17708
17882
  // Handle loading state changes
@@ -17767,7 +17941,11 @@ class AuroMenu extends AuroElement {
17767
17941
  * @protected
17768
17942
  */
17769
17943
  makeSelection() {
17770
- this.menuService.selectHighlightedOption();
17944
+ const { menuService } = this;
17945
+ if (!menuService) {
17946
+ return;
17947
+ }
17948
+ menuService.selectHighlightedOption();
17771
17949
  }
17772
17950
 
17773
17951
  /**
@@ -17786,7 +17964,11 @@ class AuroMenu extends AuroElement {
17786
17964
  * @public
17787
17965
  */
17788
17966
  reset() {
17789
- this.menuService.reset();
17967
+ const { menuService } = this;
17968
+ if (!menuService) {
17969
+ return;
17970
+ }
17971
+ menuService.reset();
17790
17972
 
17791
17973
  // Dispatch reset event
17792
17974
  dispatchMenuEvent(this, 'auroMenu-selectValueReset');
@@ -17821,10 +18003,14 @@ class AuroMenu extends AuroElement {
17821
18003
  * @protected
17822
18004
  */
17823
18005
  navigateOptions(direction) {
18006
+ const { menuService } = this;
18007
+ if (!menuService) {
18008
+ return;
18009
+ }
17824
18010
  if (direction === 'up') {
17825
- this.menuService.highlightPrevious();
18011
+ menuService.highlightPrevious();
17826
18012
  } else if (direction === 'down') {
17827
- this.menuService.highlightNext();
18013
+ menuService.highlightNext();
17828
18014
  }
17829
18015
  }
17830
18016