@aurodesignsystem-dev/auro-formkit 0.0.0-pr1554.0 → 0.0.0-pr1554.10

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 (45) hide show
  1. package/components/checkbox/demo/customize.min.js +1 -1
  2. package/components/checkbox/demo/getting-started.min.js +1 -1
  3. package/components/checkbox/demo/index.min.js +1 -1
  4. package/components/checkbox/dist/index.js +1 -1
  5. package/components/checkbox/dist/registered.js +1 -1
  6. package/components/combobox/demo/customize.min.js +123 -43
  7. package/components/combobox/demo/getting-started.min.js +123 -43
  8. package/components/combobox/demo/index.min.js +123 -43
  9. package/components/combobox/dist/index.js +123 -43
  10. package/components/combobox/dist/registered.js +123 -43
  11. package/components/counter/demo/customize.min.js +47 -6
  12. package/components/counter/demo/index.min.js +47 -6
  13. package/components/counter/dist/index.js +47 -6
  14. package/components/counter/dist/registered.js +47 -6
  15. package/components/datepicker/demo/customize.min.js +85 -16
  16. package/components/datepicker/demo/index.min.js +85 -16
  17. package/components/datepicker/dist/index.js +85 -16
  18. package/components/datepicker/dist/registered.js +85 -16
  19. package/components/dropdown/demo/customize.min.js +46 -5
  20. package/components/dropdown/demo/getting-started.min.js +46 -5
  21. package/components/dropdown/demo/index.min.js +46 -5
  22. package/components/dropdown/dist/auro-dropdown.d.ts +8 -1
  23. package/components/dropdown/dist/index.js +46 -5
  24. package/components/dropdown/dist/registered.js +46 -5
  25. package/components/form/demo/customize.min.js +342 -83
  26. package/components/form/demo/getting-started.min.js +342 -83
  27. package/components/form/demo/index.min.js +342 -83
  28. package/components/form/demo/registerDemoDeps.min.js +342 -83
  29. package/components/input/demo/customize.min.js +38 -10
  30. package/components/input/demo/getting-started.min.js +38 -10
  31. package/components/input/demo/index.min.js +38 -10
  32. package/components/input/dist/index.js +38 -10
  33. package/components/input/dist/registered.js +38 -10
  34. package/components/radio/demo/customize.min.js +1 -1
  35. package/components/radio/demo/getting-started.min.js +1 -1
  36. package/components/radio/demo/index.min.js +1 -1
  37. package/components/radio/dist/index.js +1 -1
  38. package/components/radio/dist/registered.js +1 -1
  39. package/components/select/demo/customize.min.js +47 -6
  40. package/components/select/demo/getting-started.min.js +47 -6
  41. package/components/select/demo/index.min.js +47 -6
  42. package/components/select/dist/index.js +47 -6
  43. package/components/select/dist/registered.js +47 -6
  44. package/custom-elements.json +1783 -1777
  45. package/package.json +1 -1
@@ -4986,7 +4986,7 @@ let AuroHelpText$2 = class AuroHelpText extends i$3 {
4986
4986
  }
4987
4987
  };
4988
4988
 
4989
- var formkitVersion$2 = '202607152158';
4989
+ var formkitVersion$2 = '202607160655';
4990
4990
 
4991
4991
  let AuroElement$2 = class AuroElement extends i$3 {
4992
4992
  static get properties() {
@@ -5115,7 +5115,6 @@ class AuroDropdown extends AuroElement$2 {
5115
5115
  static get shadowRootOptions() {
5116
5116
  return {
5117
5117
  ...AuroElement$2.shadowRootOptions,
5118
- delegatesFocus: true,
5119
5118
  };
5120
5119
  }
5121
5120
 
@@ -5282,7 +5281,47 @@ class AuroDropdown extends AuroElement$2 {
5282
5281
  focusables[0].focus();
5283
5282
  }
5284
5283
  } else {
5284
+ this.focusTrigger();
5285
+ }
5286
+ }
5287
+
5288
+ /**
5289
+ * Focus the trigger content. When the trigger wrapper itself is focusable
5290
+ * (has tabindex), focus it directly. Otherwise, focus the first focusable
5291
+ * element slotted into the trigger slot (e.g. the auro-input).
5292
+ * @private
5293
+ */
5294
+ focusTrigger() {
5295
+ if (this.trigger.hasAttribute('tabindex')) {
5285
5296
  this.trigger.focus();
5297
+ } else {
5298
+ // Slotted content isn't a DOM child of the trigger div, so
5299
+ // getFocusableElements can't find it. Query assigned nodes directly.
5300
+ const slot = this.trigger.querySelector('slot[name="trigger"]');
5301
+ if (slot) {
5302
+ const assigned = slot.assignedElements();
5303
+ for (const el of assigned) {
5304
+ if (el.hasAttribute('disabled')) {
5305
+ continue;
5306
+ }
5307
+ // Try finding a focusable descendant first (handles non-focusable
5308
+ // wrappers like <div> containing a <button>). If none found, try
5309
+ // focusing the element directly (works for custom elements like
5310
+ // auro-input that have delegatesFocus or a custom focus() method).
5311
+ const descendants = getFocusableElements(el);
5312
+ if (descendants.length > 0) {
5313
+ descendants[0].focus();
5314
+ return;
5315
+ }
5316
+ el.focus();
5317
+ return;
5318
+ }
5319
+ }
5320
+ // Fallback: try DOM children (non-slotted content)
5321
+ const focusables = getFocusableElements(this.trigger);
5322
+ if (focusables.length > 0) {
5323
+ focusables[0].focus();
5324
+ }
5286
5325
  }
5287
5326
  }
5288
5327
 
@@ -5736,14 +5775,16 @@ class AuroDropdown extends AuroElement$2 {
5736
5775
 
5737
5776
  const eventType = event.detail.eventType || "unknown";
5738
5777
  if (!this.isPopoverVisible && this.hasFocus && eventType === "keydown") {
5739
- this.trigger.focus();
5778
+ this.focusTrigger();
5740
5779
  }
5741
5780
 
5742
5781
 
5743
5782
  // On Tab-driven close (eventType "focusloss"), let focus advance naturally
5744
5783
  // — restoring to the trigger would trap the user on this dropdown, forcing
5745
5784
  // an extra Tab to move on. Escape and outside-click still restore.
5746
- if (!this.isPopoverVisible && eventType !== "focusloss") {
5785
+ // When noHideOnThisFocusLoss is true, the consumer (e.g. combobox) manages
5786
+ // its own focus restoration — skip the generic trigger focus to avoid races.
5787
+ if (!this.isPopoverVisible && eventType !== "focusloss" && !this.noHideOnThisFocusLoss) {
5747
5788
  // wait til the bib gets fully closed and rendered
5748
5789
  setTimeout(() => {
5749
5790
  // Skip if the bib re-opened, or if focus moved intentionally outside the dropdown (not to body).
@@ -5755,7 +5796,7 @@ class AuroDropdown extends AuroElement$2 {
5755
5796
  return;
5756
5797
  }
5757
5798
  // Restore focus to the trigger.
5758
- this.trigger.focus();
5799
+ this.focusTrigger();
5759
5800
  });
5760
5801
  }
5761
5802
  }
@@ -16936,9 +16977,10 @@ class DomHandler {
16936
16977
  class BaseInput extends AuroElement$1 {
16937
16978
 
16938
16979
  // Delegate focus to the native <input> inside the shadow root so that
16939
- // showModal()'s dialog focusing steps reach the input element.
16940
- // This keeps the mobile virtual keyboard open when the fullscreen dialog
16941
- // opens, because the browser sees an input-to-input focus transfer.
16980
+ // clicking anywhere on the input wrapper focuses the native input, and
16981
+ // programmatic .focus() calls on elements in the shadow DOM work correctly.
16982
+ // The initial-load focus theft was caused by the static `autofocus`
16983
+ // attribute on the bib input (now conditional), not by delegatesFocus.
16942
16984
  static get shadowRootOptions() {
16943
16985
  return {
16944
16986
  ...AuroElement$1.shadowRootOptions,
@@ -18615,7 +18657,7 @@ let AuroHelpText$1 = class AuroHelpText extends i$3 {
18615
18657
  }
18616
18658
  };
18617
18659
 
18618
- var formkitVersion$1 = '202607152158';
18660
+ var formkitVersion$1 = '202607160655';
18619
18661
 
18620
18662
  // Copyright (c) 2025 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
18621
18663
  // See LICENSE in the project root for license information.
@@ -18901,18 +18943,45 @@ class AuroInput extends BaseInput {
18901
18943
  * @returns {void}
18902
18944
  */
18903
18945
  checkDisplayValueSlotChange() {
18904
- // flatten:true resolves through auro-combobox's forwarding slot
18905
- // (<slot name="displayValue" slot="displayValue">) so a clone appended
18906
- // directly to auro-input's light DOM alongside the forwarder still
18907
- // counts as content. The prior nodes[0].tagName === 'SLOT' recursion
18908
- // discarded any siblings past the forwarder.
18909
18946
  const slot = this.shadowRoot?.querySelector('slot[name="displayValue"]');
18910
18947
  if (!slot) {
18948
+ // Shadow slot not yet rendered — fall back to checking light-DOM
18949
+ // children so hasDisplayValueContent isn't stuck false when called
18950
+ // before firstUpdated (e.g. from auro-combobox during mount).
18951
+ // Check for any element (including custom elements like <auro-icon>
18952
+ // that render via shadow DOM with no text content).
18953
+ const lightDomContent = this.querySelector('[slot="displayValue"]:not(slot)');
18954
+ this.hasDisplayValueContent = Boolean(lightDomContent && (
18955
+ lightDomContent.textContent.trim().length > 0 ||
18956
+ lightDomContent.children.length > 0 ||
18957
+ lightDomContent.shadowRoot !== null
18958
+ ));
18959
+ this.requestUpdate();
18911
18960
  return;
18912
18961
  }
18913
18962
  const nodes = slot.assignedNodes({ flatten: true });
18914
18963
 
18915
- this.hasDisplayValueContent = nodes.length > 0;
18964
+ // Check for actual visible content, not just node existence.
18965
+ // An empty <span slot="displayValue"></span> forwarded from the
18966
+ // consumer should not be treated as "has content" — it causes the
18967
+ // displayValue wrapper to render (with hasContent class) but show
18968
+ // nothing, blocking the combobox's synthetic displayValue from
18969
+ // being visible on preset/deeplink load.
18970
+ // Custom elements (e.g. <auro-icon>) that render via shadow DOM are
18971
+ // treated as content even when they have no text or light-DOM children.
18972
+ this.hasDisplayValueContent = nodes.some((node) => {
18973
+ if (node.nodeType === Node.TEXT_NODE) {
18974
+ return node.textContent.trim().length > 0;
18975
+ }
18976
+ if (node.nodeType === Node.ELEMENT_NODE) {
18977
+ return node.textContent.trim().length > 0 ||
18978
+ node.children.length > 0 ||
18979
+ node.shadowRoot !== null;
18980
+ }
18981
+ return false;
18982
+ });
18983
+
18984
+ this.requestUpdate();
18916
18985
  }
18917
18986
 
18918
18987
  firstUpdated() {
@@ -19739,7 +19808,7 @@ class AuroBibtemplate extends i$3 {
19739
19808
  }
19740
19809
  }
19741
19810
 
19742
- var formkitVersion = '202607152158';
19811
+ var formkitVersion = '202607160655';
19743
19812
 
19744
19813
  var styleCss$3 = i$6`.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}`;
19745
19814
 
@@ -20791,6 +20860,14 @@ class AuroCombobox extends AuroElement {
20791
20860
  // auroMenu-selectedOption event hasn't fired yet, or we're on remount
20792
20861
  // with no options loaded). Synthesize a displayValue from the value so
20793
20862
  // the overlay isn't blank.
20863
+ //
20864
+ // NOTE: This renders the raw machine value (e.g. "SEA"), not the
20865
+ // human-readable label (e.g. "Seattle, WA"). For consumers where
20866
+ // value ≠ label, this produces a brief flash of the raw value until
20867
+ // the option elements load and updateTriggerTextDisplay re-runs with
20868
+ // the correct label. This is intentionally preferred over a blank
20869
+ // state — the displayValueInTrigger.remove() cleanup above ensures
20870
+ // this placeholder is replaced once the real option is available.
20794
20871
  const syntheticDV = document.createElement('span');
20795
20872
  syntheticDV.setAttribute('slot', 'displayValue');
20796
20873
  syntheticDV.textContent = this.value;
@@ -21043,7 +21120,11 @@ class AuroCombobox extends AuroElement {
21043
21120
  // after the dropdown layout settles.
21044
21121
 
21045
21122
  doubleRaf(() => {
21046
- this.setInputFocus();
21123
+ // Guard: skip if the dropdown closed before this rAF fired
21124
+ // (e.g. user selected an option immediately after the bib opened).
21125
+ if (this.dropdownOpen) {
21126
+ this.setInputFocus();
21127
+ }
21047
21128
  if (this._inFullscreenTransition) {
21048
21129
  this._inFullscreenTransition = false;
21049
21130
  }
@@ -21090,7 +21171,9 @@ class AuroCombobox extends AuroElement {
21090
21171
  }
21091
21172
 
21092
21173
  this._scheduleTimer(() => {
21093
- this.setInputFocus();
21174
+ if (this.dropdown.isPopoverVisible) {
21175
+ this.setInputFocus();
21176
+ }
21094
21177
  }, 0);
21095
21178
  });
21096
21179
  }
@@ -21099,14 +21182,19 @@ class AuroCombobox extends AuroElement {
21099
21182
  * @private
21100
21183
  */
21101
21184
  setClearBtnFocus() {
21102
- const clearBtn = this.input.shadowRoot.querySelector('.clearBtn');
21103
- if (clearBtn) {
21104
- // Wait for the element to fully render across
21105
- // multiple Lit update cycles before moving focus
21106
- doubleRaf(() => {
21185
+ doubleRaf(() => {
21186
+ // First establish focus inside the input's shadow root.
21187
+ // Without this, clearBtn.focus() silently fails when focus is on
21188
+ // document.body (e.g. after a click selection closes the bib dialog).
21189
+ // delegatesFocus on BaseInput routes this to the native <input>.
21190
+ this.input.focus();
21191
+
21192
+ // Now move focus to the clear button within the same shadow root.
21193
+ const clearBtn = this.input.shadowRoot.querySelector('.clearBtn');
21194
+ if (clearBtn) {
21107
21195
  clearBtn.focus();
21108
- });
21109
- }
21196
+ }
21197
+ });
21110
21198
  }
21111
21199
 
21112
21200
  /**
@@ -21317,6 +21405,9 @@ class AuroCombobox extends AuroElement {
21317
21405
  // only — fresh user selections take the existing hideBib path.
21318
21406
  if (isEcho && this.menu.optionSelected) {
21319
21407
  this._programmaticFilterRefresh = true;
21408
+ this.updateComplete.then(() => {
21409
+ this._programmaticFilterRefresh = false;
21410
+ });
21320
21411
  }
21321
21412
  });
21322
21413
 
@@ -21547,15 +21638,6 @@ class AuroCombobox extends AuroElement {
21547
21638
  * @returns {void}
21548
21639
  */
21549
21640
  handleTriggerInputValueChange(event) {
21550
- // Clear a stale _programmaticFilterRefresh when the user is genuinely
21551
- // interacting. On mount, updated('value') sets the flag, but the early
21552
- // return at `this.value === this.input.value` exits before clearing it.
21553
- // Without this, the first keystroke after mount fails to set _userTyped
21554
- // and the bib doesn't open.
21555
- if (this._programmaticFilterRefresh && this.componentHasFocus) {
21556
- this._programmaticFilterRefresh = false;
21557
- }
21558
-
21559
21641
  // 'input' fires for every user-initiated value change — typing, paste,
21560
21642
  // IME composition end, dead-key composition, drag-drop. Flip _userTyped
21561
21643
  // here so updated('availableOptions') auto-opens the bib for sources
@@ -21578,10 +21660,6 @@ class AuroCombobox extends AuroElement {
21578
21660
  if (this.dropdown.isBibFullscreen && this.input.value && this.input.value.length > 0 && this.dropdown.isPopoverVisible) {
21579
21661
  this.setInputFocus();
21580
21662
  }
21581
-
21582
- if (this._programmaticFilterRefresh) {
21583
- this._programmaticFilterRefresh = false;
21584
- }
21585
21663
  }
21586
21664
 
21587
21665
  /**
@@ -21780,6 +21858,12 @@ class AuroCombobox extends AuroElement {
21780
21858
  // setting the flag unconditionally here masks the user-typed open path.
21781
21859
  if (!this._userTyped) {
21782
21860
  this._programmaticFilterRefresh = true;
21861
+ // Self-clear after this update cycle completes. This collapses
21862
+ // the previous scattered clear-points into one and prevents the
21863
+ // flag from surviving into the next user interaction.
21864
+ this.updateComplete.then(() => {
21865
+ this._programmaticFilterRefresh = false;
21866
+ });
21783
21867
  }
21784
21868
 
21785
21869
  if (this.input.value !== this.value) {
@@ -21869,10 +21953,6 @@ class AuroCombobox extends AuroElement {
21869
21953
  } else if (!this.dropdown.isBibFullscreen) {
21870
21954
  this.hideBib();
21871
21955
  }
21872
-
21873
- if (this._programmaticFilterRefresh) {
21874
- this._programmaticFilterRefresh = false;
21875
- }
21876
21956
  }
21877
21957
 
21878
21958
  if (changedProperties.has('error')) {
@@ -22054,7 +22134,7 @@ class AuroCombobox extends AuroElement {
22054
22134
  <slot @slotchange="${this.handleSlotChange}"></slot>
22055
22135
  <${this.inputTag}
22056
22136
  id="inputInBib"
22057
- autofocus
22137
+ ?autofocus="${this.dropdownOpen && this.dropdown?.isBibFullscreen}"
22058
22138
  @input="${this.handleInputValueChange}"
22059
22139
  .a11yActivedescendant="${this.dropdownOpen && this.optionActive ? this.optionActive.id : undefined}"
22060
22140
  .a11yControls=${`${this.dropdownId}-floater-bib`}
@@ -4904,7 +4904,7 @@ let AuroHelpText$2 = class AuroHelpText extends LitElement {
4904
4904
  }
4905
4905
  };
4906
4906
 
4907
- var formkitVersion$2 = '202607152158';
4907
+ var formkitVersion$2 = '202607160655';
4908
4908
 
4909
4909
  let AuroElement$2 = class AuroElement extends LitElement {
4910
4910
  static get properties() {
@@ -5033,7 +5033,6 @@ class AuroDropdown extends AuroElement$2 {
5033
5033
  static get shadowRootOptions() {
5034
5034
  return {
5035
5035
  ...AuroElement$2.shadowRootOptions,
5036
- delegatesFocus: true,
5037
5036
  };
5038
5037
  }
5039
5038
 
@@ -5200,7 +5199,47 @@ class AuroDropdown extends AuroElement$2 {
5200
5199
  focusables[0].focus();
5201
5200
  }
5202
5201
  } else {
5202
+ this.focusTrigger();
5203
+ }
5204
+ }
5205
+
5206
+ /**
5207
+ * Focus the trigger content. When the trigger wrapper itself is focusable
5208
+ * (has tabindex), focus it directly. Otherwise, focus the first focusable
5209
+ * element slotted into the trigger slot (e.g. the auro-input).
5210
+ * @private
5211
+ */
5212
+ focusTrigger() {
5213
+ if (this.trigger.hasAttribute('tabindex')) {
5203
5214
  this.trigger.focus();
5215
+ } else {
5216
+ // Slotted content isn't a DOM child of the trigger div, so
5217
+ // getFocusableElements can't find it. Query assigned nodes directly.
5218
+ const slot = this.trigger.querySelector('slot[name="trigger"]');
5219
+ if (slot) {
5220
+ const assigned = slot.assignedElements();
5221
+ for (const el of assigned) {
5222
+ if (el.hasAttribute('disabled')) {
5223
+ continue;
5224
+ }
5225
+ // Try finding a focusable descendant first (handles non-focusable
5226
+ // wrappers like <div> containing a <button>). If none found, try
5227
+ // focusing the element directly (works for custom elements like
5228
+ // auro-input that have delegatesFocus or a custom focus() method).
5229
+ const descendants = getFocusableElements(el);
5230
+ if (descendants.length > 0) {
5231
+ descendants[0].focus();
5232
+ return;
5233
+ }
5234
+ el.focus();
5235
+ return;
5236
+ }
5237
+ }
5238
+ // Fallback: try DOM children (non-slotted content)
5239
+ const focusables = getFocusableElements(this.trigger);
5240
+ if (focusables.length > 0) {
5241
+ focusables[0].focus();
5242
+ }
5204
5243
  }
5205
5244
  }
5206
5245
 
@@ -5654,14 +5693,16 @@ class AuroDropdown extends AuroElement$2 {
5654
5693
 
5655
5694
  const eventType = event.detail.eventType || "unknown";
5656
5695
  if (!this.isPopoverVisible && this.hasFocus && eventType === "keydown") {
5657
- this.trigger.focus();
5696
+ this.focusTrigger();
5658
5697
  }
5659
5698
 
5660
5699
 
5661
5700
  // On Tab-driven close (eventType "focusloss"), let focus advance naturally
5662
5701
  // — restoring to the trigger would trap the user on this dropdown, forcing
5663
5702
  // an extra Tab to move on. Escape and outside-click still restore.
5664
- if (!this.isPopoverVisible && eventType !== "focusloss") {
5703
+ // When noHideOnThisFocusLoss is true, the consumer (e.g. combobox) manages
5704
+ // its own focus restoration — skip the generic trigger focus to avoid races.
5705
+ if (!this.isPopoverVisible && eventType !== "focusloss" && !this.noHideOnThisFocusLoss) {
5665
5706
  // wait til the bib gets fully closed and rendered
5666
5707
  setTimeout(() => {
5667
5708
  // Skip if the bib re-opened, or if focus moved intentionally outside the dropdown (not to body).
@@ -5673,7 +5714,7 @@ class AuroDropdown extends AuroElement$2 {
5673
5714
  return;
5674
5715
  }
5675
5716
  // Restore focus to the trigger.
5676
- this.trigger.focus();
5717
+ this.focusTrigger();
5677
5718
  });
5678
5719
  }
5679
5720
  }
@@ -16847,9 +16888,10 @@ class DomHandler {
16847
16888
  class BaseInput extends AuroElement$1 {
16848
16889
 
16849
16890
  // Delegate focus to the native <input> inside the shadow root so that
16850
- // showModal()'s dialog focusing steps reach the input element.
16851
- // This keeps the mobile virtual keyboard open when the fullscreen dialog
16852
- // opens, because the browser sees an input-to-input focus transfer.
16891
+ // clicking anywhere on the input wrapper focuses the native input, and
16892
+ // programmatic .focus() calls on elements in the shadow DOM work correctly.
16893
+ // The initial-load focus theft was caused by the static `autofocus`
16894
+ // attribute on the bib input (now conditional), not by delegatesFocus.
16853
16895
  static get shadowRootOptions() {
16854
16896
  return {
16855
16897
  ...AuroElement$1.shadowRootOptions,
@@ -18526,7 +18568,7 @@ let AuroHelpText$1 = class AuroHelpText extends LitElement {
18526
18568
  }
18527
18569
  };
18528
18570
 
18529
- var formkitVersion$1 = '202607152158';
18571
+ var formkitVersion$1 = '202607160655';
18530
18572
 
18531
18573
  // Copyright (c) 2025 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
18532
18574
  // See LICENSE in the project root for license information.
@@ -18812,18 +18854,45 @@ class AuroInput extends BaseInput {
18812
18854
  * @returns {void}
18813
18855
  */
18814
18856
  checkDisplayValueSlotChange() {
18815
- // flatten:true resolves through auro-combobox's forwarding slot
18816
- // (<slot name="displayValue" slot="displayValue">) so a clone appended
18817
- // directly to auro-input's light DOM alongside the forwarder still
18818
- // counts as content. The prior nodes[0].tagName === 'SLOT' recursion
18819
- // discarded any siblings past the forwarder.
18820
18857
  const slot = this.shadowRoot?.querySelector('slot[name="displayValue"]');
18821
18858
  if (!slot) {
18859
+ // Shadow slot not yet rendered — fall back to checking light-DOM
18860
+ // children so hasDisplayValueContent isn't stuck false when called
18861
+ // before firstUpdated (e.g. from auro-combobox during mount).
18862
+ // Check for any element (including custom elements like <auro-icon>
18863
+ // that render via shadow DOM with no text content).
18864
+ const lightDomContent = this.querySelector('[slot="displayValue"]:not(slot)');
18865
+ this.hasDisplayValueContent = Boolean(lightDomContent && (
18866
+ lightDomContent.textContent.trim().length > 0 ||
18867
+ lightDomContent.children.length > 0 ||
18868
+ lightDomContent.shadowRoot !== null
18869
+ ));
18870
+ this.requestUpdate();
18822
18871
  return;
18823
18872
  }
18824
18873
  const nodes = slot.assignedNodes({ flatten: true });
18825
18874
 
18826
- this.hasDisplayValueContent = nodes.length > 0;
18875
+ // Check for actual visible content, not just node existence.
18876
+ // An empty <span slot="displayValue"></span> forwarded from the
18877
+ // consumer should not be treated as "has content" — it causes the
18878
+ // displayValue wrapper to render (with hasContent class) but show
18879
+ // nothing, blocking the combobox's synthetic displayValue from
18880
+ // being visible on preset/deeplink load.
18881
+ // Custom elements (e.g. <auro-icon>) that render via shadow DOM are
18882
+ // treated as content even when they have no text or light-DOM children.
18883
+ this.hasDisplayValueContent = nodes.some((node) => {
18884
+ if (node.nodeType === Node.TEXT_NODE) {
18885
+ return node.textContent.trim().length > 0;
18886
+ }
18887
+ if (node.nodeType === Node.ELEMENT_NODE) {
18888
+ return node.textContent.trim().length > 0 ||
18889
+ node.children.length > 0 ||
18890
+ node.shadowRoot !== null;
18891
+ }
18892
+ return false;
18893
+ });
18894
+
18895
+ this.requestUpdate();
18827
18896
  }
18828
18897
 
18829
18898
  firstUpdated() {
@@ -19650,7 +19719,7 @@ class AuroBibtemplate extends LitElement {
19650
19719
  }
19651
19720
  }
19652
19721
 
19653
- var formkitVersion = '202607152158';
19722
+ var formkitVersion = '202607160655';
19654
19723
 
19655
19724
  var styleCss$1 = css`.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}`;
19656
19725
 
@@ -20702,6 +20771,14 @@ class AuroCombobox extends AuroElement {
20702
20771
  // auroMenu-selectedOption event hasn't fired yet, or we're on remount
20703
20772
  // with no options loaded). Synthesize a displayValue from the value so
20704
20773
  // the overlay isn't blank.
20774
+ //
20775
+ // NOTE: This renders the raw machine value (e.g. "SEA"), not the
20776
+ // human-readable label (e.g. "Seattle, WA"). For consumers where
20777
+ // value ≠ label, this produces a brief flash of the raw value until
20778
+ // the option elements load and updateTriggerTextDisplay re-runs with
20779
+ // the correct label. This is intentionally preferred over a blank
20780
+ // state — the displayValueInTrigger.remove() cleanup above ensures
20781
+ // this placeholder is replaced once the real option is available.
20705
20782
  const syntheticDV = document.createElement('span');
20706
20783
  syntheticDV.setAttribute('slot', 'displayValue');
20707
20784
  syntheticDV.textContent = this.value;
@@ -20954,7 +21031,11 @@ class AuroCombobox extends AuroElement {
20954
21031
  // after the dropdown layout settles.
20955
21032
 
20956
21033
  doubleRaf(() => {
20957
- this.setInputFocus();
21034
+ // Guard: skip if the dropdown closed before this rAF fired
21035
+ // (e.g. user selected an option immediately after the bib opened).
21036
+ if (this.dropdownOpen) {
21037
+ this.setInputFocus();
21038
+ }
20958
21039
  if (this._inFullscreenTransition) {
20959
21040
  this._inFullscreenTransition = false;
20960
21041
  }
@@ -21001,7 +21082,9 @@ class AuroCombobox extends AuroElement {
21001
21082
  }
21002
21083
 
21003
21084
  this._scheduleTimer(() => {
21004
- this.setInputFocus();
21085
+ if (this.dropdown.isPopoverVisible) {
21086
+ this.setInputFocus();
21087
+ }
21005
21088
  }, 0);
21006
21089
  });
21007
21090
  }
@@ -21010,14 +21093,19 @@ class AuroCombobox extends AuroElement {
21010
21093
  * @private
21011
21094
  */
21012
21095
  setClearBtnFocus() {
21013
- const clearBtn = this.input.shadowRoot.querySelector('.clearBtn');
21014
- if (clearBtn) {
21015
- // Wait for the element to fully render across
21016
- // multiple Lit update cycles before moving focus
21017
- doubleRaf(() => {
21096
+ doubleRaf(() => {
21097
+ // First establish focus inside the input's shadow root.
21098
+ // Without this, clearBtn.focus() silently fails when focus is on
21099
+ // document.body (e.g. after a click selection closes the bib dialog).
21100
+ // delegatesFocus on BaseInput routes this to the native <input>.
21101
+ this.input.focus();
21102
+
21103
+ // Now move focus to the clear button within the same shadow root.
21104
+ const clearBtn = this.input.shadowRoot.querySelector('.clearBtn');
21105
+ if (clearBtn) {
21018
21106
  clearBtn.focus();
21019
- });
21020
- }
21107
+ }
21108
+ });
21021
21109
  }
21022
21110
 
21023
21111
  /**
@@ -21228,6 +21316,9 @@ class AuroCombobox extends AuroElement {
21228
21316
  // only — fresh user selections take the existing hideBib path.
21229
21317
  if (isEcho && this.menu.optionSelected) {
21230
21318
  this._programmaticFilterRefresh = true;
21319
+ this.updateComplete.then(() => {
21320
+ this._programmaticFilterRefresh = false;
21321
+ });
21231
21322
  }
21232
21323
  });
21233
21324
 
@@ -21458,15 +21549,6 @@ class AuroCombobox extends AuroElement {
21458
21549
  * @returns {void}
21459
21550
  */
21460
21551
  handleTriggerInputValueChange(event) {
21461
- // Clear a stale _programmaticFilterRefresh when the user is genuinely
21462
- // interacting. On mount, updated('value') sets the flag, but the early
21463
- // return at `this.value === this.input.value` exits before clearing it.
21464
- // Without this, the first keystroke after mount fails to set _userTyped
21465
- // and the bib doesn't open.
21466
- if (this._programmaticFilterRefresh && this.componentHasFocus) {
21467
- this._programmaticFilterRefresh = false;
21468
- }
21469
-
21470
21552
  // 'input' fires for every user-initiated value change — typing, paste,
21471
21553
  // IME composition end, dead-key composition, drag-drop. Flip _userTyped
21472
21554
  // here so updated('availableOptions') auto-opens the bib for sources
@@ -21489,10 +21571,6 @@ class AuroCombobox extends AuroElement {
21489
21571
  if (this.dropdown.isBibFullscreen && this.input.value && this.input.value.length > 0 && this.dropdown.isPopoverVisible) {
21490
21572
  this.setInputFocus();
21491
21573
  }
21492
-
21493
- if (this._programmaticFilterRefresh) {
21494
- this._programmaticFilterRefresh = false;
21495
- }
21496
21574
  }
21497
21575
 
21498
21576
  /**
@@ -21691,6 +21769,12 @@ class AuroCombobox extends AuroElement {
21691
21769
  // setting the flag unconditionally here masks the user-typed open path.
21692
21770
  if (!this._userTyped) {
21693
21771
  this._programmaticFilterRefresh = true;
21772
+ // Self-clear after this update cycle completes. This collapses
21773
+ // the previous scattered clear-points into one and prevents the
21774
+ // flag from surviving into the next user interaction.
21775
+ this.updateComplete.then(() => {
21776
+ this._programmaticFilterRefresh = false;
21777
+ });
21694
21778
  }
21695
21779
 
21696
21780
  if (this.input.value !== this.value) {
@@ -21780,10 +21864,6 @@ class AuroCombobox extends AuroElement {
21780
21864
  } else if (!this.dropdown.isBibFullscreen) {
21781
21865
  this.hideBib();
21782
21866
  }
21783
-
21784
- if (this._programmaticFilterRefresh) {
21785
- this._programmaticFilterRefresh = false;
21786
- }
21787
21867
  }
21788
21868
 
21789
21869
  if (changedProperties.has('error')) {
@@ -21965,7 +22045,7 @@ class AuroCombobox extends AuroElement {
21965
22045
  <slot @slotchange="${this.handleSlotChange}"></slot>
21966
22046
  <${this.inputTag}
21967
22047
  id="inputInBib"
21968
- autofocus
22048
+ ?autofocus="${this.dropdownOpen && this.dropdown?.isBibFullscreen}"
21969
22049
  @input="${this.handleInputValueChange}"
21970
22050
  .a11yActivedescendant="${this.dropdownOpen && this.optionActive ? this.optionActive.id : undefined}"
21971
22051
  .a11yControls=${`${this.dropdownId}-floater-bib`}