@aurodesignsystem-dev/auro-formkit 0.0.0-pr1505.0 → 0.0.0-pr1506.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 (56) 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 +138 -266
  7. package/components/combobox/demo/getting-started.min.js +138 -266
  8. package/components/combobox/demo/index.min.js +138 -266
  9. package/components/combobox/dist/auro-combobox.d.ts +9 -0
  10. package/components/combobox/dist/index.js +138 -266
  11. package/components/combobox/dist/registered.js +138 -266
  12. package/components/counter/demo/customize.min.js +2 -2
  13. package/components/counter/demo/index.min.js +2 -2
  14. package/components/counter/dist/index.js +2 -2
  15. package/components/counter/dist/registered.js +2 -2
  16. package/components/datepicker/demo/api.md +0 -2
  17. package/components/datepicker/demo/customize.md +33 -195
  18. package/components/datepicker/demo/customize.min.js +41 -164
  19. package/components/datepicker/demo/index.min.js +40 -156
  20. package/components/datepicker/dist/index.js +40 -156
  21. package/components/datepicker/dist/registered.js +40 -156
  22. package/components/datepicker/dist/src/auro-datepicker.d.ts +0 -2
  23. package/components/dropdown/demo/customize.min.js +1 -1
  24. package/components/dropdown/demo/getting-started.min.js +1 -1
  25. package/components/dropdown/demo/index.min.js +1 -1
  26. package/components/dropdown/dist/index.js +1 -1
  27. package/components/dropdown/dist/registered.js +1 -1
  28. package/components/form/demo/customize.min.js +351 -599
  29. package/components/form/demo/getting-started.min.js +351 -599
  30. package/components/form/demo/index.min.js +351 -599
  31. package/components/form/demo/registerDemoDeps.min.js +351 -599
  32. package/components/input/demo/customize.md +55 -56
  33. package/components/input/demo/customize.min.js +36 -147
  34. package/components/input/demo/getting-started.min.js +36 -147
  35. package/components/input/demo/index.md +2 -2
  36. package/components/input/demo/index.min.js +36 -147
  37. package/components/input/dist/base-input.d.ts +0 -48
  38. package/components/input/dist/index.js +36 -147
  39. package/components/input/dist/registered.js +36 -147
  40. package/components/radio/demo/customize.min.js +1 -1
  41. package/components/radio/demo/getting-started.min.js +1 -1
  42. package/components/radio/demo/index.min.js +1 -1
  43. package/components/radio/dist/index.js +1 -1
  44. package/components/radio/dist/registered.js +1 -1
  45. package/components/select/demo/api.md +1 -0
  46. package/components/select/demo/customize.md +71 -0
  47. package/components/select/demo/customize.min.js +133 -26
  48. package/components/select/demo/getting-started.min.js +133 -26
  49. package/components/select/demo/index.min.js +133 -26
  50. package/components/select/demo/keyboard-behavior.md +18 -0
  51. package/components/select/dist/auro-select.d.ts +38 -2
  52. package/components/select/dist/index.js +133 -26
  53. package/components/select/dist/registered.js +133 -26
  54. package/components/select/dist/selectUtils.d.ts +12 -0
  55. package/custom-elements.json +114 -274
  56. package/package.json +1 -1
@@ -11175,6 +11175,7 @@ let AuroInputUtilities$3 = class AuroInputUtilities {
11175
11175
  const maskOptions = this.getMaskOptions('date', normalizedFormat);
11176
11176
 
11177
11177
  if (!(valueObject instanceof Date) || Number.isNaN(valueObject.getTime()) || !maskOptions || typeof maskOptions.format !== 'function') {
11178
+ console.debug('Invalid date object or mask options for formatting', { valueObject, maskOptions }); // eslint-disable-line no-console
11178
11179
  return undefined;
11179
11180
  }
11180
11181
 
@@ -11326,10 +11327,8 @@ let BaseInput$2 = class BaseInput extends AuroElement$6 {
11326
11327
  this.layout = 'classic';
11327
11328
  this.locale = 'en-US';
11328
11329
  this.max = undefined;
11329
- this._maxObject = undefined;
11330
11330
  this.maxLength = undefined;
11331
11331
  this.min = undefined;
11332
- this._minObject = undefined;
11333
11332
  this.minLength = undefined;
11334
11333
  this.required = false;
11335
11334
  this.onDark = false;
@@ -11337,7 +11336,6 @@ let BaseInput$2 = class BaseInput extends AuroElement$6 {
11337
11336
  this.size = 'lg';
11338
11337
  this.shape = 'classic';
11339
11338
  this.value = undefined;
11340
- this._valueObject = undefined;
11341
11339
 
11342
11340
  this._initializePrivateDefaults();
11343
11341
  }
@@ -11877,7 +11875,7 @@ let BaseInput$2 = class BaseInput extends AuroElement$6 {
11877
11875
  * @returns {Date|undefined}
11878
11876
  */
11879
11877
  get valueObject() {
11880
- return this._valueObject || this._computeDateObjectFallback(this.value);
11878
+ return this.value && dateFormatter$3.isValidDate(this.value) ? dateFormatter$3.stringToDateInstance(this.value) : undefined;
11881
11879
  }
11882
11880
 
11883
11881
  /**
@@ -11885,7 +11883,7 @@ let BaseInput$2 = class BaseInput extends AuroElement$6 {
11885
11883
  * @returns {Date|undefined}
11886
11884
  */
11887
11885
  get minObject() {
11888
- return this._minObject || this._computeDateObjectFallback(this.min);
11886
+ return this.min && dateFormatter$3.isValidDate(this.min) ? dateFormatter$3.stringToDateInstance(this.min) : undefined;
11889
11887
  }
11890
11888
 
11891
11889
  /**
@@ -11893,50 +11891,7 @@ let BaseInput$2 = class BaseInput extends AuroElement$6 {
11893
11891
  * @returns {Date|undefined}
11894
11892
  */
11895
11893
  get maxObject() {
11896
- return this._maxObject || this._computeDateObjectFallback(this.max);
11897
- }
11898
-
11899
- /**
11900
- * Parses a date string into a Date object when the corresponding `_*Object`
11901
- * field hasn't been synced yet by `updated()`. Returns undefined when the
11902
- * input type/format isn't a full date or the string is not a valid date.
11903
- *
11904
- * Why this exists: a parent (datepicker) can call `inputN.validate()` from
11905
- * inside its own `updated()` before this input's `updated()` has run
11906
- * `syncDateValues()` — so `_valueObject`/`_maxObject` are still `undefined`
11907
- * and range checks would otherwise silently no-op (flipping the result to
11908
- * `valid` or `patternMismatch`).
11909
- * @private
11910
- * @param {string|undefined} dateStr - ISO date string from `value`/`min`/`max`.
11911
- * @returns {Date|undefined}
11912
- */
11913
- _computeDateObjectFallback(dateStr) {
11914
- if (!dateStr || !this.util || !this.util.isFullDateFormat(this.type, this.format)) {
11915
- return undefined;
11916
- }
11917
- if (!dateFormatter$3.isValidDate(dateStr)) {
11918
- return undefined;
11919
- }
11920
- return dateFormatter$3.stringToDateInstance(dateStr);
11921
- }
11922
-
11923
- /**
11924
- * Internal setter for readonly date object properties.
11925
- * @private
11926
- * @param {'valueObject'|'minObject'|'maxObject'} propertyName - Public object property name.
11927
- * @param {Date|undefined} propertyValue - Value to assign.
11928
- * @returns {void}
11929
- */
11930
- setDateObjectProperty(propertyName, propertyValue) {
11931
- const internalPropertyName = `_${propertyName}`;
11932
- const previousValue = this[internalPropertyName];
11933
-
11934
- if (previousValue === propertyValue) {
11935
- return;
11936
- }
11937
-
11938
- this[internalPropertyName] = propertyValue;
11939
- this.requestUpdate(propertyName, previousValue);
11894
+ return this.max && dateFormatter$3.isValidDate(this.max) ? dateFormatter$3.stringToDateInstance(this.max) : undefined;
11940
11895
  }
11941
11896
 
11942
11897
  connectedCallback() {
@@ -11965,7 +11920,6 @@ let BaseInput$2 = class BaseInput extends AuroElement$6 {
11965
11920
  format: this.format
11966
11921
  });
11967
11922
  this.configureDataForType();
11968
- this.syncDateValues();
11969
11923
  }
11970
11924
 
11971
11925
  disconnectedCallback() {
@@ -11985,10 +11939,6 @@ let BaseInput$2 = class BaseInput extends AuroElement$6 {
11985
11939
  this.wrapperElement.addEventListener('click', this.handleClick);
11986
11940
  }
11987
11941
 
11988
- // add attribute for query selectors when auro-input is registered under a custom name
11989
- if (this.tagName.toLowerCase() !== 'auro-input' && !this.hasAttribute('auro-input')) {
11990
- this.setAttribute('auro-input', '');
11991
- }
11992
11942
  this.inputId = this.id ? `${this.id}-input` : window.crypto.randomUUID();
11993
11943
 
11994
11944
  // use validity message override if declared when initializing the component
@@ -11999,7 +11949,6 @@ let BaseInput$2 = class BaseInput extends AuroElement$6 {
11999
11949
  this.setCustomHelpTextMessage();
12000
11950
  this.configureAutoFormatting();
12001
11951
  this.configureDataForType();
12002
- this.syncDateValues();
12003
11952
  }
12004
11953
 
12005
11954
  /**
@@ -12136,8 +12085,6 @@ let BaseInput$2 = class BaseInput extends AuroElement$6 {
12136
12085
  this.configureDataForType();
12137
12086
  }
12138
12087
 
12139
- this.syncDateValues(changedProperties);
12140
-
12141
12088
  if (changedProperties.has('value')) {
12142
12089
  if (this.value && this.value.length > 0) {
12143
12090
  this.hasValue = true;
@@ -12159,14 +12106,14 @@ let BaseInput$2 = class BaseInput extends AuroElement$6 {
12159
12106
 
12160
12107
  if (formattedValue !== this.inputElement.value) {
12161
12108
  this.skipNextProgrammaticInputEvent = true;
12162
- if (this.maskInstance && this.type === 'credit-card') {
12109
+ if (this.maskInstance && this.type !== 'date') {
12163
12110
  // Route through the mask so its _value and el.value stay in lock-step
12164
12111
  // (set value calls updateControl which writes el.value = displayValue).
12165
12112
  // Writing el.value directly leaves the mask thinking displayValue is
12166
- // stale; _saveSelection on the next focus/click then warns. Scoped to
12167
- // credit-card so date's own formattedValue (raw ISO when calendar-invalid)
12168
- // isn't re-masked through the mm/dd/yyyy mask, which would truncate it
12169
- // and flip validity from patternMismatch to tooShort.
12113
+ // stale; _saveSelection on the next focus/click then warns. Date is
12114
+ // excluded because its formattedValue can be raw ISO when the calendar
12115
+ // is invalid, and re-masking through mm/dd/yyyy would truncate it and
12116
+ // flip validity from patternMismatch to tooShort.
12170
12117
  this.maskInstance.value = formattedValue || '';
12171
12118
  } else if (formattedValue) {
12172
12119
  this.inputElement.value = formattedValue;
@@ -12208,120 +12155,60 @@ let BaseInput$2 = class BaseInput extends AuroElement$6 {
12208
12155
  }));
12209
12156
  }
12210
12157
 
12211
-
12212
- /**
12213
- * Synchronizes the ISO string values and Date object representations for date-related properties.
12214
- * This keeps the model and display values aligned when either side changes.
12215
- *
12216
- * When a full date format is in use, this method updates `value`, `min`, and `max` from their corresponding
12217
- * Date objects or vice versa, based on which properties have changed. It only runs when the current configuration
12218
- * represents a full year/month/day date format.
12219
- *
12220
- * @param {Map<string, unknown>|undefined} [changedProperties=undefined] - Optional map of changed properties used to limit which values are synchronized.
12221
- * @returns {void}
12222
- * @private
12223
- */
12224
- syncDateValues(changedProperties = undefined) {
12225
- if (!this.util.isFullDateFormat(this.type, this.format)) {
12226
- return;
12227
- }
12228
-
12229
- this.syncSingleDateValue(changedProperties, 'valueObject', 'value');
12230
- this.syncSingleDateValue(changedProperties, 'minObject', 'min');
12231
- this.syncSingleDateValue(changedProperties, 'maxObject', 'max');
12232
- }
12233
-
12234
- /**
12235
- * Synchronizes one date object/string property pair.
12236
- * @private
12237
- * @param {Map<string, unknown>|undefined} changedProperties - Map of changed properties from Lit.
12238
- * @param {string} objectProperty - Date object property name.
12239
- * @param {string} valueProperty - ISO string property name.
12240
- * @returns {void}
12241
- */
12242
- syncSingleDateValue(changedProperties, objectProperty, valueProperty) {
12243
- const objectPropertyChanged = !changedProperties || changedProperties.has(objectProperty);
12244
-
12245
- // objectProperty wins over valueProperty when both changed
12246
- if (objectPropertyChanged && this[objectProperty]) {
12247
- this[valueProperty] = dateFormatter$3.toISOFormatString(this[objectProperty]);
12248
- return;
12249
- }
12250
-
12251
- const valuePropertyChanged = !changedProperties || changedProperties.has(valueProperty);
12252
- if (!valuePropertyChanged) {
12253
- return;
12254
- }
12255
-
12256
- // when value is newly set to the same ISO string that corresponds to the existing Date object, do not clear the Date object (avoid unnecessary updates)
12257
- if (
12258
- changedProperties &&
12259
- valueProperty === 'value' &&
12260
- changedProperties.get('value') === undefined &&
12261
- this[objectProperty] instanceof Date &&
12262
- this[valueProperty] === dateFormatter$3.toISOFormatString(this[objectProperty])
12263
- ) {
12264
- return;
12265
- }
12266
-
12267
- if (dateFormatter$3.isValidDate(this[valueProperty])) {
12268
- this.setDateObjectProperty(objectProperty, dateFormatter$3.stringToDateInstance(this[valueProperty]));
12269
- } else {
12270
- this.setDateObjectProperty(objectProperty, undefined);
12271
- }
12272
- }
12273
-
12274
12158
  /**
12275
12159
  * Sets up IMasks and logic based on auto-formatting requirements.
12276
12160
  * @private
12277
12161
  * @returns {void}
12278
12162
  */
12279
12163
  configureAutoFormatting() {
12280
- // Re-entrancy guard. The patched-setter's synthetic input event (suppressed
12281
- // by _configuringMask above) could otherwise trigger handleInput
12282
- // processCreditCard configureAutoFormatting before the outer call's
12283
- // set value has finished its alignCursor pass.
12164
+ // _configuringMask gates two things: external re-entry into this method
12165
+ // while setup is mid-flight (from property changes that call back here),
12166
+ // and the accept/complete listeners below — both need to ignore the mask
12167
+ // events fired by our own value-restore step.
12284
12168
  if (this._configuringMask) return;
12285
12169
  this._configuringMask = true;
12286
12170
  try {
12171
+ // Destroy any prior mask so IMask can attach fresh under the new format.
12287
12172
  if (this.maskInstance) {
12288
12173
  this.maskInstance.destroy();
12289
12174
  }
12290
12175
 
12291
- // Pass new format to util
12292
12176
  this.util.updateFormat(this.format);
12293
12177
 
12294
12178
  const maskOptions = this.util.getMaskOptions(this.type, this.format);
12295
12179
 
12296
12180
  if (this.inputElement && maskOptions.mask) {
12297
-
12298
- // Stash and clear any existing value before IMask init.
12299
- // IMask's constructor processes the current input value which requires
12300
- // selection state clearing first avoids that scenario entirely.
12301
- // When the format changes (e.g. locale switch) and we have a valid ISO
12302
- // model value, compute the display string for the NEW format instead of
12303
- // re-using the old display string, which may be invalid in the new mask.
12181
+ // Capture the current display so it can be re-applied after IMask
12182
+ // attaches. The restore at the bottom goes through maskInstance.value
12183
+ // (not inputElement.value directly) so the mask's internal state and
12184
+ // the input's displayed text stay in lock-step.
12304
12185
  let existingValue = this.inputElement.value;
12186
+
12187
+ // Format-change case (e.g. locale switch): existingValue is the OLD
12188
+ // mask's display string and may not parse under the new mask. When
12189
+ // we have a valid date model, rebuild the display from valueObject
12190
+ // (the canonical source) using the new mask's format function.
12305
12191
  if (
12306
12192
  this.util.isFullDateFormat(this.type, this.format) &&
12307
12193
  this.value &&
12308
- dateFormatter$3.isValidDate(this.value) &&
12309
- this.valueObject instanceof Date &&
12310
- !Number.isNaN(this.valueObject.getTime()) &&
12194
+ this.valueObject &&
12311
12195
  typeof maskOptions.format === 'function'
12312
12196
  ) {
12313
12197
  existingValue = maskOptions.format(this.valueObject);
12314
12198
  }
12315
12199
 
12200
+ // Clear before IMask attaches so the constructor seeds an empty
12201
+ // internal value. Otherwise IMask reads the stale unmasked string
12202
+ // and emits a spurious 'accept' before the restore below runs.
12316
12203
  this.skipNextProgrammaticInputEvent = true;
12317
12204
  this.inputElement.value = '';
12318
12205
 
12319
12206
  this.maskInstance = IMask$3(this.inputElement, maskOptions);
12320
12207
 
12208
+ // Mask fires 'accept' on every value change, including the restore
12209
+ // step below. Skip events fired during configureAutoFormatting so
12210
+ // we don't overwrite a value the parent just pushed.
12321
12211
  this.maskInstance.on('accept', () => {
12322
- // Suppress propagation during configureAutoFormatting's own value-restoration
12323
- // (line below) — the mask emits 'accept' on every value-set, including ours,
12324
- // and we don't want to overwrite a value the parent just pushed.
12325
12212
  if (this._configuringMask) return;
12326
12213
  this.value = this.util.toModelValue(this.maskInstance.value, this.format);
12327
12214
  if (this.type === "date") {
@@ -12329,6 +12216,8 @@ let BaseInput$2 = class BaseInput extends AuroElement$6 {
12329
12216
  }
12330
12217
  });
12331
12218
 
12219
+ // Mask fires 'complete' on the restore step below for any value that
12220
+ // happens to be a complete match. Same setup-suppression as 'accept'.
12332
12221
  this.maskInstance.on('complete', () => {
12333
12222
  if (this._configuringMask) return;
12334
12223
  this.value = this.util.toModelValue(this.maskInstance.value, this.format);
@@ -12337,7 +12226,9 @@ let BaseInput$2 = class BaseInput extends AuroElement$6 {
12337
12226
  }
12338
12227
  });
12339
12228
 
12340
- // Restore the stashed value through IMask so it's properly masked
12229
+ // Write existingValue through the mask (not the input directly) so
12230
+ // the mask reformats it under the new rules and keeps its internal
12231
+ // _value aligned with the input's displayed text.
12341
12232
  if (existingValue) {
12342
12233
  this.maskInstance.value = existingValue;
12343
12234
  }
@@ -12505,7 +12396,6 @@ let BaseInput$2 = class BaseInput extends AuroElement$6 {
12505
12396
  */
12506
12397
  reset() {
12507
12398
  this.value = undefined;
12508
- this.setDateObjectProperty('valueObject', undefined);
12509
12399
  this.validation.reset(this);
12510
12400
  }
12511
12401
 
@@ -12514,7 +12404,6 @@ let BaseInput$2 = class BaseInput extends AuroElement$6 {
12514
12404
  */
12515
12405
  clear() {
12516
12406
  this.value = undefined;
12517
- this.setDateObjectProperty('valueObject', undefined);
12518
12407
  }
12519
12408
 
12520
12409
  /**
@@ -13043,7 +12932,7 @@ let AuroHelpText$8 = class AuroHelpText extends i$3 {
13043
12932
  }
13044
12933
  };
13045
12934
 
13046
- var formkitVersion$8 = '202606171946';
12935
+ var formkitVersion$8 = '202606192004';
13047
12936
 
13048
12937
  // Copyright (c) 2025 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
13049
12938
  // See LICENSE in the project root for license information.
@@ -24282,6 +24171,7 @@ let AuroInputUtilities$1 = class AuroInputUtilities {
24282
24171
  const maskOptions = this.getMaskOptions('date', normalizedFormat);
24283
24172
 
24284
24173
  if (!(valueObject instanceof Date) || Number.isNaN(valueObject.getTime()) || !maskOptions || typeof maskOptions.format !== 'function') {
24174
+ console.debug('Invalid date object or mask options for formatting', { valueObject, maskOptions }); // eslint-disable-line no-console
24285
24175
  return undefined;
24286
24176
  }
24287
24177
 
@@ -27162,7 +27052,7 @@ let AuroBibtemplate$3 = class AuroBibtemplate extends i$3 {
27162
27052
  }
27163
27053
  };
27164
27054
 
27165
- var formkitVersion$2$1 = '202606171946';
27055
+ var formkitVersion$2$1 = '202606192004';
27166
27056
 
27167
27057
  let l$1$2 = class l{generateElementName(t,e){let o=t;return o+="-",o+=e.replace(/[.]/g,"_"),o}generateTag(o,s,a){const r=this.generateElementName(o,s),i=i$2`${s$3(r)}`;return customElements.get(r)||customElements.define(r,class extends a{}),i}};let d$1$2 = class d{registerComponent(t,e){customElements.get(t)||customElements.define(t,class extends e{});}closestElement(t,e=this,o=(e,s=e&&e.closest(t))=>e&&e!==document&&e!==window?s||o(e.getRootNode().host):null){return o(e)}handleComponentTagRename(t,e){const o=e.toLowerCase();t.tagName.toLowerCase()!==o&&t.setAttribute(o,true);}elementMatch(t,e){const o=e.toLowerCase();return t.tagName.toLowerCase()===o||t.hasAttribute(o)}getSlotText(t,e){const o=t.shadowRoot?.querySelector(`slot[name="${e}"]`),s=(o?.assignedNodes({flatten:true})||[]).map(t=>t.textContent?.trim()).join(" ").trim();return s||null}};let h$1$2 = class h{registerComponent(t,e){customElements.get(t)||customElements.define(t,class extends e{});}closestElement(t,e=this,o=(e,s=e&&e.closest(t))=>e&&e!==document&&e!==window?s||o(e.getRootNode().host):null){return o(e)}handleComponentTagRename(t,e){const o=e.toLowerCase();t.tagName.toLowerCase()!==o&&t.setAttribute(o,true);}elementMatch(t,e){const o=e.toLowerCase();return t.tagName.toLowerCase()===o||t.hasAttribute(o)}};var c$1$3=i$6`:host{color:var(--ds-auro-loader-color)}:host>span{background-color:var(--ds-auro-loader-background-color);border-color:var(--ds-auro-loader-border-color)}:host([onlight]),:host([appearance=brand]){--ds-auro-loader-color: var(--ds-basic-color-brand-primary, #01426a)}:host([ondark]),:host([appearance=inverse]){--ds-auro-loader-color: var(--ds-basic-color-texticon-inverse, #ffffff)}:host([orbit])>span{--ds-auro-loader-background-color: transparent}:host([orbit])>span:nth-child(1){--ds-auro-loader-border-color: currentcolor;opacity:.25}:host([orbit])>span:nth-child(2){--ds-auro-loader-border-color: currentcolor;border-right-color:transparent;border-bottom-color:transparent;border-left-color:transparent}
27168
27058
  `,u$4$2=i$6`.body-default{font-size:var(--wcss-body-default-font-size, 1rem);line-height:var(--wcss-body-default-line-height, 1.5rem)}.body-default,.body-lg{font-family:var(--wcss-body-family, "AS Circular"),system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;font-weight:var(--wcss-body-weight, 450);letter-spacing:var(--wcss-body-letter-spacing, 0)}.body-lg{font-size:var(--wcss-body-lg-font-size, 1.125rem);line-height:var(--wcss-body-lg-line-height, 1.625rem)}.body-sm{font-size:var(--wcss-body-sm-font-size, .875rem);line-height:var(--wcss-body-sm-line-height, 1.25rem)}.body-sm,.body-xs{font-family:var(--wcss-body-family, "AS Circular"),system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;font-weight:var(--wcss-body-weight, 450);letter-spacing:var(--wcss-body-letter-spacing, 0)}.body-xs{font-size:var(--wcss-body-xs-font-size, .75rem);line-height:var(--wcss-body-xs-line-height, 1rem)}.body-2xs{font-family:var(--wcss-body-family, "AS Circular"),system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;font-size:var(--wcss-body-2xs-font-size, .625rem);font-weight:var(--wcss-body-weight, 450);letter-spacing:var(--wcss-body-letter-spacing, 0);line-height:var(--wcss-body-2xs-line-height, .875rem)}.display-2xl{font-family:var(--wcss-display-2xl-family, "AS Circular"),var(--wcss-display-2xl-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-display-2xl-font-size, clamp(3.5rem, 6vw, 5.375rem));font-weight:var(--wcss-display-2xl-weight, 300);letter-spacing:var(--wcss-display-2xl-letter-spacing, 0);line-height:var(--wcss-display-2xl-line-height, 1.3)}.display-xl{font-family:var(--wcss-display-xl-family, "AS Circular"),var(--wcss-display-xl-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-display-xl-font-size, clamp(3rem, 5.3333333333vw, 4.5rem));font-weight:var(--wcss-display-xl-weight, 300);letter-spacing:var(--wcss-display-xl-letter-spacing, 0);line-height:var(--wcss-display-xl-line-height, 1.3)}.display-lg{font-family:var(--wcss-display-lg-family, "AS Circular"),var(--wcss-display-lg-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-display-lg-font-size, clamp(2.75rem, 4.6666666667vw, 4rem));font-weight:var(--wcss-display-lg-weight, 300);letter-spacing:var(--wcss-display-lg-letter-spacing, 0);line-height:var(--wcss-display-lg-line-height, 1.3)}.display-md{font-family:var(--wcss-display-md-family, "AS Circular"),var(--wcss-display-md-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-display-md-font-size, clamp(2.5rem, 4vw, 3.5rem));font-weight:var(--wcss-display-md-weight, 300);letter-spacing:var(--wcss-display-md-letter-spacing, 0);line-height:var(--wcss-display-md-line-height, 1.3)}.display-sm{font-family:var(--wcss-display-sm-family, "AS Circular"),var(--wcss-display-sm-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-display-sm-font-size, clamp(2rem, 3.6666666667vw, 3rem));font-weight:var(--wcss-display-sm-weight, 300);letter-spacing:var(--wcss-display-sm-letter-spacing, 0);line-height:var(--wcss-display-sm-line-height, 1.3)}.display-xs{font-family:var(--wcss-display-xs-family, "AS Circular"),var(--wcss-display-xs-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-display-xs-font-size, clamp(1.75rem, 3vw, 2.375rem));font-weight:var(--wcss-display-xs-weight, 300);letter-spacing:var(--wcss-display-xs-letter-spacing, 0);line-height:var(--wcss-display-xs-line-height, 1.3)}.heading-xl{font-family:var(--wcss-heading-xl-family, "AS Circular"),var(--wcss-heading-xl-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-heading-xl-font-size, clamp(2rem, 3vw, 2.5rem));font-weight:var(--wcss-heading-xl-weight, 300);letter-spacing:var(--wcss-heading-xl-letter-spacing, 0);line-height:var(--wcss-heading-xl-line-height, 1.3)}.heading-lg{font-family:var(--wcss-heading-lg-family, "AS Circular"),var(--wcss-heading-lg-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-heading-lg-font-size, clamp(1.75rem, 2.6666666667vw, 2.25rem));font-weight:var(--wcss-heading-lg-weight, 300);letter-spacing:var(--wcss-heading-lg-letter-spacing, 0);line-height:var(--wcss-heading-lg-line-height, 1.3)}.heading-md{font-family:var(--wcss-heading-md-family, "AS Circular"),var(--wcss-heading-md-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-heading-md-font-size, clamp(1.625rem, 2.3333333333vw, 1.75rem));font-weight:var(--wcss-heading-md-weight, 300);letter-spacing:var(--wcss-heading-md-letter-spacing, 0);line-height:var(--wcss-heading-md-line-height, 1.3)}.heading-sm{font-family:var(--wcss-heading-sm-family, "AS Circular"),var(--wcss-heading-sm-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-heading-sm-font-size, clamp(1.375rem, 2vw, 1.5rem));font-weight:var(--wcss-heading-sm-weight, 300);letter-spacing:var(--wcss-heading-sm-letter-spacing, 0);line-height:var(--wcss-heading-sm-line-height, 1.3)}.heading-xs{font-family:var(--wcss-heading-xs-family, "AS Circular"),var(--wcss-heading-xs-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-heading-xs-font-size, clamp(1.25rem, 1.6666666667vw, 1.25rem));font-weight:var(--wcss-heading-xs-weight, 450);letter-spacing:var(--wcss-heading-xs-letter-spacing, 0);line-height:var(--wcss-heading-xs-line-height, 1.3)}.heading-2xs{font-family:var(--wcss-heading-2xs-family, "AS Circular"),var(--wcss-heading-2xs-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-heading-2xs-font-size, clamp(1.125rem, 1.5vw, 1.125rem));font-weight:var(--wcss-heading-2xs-weight, 450);letter-spacing:var(--wcss-heading-2xs-letter-spacing, 0);line-height:var(--wcss-heading-2xs-line-height, 1.3)}.accent-2xl{font-family:var(--wcss-accent-2xl-family, "Good OT"),var(--wcss-accent-2xl-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-accent-2xl-font-size, clamp(2rem, 3.1666666667vw, 2.375rem));font-weight:var(--wcss-accent-2xl-weight, 450);letter-spacing:var(--wcss-accent-2xl-letter-spacing, .05em);line-height:var(--wcss-accent-2xl-line-height, 1)}.accent-2xl,.accent-xl{text-transform:uppercase}.accent-xl{font-family:var(--wcss-accent-xl-family, "Good OT"),var(--wcss-accent-xl-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-accent-xl-font-size, clamp(1.625rem, 2.3333333333vw, 2rem));font-weight:var(--wcss-accent-xl-weight, 450);letter-spacing:var(--wcss-accent-xl-letter-spacing, .05em);line-height:var(--wcss-accent-xl-line-height, 1.3)}.accent-lg{font-family:var(--wcss-accent-lg-family, "Good OT"),var(--wcss-accent-lg-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-accent-lg-font-size, clamp(1.5rem, 2.1666666667vw, 1.75rem));font-weight:var(--wcss-accent-lg-weight, 450);letter-spacing:var(--wcss-accent-lg-letter-spacing, .05em);line-height:var(--wcss-accent-lg-line-height, 1.3)}.accent-lg,.accent-md{text-transform:uppercase}.accent-md{font-family:var(--wcss-accent-md-family, "Good OT"),var(--wcss-accent-md-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-accent-md-font-size, clamp(1.375rem, 1.8333333333vw, 1.5rem));font-weight:var(--wcss-accent-md-weight, 500);letter-spacing:var(--wcss-accent-md-letter-spacing, .05em);line-height:var(--wcss-accent-md-line-height, 1.3)}.accent-sm{font-family:var(--wcss-accent-sm-family, "Good OT"),var(--wcss-accent-sm-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-accent-sm-font-size, clamp(1.125rem, 1.5vw, 1.25rem));font-weight:var(--wcss-accent-sm-weight, 500);letter-spacing:var(--wcss-accent-sm-letter-spacing, .05em);line-height:var(--wcss-accent-sm-line-height, 1.3)}.accent-sm,.accent-xs{text-transform:uppercase}.accent-xs{font-family:var(--wcss-accent-xs-family, "Good OT"),var(--wcss-accent-xs-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-accent-xs-font-size, clamp(1rem, 1.3333333333vw, 1rem));font-weight:var(--wcss-accent-xs-weight, 500);letter-spacing:var(--wcss-accent-xs-letter-spacing, .1em);line-height:var(--wcss-accent-xs-line-height, 1.3)}.accent-2xs{font-family:var(--wcss-accent-2xs-family, "Good OT"),var(--wcss-accent-2xs-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-accent-2xs-font-size, clamp(.875rem, 1.1666666667vw, .875rem));font-weight:var(--wcss-accent-2xs-weight, 450);letter-spacing:var(--wcss-accent-2xs-letter-spacing, .1em);line-height:var(--wcss-accent-2xs-line-height, 1.3);text-transform:uppercase}:focus:not(:focus-visible){outline:3px solid transparent}:host,:host>span{position:relative}:host{width:2rem;height:2rem;display:inline-block;font-size:0}:host>span{position:absolute;display:inline-block;float:none;top:0;left:0;width:2rem;height:2rem;border-radius:100%;border-style:solid;border-width:0;box-sizing:border-box}:host([xs]),:host([xs])>span{width:1.2rem;height:1.2rem}:host([sm]),:host([sm])>span{width:3rem;height:3rem}:host([md]),:host([md])>span{width:5rem;height:5rem}:host([lg]),:host([lg])>span{width:8rem;height:8rem}:host{--margin: .375rem;--margin-xs: .2rem;--margin-sm: .5rem;--margin-md: .75rem;--margin-lg: 1rem}:host([pulse]),:host([pulse])>span{position:relative}:host([pulse]){width:calc(3rem + var(--margin) * 6);height:calc(1rem + var(--margin) * 2)}:host([pulse])>span{width:1rem;height:1rem;margin:var(--margin);animation:pulse 1.5s ease infinite}:host([pulse][xs]){width:calc(1.95rem + var(--margin-xs) * 6);height:calc(.65rem + var(--margin-xs) * 2)}:host([pulse][xs])>span{margin:var(--margin-xs);width:.65rem;height:.65rem}:host([pulse][sm]){width:calc(6rem + var(--margin-sm) * 6);height:calc(2rem + var(--margin-sm) * 2)}:host([pulse][sm])>span{margin:var(--margin-sm);width:2rem;height:2rem}:host([pulse][md]){width:calc(9rem + var(--margin-md) * 6);height:calc(3rem + var(--margin-md) * 2)}:host([pulse][md])>span{margin:var(--margin-md);width:3rem;height:3rem}:host([pulse][lg]){width:calc(15rem + var(--margin-lg) * 6);height:calc(5rem + var(--margin-lg) * 2)}:host([pulse][lg])>span{margin:var(--margin-lg);width:5rem;height:5rem}:host([pulse])>span:nth-child(1){animation-delay:-.4s}:host([pulse])>span:nth-child(2){animation-delay:-.2s}:host([pulse])>span:nth-child(3){animation-delay:0ms}@keyframes pulse{0%,to{opacity:.1;transform:scale(.9)}50%{opacity:1;transform:scale(1.1)}}:host([orbit]),:host([orbit])>span{opacity:1}:host([orbit])>span{border-width:5px}:host([orbit])>span:nth-child(2){animation:orbit 2s linear infinite}:host([orbit][sm])>span{border-width:8px}:host([orbit][md])>span{border-width:13px}:host([orbit][lg])>span{border-width:21px}@keyframes orbit{0%{transform:rotate(0)}to{transform:rotate(360deg)}}:host([ringworm])>svg{animation:rotate 2s linear infinite;height:100%;width:100%;stroke:currentcolor;stroke-width:8}:host([ringworm]) .path{stroke-dashoffset:0;animation:ringworm 1.5s ease-in-out infinite;stroke-linecap:round}@keyframes rotate{to{transform:rotate(360deg)}}@keyframes ringworm{0%{stroke-dasharray:1,200;stroke-dashoffset:0}50%{stroke-dasharray:89,200;stroke-dashoffset:-35px}to{stroke-dasharray:89,200;stroke-dashoffset:-124px}}:host([laser]){position:static;width:100%;display:block;height:0;overflow:hidden;font-size:unset}:host([laser])>span{position:fixed;width:100%;height:.25rem;border-radius:0;z-index:100}:host([laser])>span:nth-child(1){border-color:currentcolor;opacity:.25}:host([laser])>span:nth-child(2){border-color:currentcolor;animation:laser 2s linear infinite;opacity:1;width:50%}:host([laser][sm])>span:nth-child(2){width:20%}:host([laser][md])>span:nth-child(2){width:30%}:host([laser][lg])>span:nth-child(2){width:50%;animation-duration:1.5s}:host([laser][xl])>span:nth-child(2){width:80%;animation-duration:1.5s}@keyframes laser{0%{left:-100%}to{left:110%}}:host>.no-animation{display:none}@media (prefers-reduced-motion: reduce){:host{display:flex;align-items:center;justify-content:center}:host>span{opacity:1}:host>.loader{display:none}:host>svg{display:none}:host>.no-animation{display:block}}
@@ -32673,7 +32563,7 @@ let AuroHelpText$2$1 = class AuroHelpText extends i$3 {
32673
32563
  }
32674
32564
  };
32675
32565
 
32676
- var formkitVersion$1$3 = '202606171946';
32566
+ var formkitVersion$1$3 = '202606192004';
32677
32567
 
32678
32568
  let AuroElement$2$2 = class AuroElement extends i$3 {
32679
32569
  static get properties() {
@@ -44387,6 +44277,7 @@ let AuroInputUtilities$2 = class AuroInputUtilities {
44387
44277
  const maskOptions = this.getMaskOptions('date', normalizedFormat);
44388
44278
 
44389
44279
  if (!(valueObject instanceof Date) || Number.isNaN(valueObject.getTime()) || !maskOptions || typeof maskOptions.format !== 'function') {
44280
+ console.debug('Invalid date object or mask options for formatting', { valueObject, maskOptions }); // eslint-disable-line no-console
44390
44281
  return undefined;
44391
44282
  }
44392
44283
 
@@ -44538,10 +44429,8 @@ let BaseInput$1 = class BaseInput extends AuroElement$1$3 {
44538
44429
  this.layout = 'classic';
44539
44430
  this.locale = 'en-US';
44540
44431
  this.max = undefined;
44541
- this._maxObject = undefined;
44542
44432
  this.maxLength = undefined;
44543
44433
  this.min = undefined;
44544
- this._minObject = undefined;
44545
44434
  this.minLength = undefined;
44546
44435
  this.required = false;
44547
44436
  this.onDark = false;
@@ -44549,7 +44438,6 @@ let BaseInput$1 = class BaseInput extends AuroElement$1$3 {
44549
44438
  this.size = 'lg';
44550
44439
  this.shape = 'classic';
44551
44440
  this.value = undefined;
44552
- this._valueObject = undefined;
44553
44441
 
44554
44442
  this._initializePrivateDefaults();
44555
44443
  }
@@ -45089,7 +44977,7 @@ let BaseInput$1 = class BaseInput extends AuroElement$1$3 {
45089
44977
  * @returns {Date|undefined}
45090
44978
  */
45091
44979
  get valueObject() {
45092
- return this._valueObject || this._computeDateObjectFallback(this.value);
44980
+ return this.value && dateFormatter$2.isValidDate(this.value) ? dateFormatter$2.stringToDateInstance(this.value) : undefined;
45093
44981
  }
45094
44982
 
45095
44983
  /**
@@ -45097,7 +44985,7 @@ let BaseInput$1 = class BaseInput extends AuroElement$1$3 {
45097
44985
  * @returns {Date|undefined}
45098
44986
  */
45099
44987
  get minObject() {
45100
- return this._minObject || this._computeDateObjectFallback(this.min);
44988
+ return this.min && dateFormatter$2.isValidDate(this.min) ? dateFormatter$2.stringToDateInstance(this.min) : undefined;
45101
44989
  }
45102
44990
 
45103
44991
  /**
@@ -45105,50 +44993,7 @@ let BaseInput$1 = class BaseInput extends AuroElement$1$3 {
45105
44993
  * @returns {Date|undefined}
45106
44994
  */
45107
44995
  get maxObject() {
45108
- return this._maxObject || this._computeDateObjectFallback(this.max);
45109
- }
45110
-
45111
- /**
45112
- * Parses a date string into a Date object when the corresponding `_*Object`
45113
- * field hasn't been synced yet by `updated()`. Returns undefined when the
45114
- * input type/format isn't a full date or the string is not a valid date.
45115
- *
45116
- * Why this exists: a parent (datepicker) can call `inputN.validate()` from
45117
- * inside its own `updated()` before this input's `updated()` has run
45118
- * `syncDateValues()` — so `_valueObject`/`_maxObject` are still `undefined`
45119
- * and range checks would otherwise silently no-op (flipping the result to
45120
- * `valid` or `patternMismatch`).
45121
- * @private
45122
- * @param {string|undefined} dateStr - ISO date string from `value`/`min`/`max`.
45123
- * @returns {Date|undefined}
45124
- */
45125
- _computeDateObjectFallback(dateStr) {
45126
- if (!dateStr || !this.util || !this.util.isFullDateFormat(this.type, this.format)) {
45127
- return undefined;
45128
- }
45129
- if (!dateFormatter$2.isValidDate(dateStr)) {
45130
- return undefined;
45131
- }
45132
- return dateFormatter$2.stringToDateInstance(dateStr);
45133
- }
45134
-
45135
- /**
45136
- * Internal setter for readonly date object properties.
45137
- * @private
45138
- * @param {'valueObject'|'minObject'|'maxObject'} propertyName - Public object property name.
45139
- * @param {Date|undefined} propertyValue - Value to assign.
45140
- * @returns {void}
45141
- */
45142
- setDateObjectProperty(propertyName, propertyValue) {
45143
- const internalPropertyName = `_${propertyName}`;
45144
- const previousValue = this[internalPropertyName];
45145
-
45146
- if (previousValue === propertyValue) {
45147
- return;
45148
- }
45149
-
45150
- this[internalPropertyName] = propertyValue;
45151
- this.requestUpdate(propertyName, previousValue);
44996
+ return this.max && dateFormatter$2.isValidDate(this.max) ? dateFormatter$2.stringToDateInstance(this.max) : undefined;
45152
44997
  }
45153
44998
 
45154
44999
  connectedCallback() {
@@ -45177,7 +45022,6 @@ let BaseInput$1 = class BaseInput extends AuroElement$1$3 {
45177
45022
  format: this.format
45178
45023
  });
45179
45024
  this.configureDataForType();
45180
- this.syncDateValues();
45181
45025
  }
45182
45026
 
45183
45027
  disconnectedCallback() {
@@ -45197,10 +45041,6 @@ let BaseInput$1 = class BaseInput extends AuroElement$1$3 {
45197
45041
  this.wrapperElement.addEventListener('click', this.handleClick);
45198
45042
  }
45199
45043
 
45200
- // add attribute for query selectors when auro-input is registered under a custom name
45201
- if (this.tagName.toLowerCase() !== 'auro-input' && !this.hasAttribute('auro-input')) {
45202
- this.setAttribute('auro-input', '');
45203
- }
45204
45044
  this.inputId = this.id ? `${this.id}-input` : window.crypto.randomUUID();
45205
45045
 
45206
45046
  // use validity message override if declared when initializing the component
@@ -45211,7 +45051,6 @@ let BaseInput$1 = class BaseInput extends AuroElement$1$3 {
45211
45051
  this.setCustomHelpTextMessage();
45212
45052
  this.configureAutoFormatting();
45213
45053
  this.configureDataForType();
45214
- this.syncDateValues();
45215
45054
  }
45216
45055
 
45217
45056
  /**
@@ -45348,8 +45187,6 @@ let BaseInput$1 = class BaseInput extends AuroElement$1$3 {
45348
45187
  this.configureDataForType();
45349
45188
  }
45350
45189
 
45351
- this.syncDateValues(changedProperties);
45352
-
45353
45190
  if (changedProperties.has('value')) {
45354
45191
  if (this.value && this.value.length > 0) {
45355
45192
  this.hasValue = true;
@@ -45371,14 +45208,14 @@ let BaseInput$1 = class BaseInput extends AuroElement$1$3 {
45371
45208
 
45372
45209
  if (formattedValue !== this.inputElement.value) {
45373
45210
  this.skipNextProgrammaticInputEvent = true;
45374
- if (this.maskInstance && this.type === 'credit-card') {
45211
+ if (this.maskInstance && this.type !== 'date') {
45375
45212
  // Route through the mask so its _value and el.value stay in lock-step
45376
45213
  // (set value calls updateControl which writes el.value = displayValue).
45377
45214
  // Writing el.value directly leaves the mask thinking displayValue is
45378
- // stale; _saveSelection on the next focus/click then warns. Scoped to
45379
- // credit-card so date's own formattedValue (raw ISO when calendar-invalid)
45380
- // isn't re-masked through the mm/dd/yyyy mask, which would truncate it
45381
- // and flip validity from patternMismatch to tooShort.
45215
+ // stale; _saveSelection on the next focus/click then warns. Date is
45216
+ // excluded because its formattedValue can be raw ISO when the calendar
45217
+ // is invalid, and re-masking through mm/dd/yyyy would truncate it and
45218
+ // flip validity from patternMismatch to tooShort.
45382
45219
  this.maskInstance.value = formattedValue || '';
45383
45220
  } else if (formattedValue) {
45384
45221
  this.inputElement.value = formattedValue;
@@ -45420,120 +45257,60 @@ let BaseInput$1 = class BaseInput extends AuroElement$1$3 {
45420
45257
  }));
45421
45258
  }
45422
45259
 
45423
-
45424
- /**
45425
- * Synchronizes the ISO string values and Date object representations for date-related properties.
45426
- * This keeps the model and display values aligned when either side changes.
45427
- *
45428
- * When a full date format is in use, this method updates `value`, `min`, and `max` from their corresponding
45429
- * Date objects or vice versa, based on which properties have changed. It only runs when the current configuration
45430
- * represents a full year/month/day date format.
45431
- *
45432
- * @param {Map<string, unknown>|undefined} [changedProperties=undefined] - Optional map of changed properties used to limit which values are synchronized.
45433
- * @returns {void}
45434
- * @private
45435
- */
45436
- syncDateValues(changedProperties = undefined) {
45437
- if (!this.util.isFullDateFormat(this.type, this.format)) {
45438
- return;
45439
- }
45440
-
45441
- this.syncSingleDateValue(changedProperties, 'valueObject', 'value');
45442
- this.syncSingleDateValue(changedProperties, 'minObject', 'min');
45443
- this.syncSingleDateValue(changedProperties, 'maxObject', 'max');
45444
- }
45445
-
45446
- /**
45447
- * Synchronizes one date object/string property pair.
45448
- * @private
45449
- * @param {Map<string, unknown>|undefined} changedProperties - Map of changed properties from Lit.
45450
- * @param {string} objectProperty - Date object property name.
45451
- * @param {string} valueProperty - ISO string property name.
45452
- * @returns {void}
45453
- */
45454
- syncSingleDateValue(changedProperties, objectProperty, valueProperty) {
45455
- const objectPropertyChanged = !changedProperties || changedProperties.has(objectProperty);
45456
-
45457
- // objectProperty wins over valueProperty when both changed
45458
- if (objectPropertyChanged && this[objectProperty]) {
45459
- this[valueProperty] = dateFormatter$2.toISOFormatString(this[objectProperty]);
45460
- return;
45461
- }
45462
-
45463
- const valuePropertyChanged = !changedProperties || changedProperties.has(valueProperty);
45464
- if (!valuePropertyChanged) {
45465
- return;
45466
- }
45467
-
45468
- // when value is newly set to the same ISO string that corresponds to the existing Date object, do not clear the Date object (avoid unnecessary updates)
45469
- if (
45470
- changedProperties &&
45471
- valueProperty === 'value' &&
45472
- changedProperties.get('value') === undefined &&
45473
- this[objectProperty] instanceof Date &&
45474
- this[valueProperty] === dateFormatter$2.toISOFormatString(this[objectProperty])
45475
- ) {
45476
- return;
45477
- }
45478
-
45479
- if (dateFormatter$2.isValidDate(this[valueProperty])) {
45480
- this.setDateObjectProperty(objectProperty, dateFormatter$2.stringToDateInstance(this[valueProperty]));
45481
- } else {
45482
- this.setDateObjectProperty(objectProperty, undefined);
45483
- }
45484
- }
45485
-
45486
45260
  /**
45487
45261
  * Sets up IMasks and logic based on auto-formatting requirements.
45488
45262
  * @private
45489
45263
  * @returns {void}
45490
45264
  */
45491
45265
  configureAutoFormatting() {
45492
- // Re-entrancy guard. The patched-setter's synthetic input event (suppressed
45493
- // by _configuringMask above) could otherwise trigger handleInput
45494
- // processCreditCard configureAutoFormatting before the outer call's
45495
- // set value has finished its alignCursor pass.
45266
+ // _configuringMask gates two things: external re-entry into this method
45267
+ // while setup is mid-flight (from property changes that call back here),
45268
+ // and the accept/complete listeners below — both need to ignore the mask
45269
+ // events fired by our own value-restore step.
45496
45270
  if (this._configuringMask) return;
45497
45271
  this._configuringMask = true;
45498
45272
  try {
45273
+ // Destroy any prior mask so IMask can attach fresh under the new format.
45499
45274
  if (this.maskInstance) {
45500
45275
  this.maskInstance.destroy();
45501
45276
  }
45502
45277
 
45503
- // Pass new format to util
45504
45278
  this.util.updateFormat(this.format);
45505
45279
 
45506
45280
  const maskOptions = this.util.getMaskOptions(this.type, this.format);
45507
45281
 
45508
45282
  if (this.inputElement && maskOptions.mask) {
45509
-
45510
- // Stash and clear any existing value before IMask init.
45511
- // IMask's constructor processes the current input value which requires
45512
- // selection state clearing first avoids that scenario entirely.
45513
- // When the format changes (e.g. locale switch) and we have a valid ISO
45514
- // model value, compute the display string for the NEW format instead of
45515
- // re-using the old display string, which may be invalid in the new mask.
45283
+ // Capture the current display so it can be re-applied after IMask
45284
+ // attaches. The restore at the bottom goes through maskInstance.value
45285
+ // (not inputElement.value directly) so the mask's internal state and
45286
+ // the input's displayed text stay in lock-step.
45516
45287
  let existingValue = this.inputElement.value;
45288
+
45289
+ // Format-change case (e.g. locale switch): existingValue is the OLD
45290
+ // mask's display string and may not parse under the new mask. When
45291
+ // we have a valid date model, rebuild the display from valueObject
45292
+ // (the canonical source) using the new mask's format function.
45517
45293
  if (
45518
45294
  this.util.isFullDateFormat(this.type, this.format) &&
45519
45295
  this.value &&
45520
- dateFormatter$2.isValidDate(this.value) &&
45521
- this.valueObject instanceof Date &&
45522
- !Number.isNaN(this.valueObject.getTime()) &&
45296
+ this.valueObject &&
45523
45297
  typeof maskOptions.format === 'function'
45524
45298
  ) {
45525
45299
  existingValue = maskOptions.format(this.valueObject);
45526
45300
  }
45527
45301
 
45302
+ // Clear before IMask attaches so the constructor seeds an empty
45303
+ // internal value. Otherwise IMask reads the stale unmasked string
45304
+ // and emits a spurious 'accept' before the restore below runs.
45528
45305
  this.skipNextProgrammaticInputEvent = true;
45529
45306
  this.inputElement.value = '';
45530
45307
 
45531
45308
  this.maskInstance = IMask$2(this.inputElement, maskOptions);
45532
45309
 
45310
+ // Mask fires 'accept' on every value change, including the restore
45311
+ // step below. Skip events fired during configureAutoFormatting so
45312
+ // we don't overwrite a value the parent just pushed.
45533
45313
  this.maskInstance.on('accept', () => {
45534
- // Suppress propagation during configureAutoFormatting's own value-restoration
45535
- // (line below) — the mask emits 'accept' on every value-set, including ours,
45536
- // and we don't want to overwrite a value the parent just pushed.
45537
45314
  if (this._configuringMask) return;
45538
45315
  this.value = this.util.toModelValue(this.maskInstance.value, this.format);
45539
45316
  if (this.type === "date") {
@@ -45541,6 +45318,8 @@ let BaseInput$1 = class BaseInput extends AuroElement$1$3 {
45541
45318
  }
45542
45319
  });
45543
45320
 
45321
+ // Mask fires 'complete' on the restore step below for any value that
45322
+ // happens to be a complete match. Same setup-suppression as 'accept'.
45544
45323
  this.maskInstance.on('complete', () => {
45545
45324
  if (this._configuringMask) return;
45546
45325
  this.value = this.util.toModelValue(this.maskInstance.value, this.format);
@@ -45549,7 +45328,9 @@ let BaseInput$1 = class BaseInput extends AuroElement$1$3 {
45549
45328
  }
45550
45329
  });
45551
45330
 
45552
- // Restore the stashed value through IMask so it's properly masked
45331
+ // Write existingValue through the mask (not the input directly) so
45332
+ // the mask reformats it under the new rules and keeps its internal
45333
+ // _value aligned with the input's displayed text.
45553
45334
  if (existingValue) {
45554
45335
  this.maskInstance.value = existingValue;
45555
45336
  }
@@ -45717,7 +45498,6 @@ let BaseInput$1 = class BaseInput extends AuroElement$1$3 {
45717
45498
  */
45718
45499
  reset() {
45719
45500
  this.value = undefined;
45720
- this.setDateObjectProperty('valueObject', undefined);
45721
45501
  this.validation.reset(this);
45722
45502
  }
45723
45503
 
@@ -45726,7 +45506,6 @@ let BaseInput$1 = class BaseInput extends AuroElement$1$3 {
45726
45506
  */
45727
45507
  clear() {
45728
45508
  this.value = undefined;
45729
- this.setDateObjectProperty('valueObject', undefined);
45730
45509
  }
45731
45510
 
45732
45511
  /**
@@ -46255,7 +46034,7 @@ let AuroHelpText$1$3 = class AuroHelpText extends i$3 {
46255
46034
  }
46256
46035
  };
46257
46036
 
46258
- var formkitVersion$7 = '202606171946';
46037
+ var formkitVersion$7 = '202606192004';
46259
46038
 
46260
46039
  // Copyright (c) 2025 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
46261
46040
  // See LICENSE in the project root for license information.
@@ -47675,8 +47454,6 @@ const datepickerKeyboardStrategy = {
47675
47454
  * @slot label - Defines the label content for the entire datepicker when `layout="snowflake"`.
47676
47455
  * @slot toLabel - Defines the label content for the second input when the `range` attribute is used.
47677
47456
  * @slot fromLabel - Defines the label content for the first input.
47678
- * @slot optionalFromLabel - Overrides the "(optional)" text rendered next to the first input's label when the datepicker is not `required`.
47679
- * @slot optionalToLabel - Overrides the "(optional)" text rendered next to the second input's label when `range` is set and the datepicker is not `required`.
47680
47457
  * @slot date_YYYY_MM_DD - Defines the content to display in the auro-calendar-cell for the specified date. The content text is colored using the success state token when the `highlight` attribute is applied to the slot.
47681
47458
  * @slot popover_YYYY_MM_DD - Defines the content to display in the auro-calendar-cell popover for the specified date.
47682
47459
  * @csspart dropdown - Use for customizing the style of the dropdown.
@@ -49272,9 +49049,7 @@ class AuroDatePicker extends AuroElement$5 {
49272
49049
  // update the calendar
49273
49050
  if (this.valueEndObject) {
49274
49051
  this.calendar.dateTo = this.convertToWcValidTime(this.valueEndObject);
49275
- if (!(this.wasCellClick && this.range)) {
49276
- this.calendarRenderUtil.updateCentralDate(this, this.valueEndObject);
49277
- }
49052
+ this.calendarRenderUtil.updateCentralDate(this, this.valueEndObject);
49278
49053
  } else {
49279
49054
  if (this.inputList[1].value !== this.valueEnd) {
49280
49055
  this.inputList[1].value = this.valueEnd || '';
@@ -49669,7 +49444,6 @@ class AuroDatePicker extends AuroElement$5 {
49669
49444
  }
49670
49445
  <span slot="ariaLabel.clear">${this.runtimeUtils.getSlotText(this, 'ariaLabel.input.clear') || i18n$2(this.lang, 'clearInput')}</span>
49671
49446
  <span slot="label"><slot name="fromLabel"></slot></span>
49672
- <span slot="optionalLabel"><slot name="optionalFromLabel"> (optional)</slot></span>
49673
49447
  </${this.inputTag}>
49674
49448
  </div>
49675
49449
 
@@ -49714,7 +49488,6 @@ class AuroDatePicker extends AuroElement$5 {
49714
49488
  }
49715
49489
  <span slot="ariaLabel.clear">${this.runtimeUtils.getSlotText(this, 'ariaLabel.input.clear') || this.runtimeUtils.getSlotText(this, 'ariaLabel.input.clear') || i18n$2(this.lang, 'clearInput')}</span>
49716
49490
  <span slot="label"><slot name="toLabel"></slot></span>
49717
- <span slot="optionalLabel"><slot name="optionalToLabel"> (optional)</slot></span>
49718
49491
  </${this.inputTag}>
49719
49492
  </div>
49720
49493
  ` : undefined}
@@ -50958,7 +50731,7 @@ let AuroHelpText$1$2 = class AuroHelpText extends i$3 {
50958
50731
  }
50959
50732
  };
50960
50733
 
50961
- var formkitVersion$1$2 = '202606171946';
50734
+ var formkitVersion$1$2 = '202606192004';
50962
50735
 
50963
50736
  // Copyright (c) 2026 Alaska Airlines. All rights reserved. Licensed under the Apache-2.0 license
50964
50737
  // See LICENSE in the project root for license information.
@@ -55286,7 +55059,7 @@ let AuroHelpText$6 = class AuroHelpText extends i$3 {
55286
55059
  }
55287
55060
  };
55288
55061
 
55289
- var formkitVersion$6 = '202606171946';
55062
+ var formkitVersion$6 = '202606192004';
55290
55063
 
55291
55064
  let AuroElement$1$2 = class AuroElement extends i$3 {
55292
55065
  static get properties() {
@@ -59218,7 +58991,7 @@ let AuroHelpText$5 = class AuroHelpText extends i$3 {
59218
58991
  }
59219
58992
  };
59220
58993
 
59221
- var formkitVersion$5 = '202606171946';
58994
+ var formkitVersion$5 = '202606192004';
59222
58995
 
59223
58996
  // Copyright (c) Alaska Air. All right reserved. Licensed under the Apache-2.0 license
59224
58997
  // See LICENSE in the project root for license information.
@@ -60968,7 +60741,7 @@ let AuroHelpText$4 = class AuroHelpText extends i$3 {
60968
60741
  }
60969
60742
  };
60970
60743
 
60971
- var formkitVersion$4 = '202606171946';
60744
+ var formkitVersion$4 = '202606192004';
60972
60745
 
60973
60746
  // Copyright (c) 2026 Alaska Airlines. All rights reserved. Licensed under the Apache-2.0 license
60974
60747
  // See LICENSE in the project root for license information.
@@ -62144,6 +61917,8 @@ function navigateArrow$1(component, direction, options = {}) {
62144
61917
  }
62145
61918
  }
62146
61919
 
61920
+ /* eslint-disable no-underscore-dangle */
61921
+
62147
61922
  /**
62148
61923
  * Returns the clear button element from the active input's shadow
62149
61924
  * DOM, if available.
@@ -62179,11 +61954,9 @@ function isClearBtnFocused(ctx, clearBtn = getClearBtn(ctx)) {
62179
61954
  * @param {Object} menu - The menu component.
62180
61955
  */
62181
61956
  function reconcileMenuIndex(menu) {
62182
- // eslint-disable-next-line no-underscore-dangle
62183
61957
  if (menu._index < 0 && menu.optionActive && menu.items) {
62184
61958
  const idx = menu.items.indexOf(menu.optionActive);
62185
61959
  if (idx >= 0) {
62186
- // eslint-disable-next-line no-underscore-dangle
62187
61960
  menu._index = idx;
62188
61961
  }
62189
61962
  }
@@ -66183,7 +65956,7 @@ let AuroHelpText$2 = class AuroHelpText extends i$3 {
66183
65956
  }
66184
65957
  };
66185
65958
 
66186
- var formkitVersion$2 = '202606171946';
65959
+ var formkitVersion$2 = '202606192004';
66187
65960
 
66188
65961
  let AuroElement$2$1 = class AuroElement extends i$3 {
66189
65962
  static get properties() {
@@ -77897,6 +77670,7 @@ class AuroInputUtilities {
77897
77670
  const maskOptions = this.getMaskOptions('date', normalizedFormat);
77898
77671
 
77899
77672
  if (!(valueObject instanceof Date) || Number.isNaN(valueObject.getTime()) || !maskOptions || typeof maskOptions.format !== 'function') {
77673
+ console.debug('Invalid date object or mask options for formatting', { valueObject, maskOptions }); // eslint-disable-line no-console
77900
77674
  return undefined;
77901
77675
  }
77902
77676
 
@@ -78048,10 +77822,8 @@ class BaseInput extends AuroElement$1$1 {
78048
77822
  this.layout = 'classic';
78049
77823
  this.locale = 'en-US';
78050
77824
  this.max = undefined;
78051
- this._maxObject = undefined;
78052
77825
  this.maxLength = undefined;
78053
77826
  this.min = undefined;
78054
- this._minObject = undefined;
78055
77827
  this.minLength = undefined;
78056
77828
  this.required = false;
78057
77829
  this.onDark = false;
@@ -78059,7 +77831,6 @@ class BaseInput extends AuroElement$1$1 {
78059
77831
  this.size = 'lg';
78060
77832
  this.shape = 'classic';
78061
77833
  this.value = undefined;
78062
- this._valueObject = undefined;
78063
77834
 
78064
77835
  this._initializePrivateDefaults();
78065
77836
  }
@@ -78599,7 +78370,7 @@ class BaseInput extends AuroElement$1$1 {
78599
78370
  * @returns {Date|undefined}
78600
78371
  */
78601
78372
  get valueObject() {
78602
- return this._valueObject || this._computeDateObjectFallback(this.value);
78373
+ return this.value && dateFormatter.isValidDate(this.value) ? dateFormatter.stringToDateInstance(this.value) : undefined;
78603
78374
  }
78604
78375
 
78605
78376
  /**
@@ -78607,7 +78378,7 @@ class BaseInput extends AuroElement$1$1 {
78607
78378
  * @returns {Date|undefined}
78608
78379
  */
78609
78380
  get minObject() {
78610
- return this._minObject || this._computeDateObjectFallback(this.min);
78381
+ return this.min && dateFormatter.isValidDate(this.min) ? dateFormatter.stringToDateInstance(this.min) : undefined;
78611
78382
  }
78612
78383
 
78613
78384
  /**
@@ -78615,50 +78386,7 @@ class BaseInput extends AuroElement$1$1 {
78615
78386
  * @returns {Date|undefined}
78616
78387
  */
78617
78388
  get maxObject() {
78618
- return this._maxObject || this._computeDateObjectFallback(this.max);
78619
- }
78620
-
78621
- /**
78622
- * Parses a date string into a Date object when the corresponding `_*Object`
78623
- * field hasn't been synced yet by `updated()`. Returns undefined when the
78624
- * input type/format isn't a full date or the string is not a valid date.
78625
- *
78626
- * Why this exists: a parent (datepicker) can call `inputN.validate()` from
78627
- * inside its own `updated()` before this input's `updated()` has run
78628
- * `syncDateValues()` — so `_valueObject`/`_maxObject` are still `undefined`
78629
- * and range checks would otherwise silently no-op (flipping the result to
78630
- * `valid` or `patternMismatch`).
78631
- * @private
78632
- * @param {string|undefined} dateStr - ISO date string from `value`/`min`/`max`.
78633
- * @returns {Date|undefined}
78634
- */
78635
- _computeDateObjectFallback(dateStr) {
78636
- if (!dateStr || !this.util || !this.util.isFullDateFormat(this.type, this.format)) {
78637
- return undefined;
78638
- }
78639
- if (!dateFormatter.isValidDate(dateStr)) {
78640
- return undefined;
78641
- }
78642
- return dateFormatter.stringToDateInstance(dateStr);
78643
- }
78644
-
78645
- /**
78646
- * Internal setter for readonly date object properties.
78647
- * @private
78648
- * @param {'valueObject'|'minObject'|'maxObject'} propertyName - Public object property name.
78649
- * @param {Date|undefined} propertyValue - Value to assign.
78650
- * @returns {void}
78651
- */
78652
- setDateObjectProperty(propertyName, propertyValue) {
78653
- const internalPropertyName = `_${propertyName}`;
78654
- const previousValue = this[internalPropertyName];
78655
-
78656
- if (previousValue === propertyValue) {
78657
- return;
78658
- }
78659
-
78660
- this[internalPropertyName] = propertyValue;
78661
- this.requestUpdate(propertyName, previousValue);
78389
+ return this.max && dateFormatter.isValidDate(this.max) ? dateFormatter.stringToDateInstance(this.max) : undefined;
78662
78390
  }
78663
78391
 
78664
78392
  connectedCallback() {
@@ -78687,7 +78415,6 @@ class BaseInput extends AuroElement$1$1 {
78687
78415
  format: this.format
78688
78416
  });
78689
78417
  this.configureDataForType();
78690
- this.syncDateValues();
78691
78418
  }
78692
78419
 
78693
78420
  disconnectedCallback() {
@@ -78707,10 +78434,6 @@ class BaseInput extends AuroElement$1$1 {
78707
78434
  this.wrapperElement.addEventListener('click', this.handleClick);
78708
78435
  }
78709
78436
 
78710
- // add attribute for query selectors when auro-input is registered under a custom name
78711
- if (this.tagName.toLowerCase() !== 'auro-input' && !this.hasAttribute('auro-input')) {
78712
- this.setAttribute('auro-input', '');
78713
- }
78714
78437
  this.inputId = this.id ? `${this.id}-input` : window.crypto.randomUUID();
78715
78438
 
78716
78439
  // use validity message override if declared when initializing the component
@@ -78721,7 +78444,6 @@ class BaseInput extends AuroElement$1$1 {
78721
78444
  this.setCustomHelpTextMessage();
78722
78445
  this.configureAutoFormatting();
78723
78446
  this.configureDataForType();
78724
- this.syncDateValues();
78725
78447
  }
78726
78448
 
78727
78449
  /**
@@ -78858,8 +78580,6 @@ class BaseInput extends AuroElement$1$1 {
78858
78580
  this.configureDataForType();
78859
78581
  }
78860
78582
 
78861
- this.syncDateValues(changedProperties);
78862
-
78863
78583
  if (changedProperties.has('value')) {
78864
78584
  if (this.value && this.value.length > 0) {
78865
78585
  this.hasValue = true;
@@ -78881,14 +78601,14 @@ class BaseInput extends AuroElement$1$1 {
78881
78601
 
78882
78602
  if (formattedValue !== this.inputElement.value) {
78883
78603
  this.skipNextProgrammaticInputEvent = true;
78884
- if (this.maskInstance && this.type === 'credit-card') {
78604
+ if (this.maskInstance && this.type !== 'date') {
78885
78605
  // Route through the mask so its _value and el.value stay in lock-step
78886
78606
  // (set value calls updateControl which writes el.value = displayValue).
78887
78607
  // Writing el.value directly leaves the mask thinking displayValue is
78888
- // stale; _saveSelection on the next focus/click then warns. Scoped to
78889
- // credit-card so date's own formattedValue (raw ISO when calendar-invalid)
78890
- // isn't re-masked through the mm/dd/yyyy mask, which would truncate it
78891
- // and flip validity from patternMismatch to tooShort.
78608
+ // stale; _saveSelection on the next focus/click then warns. Date is
78609
+ // excluded because its formattedValue can be raw ISO when the calendar
78610
+ // is invalid, and re-masking through mm/dd/yyyy would truncate it and
78611
+ // flip validity from patternMismatch to tooShort.
78892
78612
  this.maskInstance.value = formattedValue || '';
78893
78613
  } else if (formattedValue) {
78894
78614
  this.inputElement.value = formattedValue;
@@ -78930,120 +78650,60 @@ class BaseInput extends AuroElement$1$1 {
78930
78650
  }));
78931
78651
  }
78932
78652
 
78933
-
78934
- /**
78935
- * Synchronizes the ISO string values and Date object representations for date-related properties.
78936
- * This keeps the model and display values aligned when either side changes.
78937
- *
78938
- * When a full date format is in use, this method updates `value`, `min`, and `max` from their corresponding
78939
- * Date objects or vice versa, based on which properties have changed. It only runs when the current configuration
78940
- * represents a full year/month/day date format.
78941
- *
78942
- * @param {Map<string, unknown>|undefined} [changedProperties=undefined] - Optional map of changed properties used to limit which values are synchronized.
78943
- * @returns {void}
78944
- * @private
78945
- */
78946
- syncDateValues(changedProperties = undefined) {
78947
- if (!this.util.isFullDateFormat(this.type, this.format)) {
78948
- return;
78949
- }
78950
-
78951
- this.syncSingleDateValue(changedProperties, 'valueObject', 'value');
78952
- this.syncSingleDateValue(changedProperties, 'minObject', 'min');
78953
- this.syncSingleDateValue(changedProperties, 'maxObject', 'max');
78954
- }
78955
-
78956
- /**
78957
- * Synchronizes one date object/string property pair.
78958
- * @private
78959
- * @param {Map<string, unknown>|undefined} changedProperties - Map of changed properties from Lit.
78960
- * @param {string} objectProperty - Date object property name.
78961
- * @param {string} valueProperty - ISO string property name.
78962
- * @returns {void}
78963
- */
78964
- syncSingleDateValue(changedProperties, objectProperty, valueProperty) {
78965
- const objectPropertyChanged = !changedProperties || changedProperties.has(objectProperty);
78966
-
78967
- // objectProperty wins over valueProperty when both changed
78968
- if (objectPropertyChanged && this[objectProperty]) {
78969
- this[valueProperty] = dateFormatter.toISOFormatString(this[objectProperty]);
78970
- return;
78971
- }
78972
-
78973
- const valuePropertyChanged = !changedProperties || changedProperties.has(valueProperty);
78974
- if (!valuePropertyChanged) {
78975
- return;
78976
- }
78977
-
78978
- // when value is newly set to the same ISO string that corresponds to the existing Date object, do not clear the Date object (avoid unnecessary updates)
78979
- if (
78980
- changedProperties &&
78981
- valueProperty === 'value' &&
78982
- changedProperties.get('value') === undefined &&
78983
- this[objectProperty] instanceof Date &&
78984
- this[valueProperty] === dateFormatter.toISOFormatString(this[objectProperty])
78985
- ) {
78986
- return;
78987
- }
78988
-
78989
- if (dateFormatter.isValidDate(this[valueProperty])) {
78990
- this.setDateObjectProperty(objectProperty, dateFormatter.stringToDateInstance(this[valueProperty]));
78991
- } else {
78992
- this.setDateObjectProperty(objectProperty, undefined);
78993
- }
78994
- }
78995
-
78996
78653
  /**
78997
78654
  * Sets up IMasks and logic based on auto-formatting requirements.
78998
78655
  * @private
78999
78656
  * @returns {void}
79000
78657
  */
79001
78658
  configureAutoFormatting() {
79002
- // Re-entrancy guard. The patched-setter's synthetic input event (suppressed
79003
- // by _configuringMask above) could otherwise trigger handleInput
79004
- // processCreditCard configureAutoFormatting before the outer call's
79005
- // set value has finished its alignCursor pass.
78659
+ // _configuringMask gates two things: external re-entry into this method
78660
+ // while setup is mid-flight (from property changes that call back here),
78661
+ // and the accept/complete listeners below — both need to ignore the mask
78662
+ // events fired by our own value-restore step.
79006
78663
  if (this._configuringMask) return;
79007
78664
  this._configuringMask = true;
79008
78665
  try {
78666
+ // Destroy any prior mask so IMask can attach fresh under the new format.
79009
78667
  if (this.maskInstance) {
79010
78668
  this.maskInstance.destroy();
79011
78669
  }
79012
78670
 
79013
- // Pass new format to util
79014
78671
  this.util.updateFormat(this.format);
79015
78672
 
79016
78673
  const maskOptions = this.util.getMaskOptions(this.type, this.format);
79017
78674
 
79018
78675
  if (this.inputElement && maskOptions.mask) {
79019
-
79020
- // Stash and clear any existing value before IMask init.
79021
- // IMask's constructor processes the current input value which requires
79022
- // selection state clearing first avoids that scenario entirely.
79023
- // When the format changes (e.g. locale switch) and we have a valid ISO
79024
- // model value, compute the display string for the NEW format instead of
79025
- // re-using the old display string, which may be invalid in the new mask.
78676
+ // Capture the current display so it can be re-applied after IMask
78677
+ // attaches. The restore at the bottom goes through maskInstance.value
78678
+ // (not inputElement.value directly) so the mask's internal state and
78679
+ // the input's displayed text stay in lock-step.
79026
78680
  let existingValue = this.inputElement.value;
78681
+
78682
+ // Format-change case (e.g. locale switch): existingValue is the OLD
78683
+ // mask's display string and may not parse under the new mask. When
78684
+ // we have a valid date model, rebuild the display from valueObject
78685
+ // (the canonical source) using the new mask's format function.
79027
78686
  if (
79028
78687
  this.util.isFullDateFormat(this.type, this.format) &&
79029
78688
  this.value &&
79030
- dateFormatter.isValidDate(this.value) &&
79031
- this.valueObject instanceof Date &&
79032
- !Number.isNaN(this.valueObject.getTime()) &&
78689
+ this.valueObject &&
79033
78690
  typeof maskOptions.format === 'function'
79034
78691
  ) {
79035
78692
  existingValue = maskOptions.format(this.valueObject);
79036
78693
  }
79037
78694
 
78695
+ // Clear before IMask attaches so the constructor seeds an empty
78696
+ // internal value. Otherwise IMask reads the stale unmasked string
78697
+ // and emits a spurious 'accept' before the restore below runs.
79038
78698
  this.skipNextProgrammaticInputEvent = true;
79039
78699
  this.inputElement.value = '';
79040
78700
 
79041
78701
  this.maskInstance = IMask(this.inputElement, maskOptions);
79042
78702
 
78703
+ // Mask fires 'accept' on every value change, including the restore
78704
+ // step below. Skip events fired during configureAutoFormatting so
78705
+ // we don't overwrite a value the parent just pushed.
79043
78706
  this.maskInstance.on('accept', () => {
79044
- // Suppress propagation during configureAutoFormatting's own value-restoration
79045
- // (line below) — the mask emits 'accept' on every value-set, including ours,
79046
- // and we don't want to overwrite a value the parent just pushed.
79047
78707
  if (this._configuringMask) return;
79048
78708
  this.value = this.util.toModelValue(this.maskInstance.value, this.format);
79049
78709
  if (this.type === "date") {
@@ -79051,6 +78711,8 @@ class BaseInput extends AuroElement$1$1 {
79051
78711
  }
79052
78712
  });
79053
78713
 
78714
+ // Mask fires 'complete' on the restore step below for any value that
78715
+ // happens to be a complete match. Same setup-suppression as 'accept'.
79054
78716
  this.maskInstance.on('complete', () => {
79055
78717
  if (this._configuringMask) return;
79056
78718
  this.value = this.util.toModelValue(this.maskInstance.value, this.format);
@@ -79059,7 +78721,9 @@ class BaseInput extends AuroElement$1$1 {
79059
78721
  }
79060
78722
  });
79061
78723
 
79062
- // Restore the stashed value through IMask so it's properly masked
78724
+ // Write existingValue through the mask (not the input directly) so
78725
+ // the mask reformats it under the new rules and keeps its internal
78726
+ // _value aligned with the input's displayed text.
79063
78727
  if (existingValue) {
79064
78728
  this.maskInstance.value = existingValue;
79065
78729
  }
@@ -79227,7 +78891,6 @@ class BaseInput extends AuroElement$1$1 {
79227
78891
  */
79228
78892
  reset() {
79229
78893
  this.value = undefined;
79230
- this.setDateObjectProperty('valueObject', undefined);
79231
78894
  this.validation.reset(this);
79232
78895
  }
79233
78896
 
@@ -79236,7 +78899,6 @@ class BaseInput extends AuroElement$1$1 {
79236
78899
  */
79237
78900
  clear() {
79238
78901
  this.value = undefined;
79239
- this.setDateObjectProperty('valueObject', undefined);
79240
78902
  }
79241
78903
 
79242
78904
  /**
@@ -79765,7 +79427,7 @@ let AuroHelpText$1$1 = class AuroHelpText extends i$3 {
79765
79427
  }
79766
79428
  };
79767
79429
 
79768
- var formkitVersion$1$1 = '202606171946';
79430
+ var formkitVersion$1$1 = '202606192004';
79769
79431
 
79770
79432
  // Copyright (c) 2025 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
79771
79433
  // See LICENSE in the project root for license information.
@@ -80886,7 +80548,7 @@ let AuroBibtemplate$1 = class AuroBibtemplate extends i$3 {
80886
80548
  }
80887
80549
  };
80888
80550
 
80889
- var formkitVersion$3 = '202606171946';
80551
+ var formkitVersion$3 = '202606192004';
80890
80552
 
80891
80553
  var styleCss$1$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}`;
80892
80554
 
@@ -81873,7 +81535,7 @@ class AuroCombobox extends AuroElement$3 {
81873
81535
  if (this.menu) {
81874
81536
  this.menu.matchWord = normalizeFilterValue(this.input.value);
81875
81537
  }
81876
- const label = getOptionLabel(this.menu.optionSelected) || this.menu.currentLabel;
81538
+ const label = getOptionLabel(this.menu.optionSelected);
81877
81539
  this.updateTriggerTextDisplay(label || this.value);
81878
81540
  }
81879
81541
 
@@ -81887,40 +81549,9 @@ class AuroCombobox extends AuroElement$3 {
81887
81549
  // in suggestion mode, do not override input value if no selection has been made and the input currently has focus
81888
81550
  const isInputFocusedWithNoSelection = !this.menu.value && (this.input.matches(':focus-within') || (this.inputInBib && this.inputInBib.matches(':focus-within')));
81889
81551
 
81890
- if (!this.persistInput && !(this.behavior === 'suggestion' && isInputFocusedWithNoSelection)) {
81891
- const nextValue = label || this.value;
81892
- // Only set the flag when there's an actual write to suppress —
81893
- // syncValuesAndStates re-enters here during typing when both inputs
81894
- // already match, and a no-op flag flip would make the bib branch's
81895
- // bail eat legitimate user-input events.
81896
- const triggerNeedsSync = this.input.value !== nextValue;
81897
- const bibNeedsSync = Boolean(this.inputInBib && this.inputInBib !== this.input && this.inputInBib.value !== nextValue);
81898
- if (triggerNeedsSync || bibNeedsSync) {
81899
- this._syncingDisplayValue = true;
81900
- if (triggerNeedsSync) {
81901
- this.input.value = nextValue;
81902
- }
81903
- if (bibNeedsSync) {
81904
- this.inputInBib.value = nextValue;
81905
- }
81906
- const pending = [];
81907
- if (triggerNeedsSync) {
81908
- pending.push(this.input.updateComplete);
81909
- }
81910
- if (bibNeedsSync) {
81911
- pending.push(this.inputInBib.updateComplete);
81912
- }
81913
- Promise.all(pending).then(() => {
81914
- // imask reasserts otherwise, and handleBlur reverts to its stale value.
81915
- if (triggerNeedsSync && this.input.maskInstance && typeof this.input.maskInstance.updateValue === 'function') {
81916
- this.input.maskInstance.updateValue();
81917
- }
81918
- if (bibNeedsSync && this.inputInBib && this.inputInBib.maskInstance && typeof this.inputInBib.maskInstance.updateValue === 'function') {
81919
- this.inputInBib.maskInstance.updateValue();
81920
- }
81921
- this._syncingDisplayValue = false;
81922
- });
81923
- }
81552
+ const suppressed = this.persistInput || (this.behavior === 'suggestion' && isInputFocusedWithNoSelection);
81553
+ if (!suppressed) {
81554
+ this.syncInputValuesAcrossTriggerAndBib(label || this.value);
81924
81555
  }
81925
81556
 
81926
81557
  // update the displayValue in the trigger if displayValue slot content is present
@@ -81948,6 +81579,52 @@ class AuroCombobox extends AuroElement$3 {
81948
81579
  this.requestUpdate();
81949
81580
  }
81950
81581
 
81582
+ /**
81583
+ * Writes nextValue to the trigger input and the bib input when their current
81584
+ * value differs, then re-asserts imask after Lit's update flushes.
81585
+ * @param {string} nextValue - The value to write to both inputs.
81586
+ * @returns {Promise<void> | null} Promise that resolves after the inputs flush,
81587
+ * or null when no sync was needed (so callers can skip post-flush work).
81588
+ * @private
81589
+ */
81590
+ syncInputValuesAcrossTriggerAndBib(nextValue) {
81591
+ // Only set the flag when there's an actual write to suppress —
81592
+ // syncValuesAndStates re-enters here during typing when both inputs
81593
+ // already match, and a no-op flag flip would make the bib branch's
81594
+ // bail eat legitimate user-input events.
81595
+ const triggerNeedsSync = this.input.value !== nextValue;
81596
+ const bibNeedsSync = Boolean(this.inputInBib && this.inputInBib !== this.input && this.inputInBib.value !== nextValue);
81597
+ if (!triggerNeedsSync && !bibNeedsSync) {
81598
+ return null;
81599
+ }
81600
+
81601
+ this._syncingDisplayValue = true;
81602
+ if (triggerNeedsSync) {
81603
+ this.input.value = nextValue;
81604
+ }
81605
+ if (bibNeedsSync) {
81606
+ this.inputInBib.value = nextValue;
81607
+ }
81608
+
81609
+ const pending = [];
81610
+ if (triggerNeedsSync) {
81611
+ pending.push(this.input.updateComplete);
81612
+ }
81613
+ if (bibNeedsSync) {
81614
+ pending.push(this.inputInBib.updateComplete);
81615
+ }
81616
+ return Promise.all(pending).then(() => {
81617
+ // imask reasserts otherwise, and handleBlur reverts to its stale value.
81618
+ if (triggerNeedsSync && this.input.maskInstance && typeof this.input.maskInstance.updateValue === 'function') {
81619
+ this.input.maskInstance.updateValue();
81620
+ }
81621
+ if (bibNeedsSync && this.inputInBib && this.inputInBib.maskInstance && typeof this.inputInBib.maskInstance.updateValue === 'function') {
81622
+ this.inputInBib.maskInstance.updateValue();
81623
+ }
81624
+ this._syncingDisplayValue = false;
81625
+ });
81626
+ }
81627
+
81951
81628
  /**
81952
81629
  * Processes hidden state of all menu options and determines if there are any available options not hidden.
81953
81630
  * @private
@@ -81975,9 +81652,9 @@ class AuroCombobox extends AuroElement$3 {
81975
81652
  this.syncValuesAndStates();
81976
81653
  }
81977
81654
 
81978
- // Re-activate when optionActive is no longer visible, or when _index has
81979
- // been reset (e.g. by clearSelection in an async update) so that
81980
- // makeSelection() can find the correct option.
81655
+ // Re-activate when optionActive is not in the current scrollable viewport,
81656
+ // or when _index has been reset (e.g. by clearSelection in an async update)
81657
+ // so that makeSelection() can find the correct option.
81981
81658
  if (!this.availableOptions.includes(this.menu.optionActive) || this.menu._index < 0) {
81982
81659
  this.activateFirstEnabledAvailableOption();
81983
81660
  }
@@ -82111,28 +81788,25 @@ class AuroCombobox extends AuroElement$3 {
82111
81788
 
82112
81789
  guardTouchPassthrough$1(this.menu);
82113
81790
 
82114
- // The dialog's showModal() steals focus from the trigger.
82115
- // A single rAF is enough for the dialog DOM to be painted and
82116
- // focusable, then doubleRaf finalizes the transition.
81791
+ // showModal() takes focus away from the trigger. Early focus once
81792
+ // the dialog has painted; the shared doubleRaf below is the fallback
81793
+ // for when the dialog needs an extra frame and also clears the
81794
+ // validation guard.
82117
81795
  requestAnimationFrame(() => {
82118
81796
  this.setInputFocus();
82119
81797
  });
82120
-
82121
- doubleRaf$1(() => {
82122
- this.setInputFocus();
82123
- this._inFullscreenTransition = false;
82124
- });
82125
- } else {
82126
- // Desktop popover-open: restore the trigger caret to end-of-text.
82127
- // Clicking the trigger lands on auro-input's floating <label for="…">
82128
- // overlay; Chrome resets the native input's selection to [0, 0] on
82129
- // label-focus before any JS runs. setInputFocus()'s non-fullscreen
82130
- // branch parks the caret at end. doubleRaf lets the dropdown layout
82131
- // settle first, matching the fullscreen branch timing.
82132
- doubleRaf$1(() => {
82133
- this.setInputFocus();
82134
- });
82135
81798
  }
81799
+ // else (desktop popover-open): Chrome resets the trigger caret to
81800
+ // [0, 0] when its floating <label for="…"> overlay receives focus.
81801
+ // The shared doubleRaf below parks the caret back at end-of-text
81802
+ // after the dropdown layout settles.
81803
+
81804
+ doubleRaf$1(() => {
81805
+ this.setInputFocus();
81806
+ if (this._inFullscreenTransition) {
81807
+ this._inFullscreenTransition = false;
81808
+ }
81809
+ });
82136
81810
  }
82137
81811
  });
82138
81812
 
@@ -82239,9 +81913,9 @@ class AuroCombobox extends AuroElement$3 {
82239
81913
  } else {
82240
81914
  // Safety net for the strategy-change setTimeout: a viewport-crossing
82241
81915
  // fullscreen→floating switch can close the dialog and leave focus on
82242
- // body. Every other Branch 2 callsite already has focus on the input
82243
- // via the focusin → this.focus() redirect (L1448-1452), so this is a
82244
- // no-op in the common case.
81916
+ // body. Every other call into this branch already has focus on the
81917
+ // input via the combobox-level focusin → this.focus() redirect, so
81918
+ // this is a no-op in the common case.
82245
81919
  if (!this.input.componentHasFocus) {
82246
81920
  this.input.focus();
82247
81921
  }
@@ -82360,7 +82034,7 @@ class AuroCombobox extends AuroElement$3 {
82360
82034
  if (this.menu.optionSelected) {
82361
82035
  const selected = this.menu.optionSelected;
82362
82036
 
82363
- if (!this.optionSelected || this.optionSelected !== selected) {
82037
+ if (this.optionSelected !== selected) {
82364
82038
  this.optionSelected = selected;
82365
82039
  }
82366
82040
 
@@ -82373,7 +82047,7 @@ class AuroCombobox extends AuroElement$3 {
82373
82047
  }
82374
82048
 
82375
82049
  // Update display
82376
- this.updateTriggerTextDisplay(getOptionLabel(this.optionSelected) || this.menu.value);
82050
+ this.updateTriggerTextDisplay(getOptionLabel(this.optionSelected));
82377
82051
 
82378
82052
  // Update match word for filtering
82379
82053
  const trimmedInput = normalizeFilterValue(this.input.value);
@@ -82391,11 +82065,15 @@ class AuroCombobox extends AuroElement$3 {
82391
82065
 
82392
82066
  // Announce the selection after the dropdown closes so it isn't
82393
82067
  // overridden by VoiceOver's "collapsed" announcement from aria-expanded.
82068
+ // Skip when there's no selected value (e.g. menu.clearSelection() from
82069
+ // the unmatched-value path), otherwise VoiceOver reads "undefined".
82394
82070
  const selectedValue = this.menu.value;
82395
- const announcementDelay = 300;
82396
- setTimeout(() => {
82397
- announceToScreenReader$1(this._getAnnouncementRoot(), `${selectedValue}, selected`);
82398
- }, announcementDelay);
82071
+ if (selectedValue) {
82072
+ const announcementDelay = 300;
82073
+ setTimeout(() => {
82074
+ announceToScreenReader$1(this._getAnnouncementRoot(), `${selectedValue}, selected`);
82075
+ }, announcementDelay);
82076
+ }
82399
82077
  }
82400
82078
 
82401
82079
  // Programmatic value syncs leave availableOptions stale because
@@ -82755,15 +82433,7 @@ class AuroCombobox extends AuroElement$3 {
82755
82433
  this.menu.value = undefined;
82756
82434
  this.validation.reset(this);
82757
82435
  this.touched = false;
82758
- // Force validity back to the cleared state. validation.reset() calls
82759
- // validate() at the end, and (post-credit-card-fix) the trigger input's
82760
- // residual validity may still be copied into the combobox by the
82761
- // auroInputElements loop. Explicitly clear here so reset() actually
82762
- // leaves the component in a "no validity" state.
82763
82436
  this.validity = undefined;
82764
- this.errorMessage = '';
82765
- this.input.validity = undefined;
82766
- this.input.errorMessage = '';
82767
82437
  }
82768
82438
 
82769
82439
  /**
@@ -82816,52 +82486,27 @@ class AuroCombobox extends AuroElement$3 {
82816
82486
  this.input.value = this.value;
82817
82487
  }
82818
82488
 
82819
- // Sync menu.value only when an option actually matches; otherwise clear it.
82489
+ // Sync menu.value only when an option actually matches, or when filter
82490
+ // mode needs setMenuValue to dispatch auroMenu-selectValueFailure (the
82491
+ // listener at line 1206 clears combobox.value, mirroring select's
82492
+ // pattern). Otherwise sync the input display for freeform values.
82820
82493
  if (this.menu.options && this.menu.options.length > 0) {
82821
- if (this.menu.options.some((opt) => opt.value === this.value)) {
82822
- this.setMenuValue(this.value);
82823
- } else if (this.behavior === 'filter') {
82824
- // In filter mode, freeform values aren't allowed. Push the unmatched
82825
- // value through setMenuValue so menu dispatches auroMenu-selectValueFailure
82826
- // and the listener at line 1206 clears combobox.value (mirrors select's
82827
- // pattern). Bypassing setMenuValue here would skip the failure cascade.
82494
+ if (this.menu.options.some((opt) => opt.value === this.value) || this.behavior === 'filter') {
82828
82495
  this.setMenuValue(this.value);
82829
82496
  } else {
82830
- if (this.menu.value) {
82831
- this.menu.value = undefined;
82497
+ // Clear menu.value AND menu.optionSelected together. Clearing only
82498
+ // menu.value leaves the previously-selected option element pinned
82499
+ // as menu.optionSelected; a later auroMenu-selectedOption event
82500
+ // would then write its stale .value back into combobox.value.
82501
+ if (this.menu.value || this.menu.optionSelected) {
82502
+ this.menu.clearSelection();
82832
82503
  }
82833
- // Sync the display for programmatic freeform value changes (e.g. the
82834
- // swap-values pattern). Guard with _syncingDisplayValue so that the
82835
- // re-entrant input event from base-input.notifyValueChanged() is
82836
- // ignored by handleInputValueChange. Skip the sync when input already
82837
- // matches to avoid spurious events during the normal typing path.
82838
- const nextValue = this.value || '';
82839
- const triggerNeedsSync = this.input.value !== nextValue;
82840
- const bibNeedsSync = Boolean(this.inputInBib && this.inputInBib !== this.input && this.inputInBib.value !== nextValue);
82841
- if (triggerNeedsSync || bibNeedsSync) {
82842
- this._syncingDisplayValue = true;
82843
- if (triggerNeedsSync) {
82844
- this.input.value = nextValue;
82845
- }
82846
- if (bibNeedsSync) {
82847
- this.inputInBib.value = nextValue;
82848
- }
82849
- const pending = [];
82850
- if (triggerNeedsSync) {
82851
- pending.push(this.input.updateComplete);
82852
- }
82853
- if (bibNeedsSync) {
82854
- pending.push(this.inputInBib.updateComplete);
82855
- }
82856
- Promise.all(pending).then(() => {
82857
- if (triggerNeedsSync && this.input.maskInstance && typeof this.input.maskInstance.updateValue === 'function') {
82858
- this.input.maskInstance.updateValue();
82859
- }
82860
- if (bibNeedsSync && this.inputInBib && this.inputInBib.maskInstance && typeof this.inputInBib.maskInstance.updateValue === 'function') {
82861
- this.inputInBib.maskInstance.updateValue();
82862
- }
82863
- this._syncingDisplayValue = false;
82864
- // handleInputValueChange bailed on the flag — refresh the filter.
82504
+ // Suggestion-mode freeform value: sync the trigger + bib to show it,
82505
+ // then refresh the filter once the inputs flush (handleInputValueChange
82506
+ // bailed on _syncingDisplayValue).
82507
+ const syncPromise = this.syncInputValuesAcrossTriggerAndBib(this.value || '');
82508
+ if (syncPromise) {
82509
+ syncPromise.then(() => {
82865
82510
  this._programmaticFilterRefresh = true;
82866
82511
  this.handleMenuOptions();
82867
82512
  setTimeout(() => {
@@ -85650,6 +85295,21 @@ function getEnabledOptions(menu) {
85650
85295
  return (menu?.options || []).filter((option) => !option.disabled);
85651
85296
  }
85652
85297
 
85298
+ /**
85299
+ * Returns the active (selectable + visible) options for type-ahead navigation.
85300
+ *
85301
+ * Uses auro-menuoption's `isActive` getter, which excludes disabled, hidden,
85302
+ * and static options (e.g. `static nomatch` placeholders) so the type-ahead
85303
+ * cursor never lands on a non-actionable item. Same empty-safe handling as
85304
+ * `getEnabledOptions`.
85305
+ *
85306
+ * @param {HTMLElement | null | undefined} menu - The auro-menu element.
85307
+ * @returns {Array<HTMLElement>} Active options, empty array when none.
85308
+ */
85309
+ function getActiveOptions(menu) {
85310
+ return (menu?.options || []).filter((option) => option.isActive);
85311
+ }
85312
+
85653
85313
  /* eslint-disable new-cap */
85654
85314
 
85655
85315
  const selectKeyboardStrategy = {
@@ -85682,6 +85342,14 @@ const selectKeyboardStrategy = {
85682
85342
  },
85683
85343
 
85684
85344
  Escape(component, evt, ctx) {
85345
+ // Always clear the type-ahead buffer — Escape is a universal cancel.
85346
+ // Safe to call when the buffer is empty.
85347
+ // eslint-disable-next-line no-underscore-dangle
85348
+ if (typeof component._clearTypeaheadBuffer === 'function') {
85349
+ // eslint-disable-next-line no-underscore-dangle
85350
+ component._clearTypeaheadBuffer();
85351
+ }
85352
+
85685
85353
  if (!ctx.isExpanded) {
85686
85354
  return;
85687
85355
  }
@@ -85741,16 +85409,25 @@ const selectKeyboardStrategy = {
85741
85409
  },
85742
85410
 
85743
85411
  default(component, evt, ctx) {
85744
- component.updateActiveOptionBasedOnKey(evt.key);
85412
+ // Space resolves to either typeahead-buffer extension or bib toggle
85413
+ // depending on whether a type-ahead buffer is active. Mirrors native
85414
+ // <select> and the WAI-ARIA APG Listbox guidance: mid-typeahead space
85415
+ // is a search character (e.g. "San Francisco"); otherwise it toggles.
85745
85416
  if (evt.key === ' ') {
85746
85417
  evt.preventDefault();
85747
85418
  evt.stopPropagation();
85419
+ if (component.typeaheadBuffer && component.typeaheadBuffer.length > 0) {
85420
+ component.updateActiveOptionBasedOnKey(evt.key);
85421
+ return;
85422
+ }
85748
85423
  if (ctx.isExpanded) {
85749
85424
  component.dropdown.hide();
85750
- return;
85425
+ } else {
85426
+ component.dropdown.show();
85751
85427
  }
85752
- component.dropdown.show();
85428
+ return;
85753
85429
  }
85430
+ component.updateActiveOptionBasedOnKey(evt.key);
85754
85431
  },
85755
85432
  };
85756
85433
 
@@ -89662,7 +89339,7 @@ let AuroHelpText$1 = class AuroHelpText extends i$3 {
89662
89339
  }
89663
89340
  };
89664
89341
 
89665
- var formkitVersion$1 = '202606171946';
89342
+ var formkitVersion$1 = '202606192004';
89666
89343
 
89667
89344
  class AuroElement extends i$3 {
89668
89345
  static get properties() {
@@ -91675,7 +91352,7 @@ class AuroHelpText extends i$3 {
91675
91352
  }
91676
91353
  }
91677
91354
 
91678
- var formkitVersion = '202606171946';
91355
+ var formkitVersion = '202606192004';
91679
91356
 
91680
91357
  var styleCss = 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}.body-default{font-size:var(--wcss-body-default-font-size, 1rem);font-weight:var(--wcss-body-default-weight, );line-height:var(--wcss-body-default-line-height, 1.5rem)}.body-default,.body-default-emphasized{font-family:var(--wcss-body-family, "AS Circular"),system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;letter-spacing:var(--wcss-body-letter-spacing, 0)}.body-default-emphasized{font-size:var(--wcss-body-default-emphasized-font-size, 1rem);font-weight:var(--wcss-body-default-emphasized-weight, );line-height:var(--wcss-body-default-emphasized-line-height, 1.5rem)}.body-lg{font-size:var(--wcss-body-lg-font-size, 1.125rem);font-weight:var(--wcss-body-lg-weight, );line-height:var(--wcss-body-lg-line-height, 1.625rem)}.body-lg,.body-lg-emphasized{font-family:var(--wcss-body-family, "AS Circular"),system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;letter-spacing:var(--wcss-body-letter-spacing, 0)}.body-lg-emphasized{font-size:var(--wcss-body-lg-emphasized-font-size, 1.125rem);font-weight:var(--wcss-body-lg-emphasized-weight, );line-height:var(--wcss-body-lg-emphasized-line-height, 1.625rem)}.body-sm{font-size:var(--wcss-body-sm-font-size, 0.875rem);font-weight:var(--wcss-body-sm-weight, );line-height:var(--wcss-body-sm-line-height, 1.25rem)}.body-sm,.body-sm-emphasized{font-family:var(--wcss-body-family, "AS Circular"),system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;letter-spacing:var(--wcss-body-letter-spacing, 0)}.body-sm-emphasized{font-size:var(--wcss-body-sm-emphasized-font-size, 0.875rem);font-weight:var(--wcss-body-sm-emphasized-weight, );line-height:var(--wcss-body-sm-emphasized-line-height, 1.25rem)}.body-xs{font-size:var(--wcss-body-xs-font-size, 0.75rem);font-weight:var(--wcss-body-xs-weight, );line-height:var(--wcss-body-xs-line-height, 1rem)}.body-xs,.body-xs-emphasized{font-family:var(--wcss-body-family, "AS Circular"),system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;letter-spacing:var(--wcss-body-letter-spacing, 0)}.body-xs-emphasized{font-size:var(--wcss-body-xs-emphasized-font-size, 0.75rem);font-weight:var(--wcss-body-xs-emphasized-weight, );line-height:var(--wcss-body-xs-emphasized-line-height, 1rem)}.body-2xs{font-size:var(--wcss-body-2xs-font-size, 0.625rem);font-weight:var(--wcss-body-2xs-weight, );line-height:var(--wcss-body-2xs-line-height, 0.875rem)}.body-2xs,.body-2xs-emphasized{font-family:var(--wcss-body-family, "AS Circular"),system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;letter-spacing:var(--wcss-body-letter-spacing, 0)}.body-2xs-emphasized{font-size:var(--wcss-body-2xs-emphasized-font-size, 0.625rem);font-weight:var(--wcss-body-2xs-emphasized-weight, );line-height:var(--wcss-body-2xs-emphasized-line-height, 0.875rem)}.display-2xl{font-family:var(--wcss-display-2xl-family, "AS Circular"),var(--wcss-display-2xl-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-display-2xl-font-size, clamp(3.5rem, 6vw, 5.375rem));font-weight:var(--wcss-display-2xl-weight, 300);letter-spacing:var(--wcss-display-2xl-letter-spacing, 0);line-height:var(--wcss-display-2xl-line-height, 1.3)}.display-xl{font-family:var(--wcss-display-xl-family, "AS Circular"),var(--wcss-display-xl-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-display-xl-font-size, clamp(3rem, 5.3333333333vw, 4.5rem));font-weight:var(--wcss-display-xl-weight, 300);letter-spacing:var(--wcss-display-xl-letter-spacing, 0);line-height:var(--wcss-display-xl-line-height, 1.3)}.display-lg{font-family:var(--wcss-display-lg-family, "AS Circular"),var(--wcss-display-lg-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-display-lg-font-size, clamp(2.75rem, 4.6666666667vw, 4rem));font-weight:var(--wcss-display-lg-weight, 300);letter-spacing:var(--wcss-display-lg-letter-spacing, 0);line-height:var(--wcss-display-lg-line-height, 1.3)}.display-md{font-family:var(--wcss-display-md-family, "AS Circular"),var(--wcss-display-md-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-display-md-font-size, clamp(2.5rem, 4vw, 3.5rem));font-weight:var(--wcss-display-md-weight, 300);letter-spacing:var(--wcss-display-md-letter-spacing, 0);line-height:var(--wcss-display-md-line-height, 1.3)}.display-sm{font-family:var(--wcss-display-sm-family, "AS Circular"),var(--wcss-display-sm-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-display-sm-font-size, clamp(2rem, 3.6666666667vw, 3rem));font-weight:var(--wcss-display-sm-weight, 300);letter-spacing:var(--wcss-display-sm-letter-spacing, 0);line-height:var(--wcss-display-sm-line-height, 1.3)}.display-xs{font-family:var(--wcss-display-xs-family, "AS Circular"),var(--wcss-display-xs-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-display-xs-font-size, clamp(1.75rem, 3vw, 2.375rem));font-weight:var(--wcss-display-xs-weight, 300);letter-spacing:var(--wcss-display-xs-letter-spacing, 0);line-height:var(--wcss-display-xs-line-height, 1.3)}.heading-xl{font-family:var(--wcss-heading-xl-family, "AS Circular"),var(--wcss-heading-xl-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-heading-xl-font-size, clamp(2rem, 3vw, 2.5rem));font-weight:var(--wcss-heading-xl-weight, 300);letter-spacing:var(--wcss-heading-xl-letter-spacing, 0);line-height:var(--wcss-heading-xl-line-height, 1.3)}.heading-lg{font-family:var(--wcss-heading-lg-family, "AS Circular"),var(--wcss-heading-lg-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-heading-lg-font-size, clamp(1.75rem, 2.6666666667vw, 2.25rem));font-weight:var(--wcss-heading-lg-weight, 300);letter-spacing:var(--wcss-heading-lg-letter-spacing, 0);line-height:var(--wcss-heading-lg-line-height, 1.3)}.heading-md{font-family:var(--wcss-heading-md-family, "AS Circular"),var(--wcss-heading-md-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-heading-md-font-size, clamp(1.625rem, 2.3333333333vw, 1.75rem));font-weight:var(--wcss-heading-md-weight, 300);letter-spacing:var(--wcss-heading-md-letter-spacing, 0);line-height:var(--wcss-heading-md-line-height, 1.3)}.heading-sm{font-family:var(--wcss-heading-sm-family, "AS Circular"),var(--wcss-heading-sm-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-heading-sm-font-size, clamp(1.375rem, 2vw, 1.5rem));font-weight:var(--wcss-heading-sm-weight, 300);letter-spacing:var(--wcss-heading-sm-letter-spacing, 0);line-height:var(--wcss-heading-sm-line-height, 1.3)}.heading-xs{font-family:var(--wcss-heading-xs-family, "AS Circular"),var(--wcss-heading-xs-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-heading-xs-font-size, clamp(1.25rem, 1.6666666667vw, 1.25rem));font-weight:var(--wcss-heading-xs-weight, 300);letter-spacing:var(--wcss-heading-xs-letter-spacing, 0);line-height:var(--wcss-heading-xs-line-height, 1.3)}.heading-2xs{font-family:var(--wcss-heading-2xs-family, "AS Circular"),var(--wcss-heading-2xs-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-heading-2xs-font-size, clamp(1.125rem, 1.5vw, 1.125rem));font-weight:var(--wcss-heading-2xs-weight, 300);letter-spacing:var(--wcss-heading-2xs-letter-spacing, 0);line-height:var(--wcss-heading-2xs-line-height, 1.3)}.accent-2xl{font-family:var(--wcss-accent-2xl-family, "Good OT"),var(--wcss-accent-2xl-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-accent-2xl-font-size, clamp(2rem, 3.1666666667vw, 2.375rem));font-weight:var(--wcss-accent-2xl-weight, 450);letter-spacing:var(--wcss-accent-2xl-letter-spacing, 0.05em);line-height:var(--wcss-accent-2xl-line-height, 1)}.accent-2xl,.accent-xl{text-transform:uppercase}.accent-xl{font-family:var(--wcss-accent-xl-family, "Good OT"),var(--wcss-accent-xl-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-accent-xl-font-size, clamp(1.625rem, 2.3333333333vw, 2rem));font-weight:var(--wcss-accent-xl-weight, 450);letter-spacing:var(--wcss-accent-xl-letter-spacing, 0.05em);line-height:var(--wcss-accent-xl-line-height, 1.3)}.accent-lg{font-family:var(--wcss-accent-lg-family, "Good OT"),var(--wcss-accent-lg-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-accent-lg-font-size, clamp(1.5rem, 2.1666666667vw, 1.75rem));font-weight:var(--wcss-accent-lg-weight, 450);letter-spacing:var(--wcss-accent-lg-letter-spacing, 0.05em);line-height:var(--wcss-accent-lg-line-height, 1.3)}.accent-lg,.accent-md{text-transform:uppercase}.accent-md{font-family:var(--wcss-accent-md-family, "Good OT"),var(--wcss-accent-md-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-accent-md-font-size, clamp(1.375rem, 1.8333333333vw, 1.5rem));font-weight:var(--wcss-accent-md-weight, 500);letter-spacing:var(--wcss-accent-md-letter-spacing, 0.05em);line-height:var(--wcss-accent-md-line-height, 1.3)}.accent-sm{font-family:var(--wcss-accent-sm-family, "Good OT"),var(--wcss-accent-sm-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-accent-sm-font-size, clamp(1.125rem, 1.5vw, 1.25rem));font-weight:var(--wcss-accent-sm-weight, 500);letter-spacing:var(--wcss-accent-sm-letter-spacing, 0.05em);line-height:var(--wcss-accent-sm-line-height, 1.3)}.accent-sm,.accent-xs{text-transform:uppercase}.accent-xs{font-family:var(--wcss-accent-xs-family, "Good OT"),var(--wcss-accent-xs-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-accent-xs-font-size, clamp(1rem, 1.3333333333vw, 1rem));font-weight:var(--wcss-accent-xs-weight, 500);letter-spacing:var(--wcss-accent-xs-letter-spacing, 0.1em);line-height:var(--wcss-accent-xs-line-height, 1.3)}.accent-2xs{font-family:var(--wcss-accent-2xs-family, "Good OT"),var(--wcss-accent-2xs-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-accent-2xs-font-size, clamp(0.875rem, 1.1666666667vw, 0.875rem));font-weight:var(--wcss-accent-2xs-weight, 450);letter-spacing:var(--wcss-accent-2xs-letter-spacing, 0.1em);line-height:var(--wcss-accent-2xs-line-height, 1.3);text-transform:uppercase}[auro-dropdown]{--ds-auro-dropdown-trigger-border-color: var(--ds-auro-select-border-color);--ds-auro-dropdown-trigger-background-color: var(--ds-auro-select-background-color);--ds-auro-dropdown-trigger-container-color: var(--ds-auro-select-background-color);--ds-auro-dropdown-trigger-outline-color: var(--ds-auro-select-outline-color)}:host{display:inline-block;text-align:left;vertical-align:top}:host([layout*=emphasized]) [auro-dropdown],:host([layout*=snowflake]) [auro-dropdown]{--ds-auro-select-border-color: transparent}:host([layout*=emphasized]) .mainContent,:host([layout*=snowflake]) .mainContent{text-align:center}.mainContent{position:relative;display:flex;overflow:hidden;flex:1;flex-direction:column;align-items:center;justify-content:center}.valueContainer [slot=displayValue]{display:none}.accents{display:flex;flex-direction:row;align-items:center;justify-content:center}::slotted([slot=typeIcon]){margin-right:var(--ds-size-100, 0.5rem)}.displayValue{display:block}.displayValue:not(.force){display:none}.displayValue:not(.force).hasContent:is(.withValue):not(.hasFocus){display:block}.triggerContent{display:flex;width:100%;align-items:center;justify-content:center}:host([layout*=emphasized]) .triggerContent{padding:0 var(--ds-size-100, 0.5rem) 0 var(--ds-size-300, 1.5rem)}:host([layout*=snowflake]) .triggerContent{padding:0 var(--ds-size-100, 0.5rem) 0 var(--ds-size-200, 1rem)}:host([layout*=snowflake]) label{padding-block:var(--ds-size-25, 0.125rem)}:host([layout*=classic]) .triggerContent{padding:0 var(--ds-size-100, 0.5rem)}:host([layout*=classic]) .mainContent{align-items:start}:host([layout*=classic]) label{overflow:hidden;cursor:text;text-overflow:ellipsis;white-space:nowrap}:host([layout*=classic]) .value{height:auto}label{color:var(--ds-auro-select-label-text-color)}:host(:is([validity]:not([validity=valid]))) [auro-dropdown]{--ds-auro-select-border-color: var(--ds-basic-color-status-error, #e31f26);--ds-auro-select-outline-color: var(--ds-basic-color-status-error, #e31f26);--ds-auro-dropdown-helptext-text-color: var(--ds-basic-color-texticon-default, #2a2a2a)}:host([ondark]:is([validity]:not([validity=valid]))) [auro-dropdown],:host([appearance=inverse]:is([validity]:not([validity=valid]))) [auro-dropdown]{--ds-auro-select-border-color: var(--ds-advanced-color-state-error-inverse, #f9a4a8);--ds-auro-select-outline-color: var(--ds-advanced-color-state-error-inverse, #f9a4a8);--ds-auro-dropdown-helptext-text-color: var(--ds-basic-color-texticon-inverse, #ffffff)}#slotHolder{display:none}:host([fluid]){width:100%}:host([disabled]){pointer-events:none;user-select:none}:host([disabled]:not([ondark])) [auro-dropdown],:host([disabled]:not([appearance=inverse])) [auro-dropdown]{--ds-auro-select-border-color: var(--ds-basic-color-border-subtle, #dddddd)}:host(:not([layout*=classic])[disabled][ondark]) [auro-dropdown],:host(:not([layout*=classic])[disabled][appearance=inverse]) [auro-dropdown]{--ds-auro-select-border-color: transparent}`;
91681
91358
 
@@ -91780,6 +91457,16 @@ class AuroSelect extends AuroElement$1 {
91780
91457
  * @private
91781
91458
  */
91782
91459
  this.hasDisplayValueContent = false;
91460
+
91461
+ /**
91462
+ * @private
91463
+ */
91464
+ this.typeaheadBuffer = '';
91465
+
91466
+ /**
91467
+ * @private
91468
+ */
91469
+ this._typeaheadTimeout = null;
91783
91470
  }
91784
91471
 
91785
91472
  /**
@@ -91792,6 +91479,7 @@ class AuroSelect extends AuroElement$1 {
91792
91479
  this.fullscreenBreakpoint = 'sm';
91793
91480
  this.onDark = false;
91794
91481
  this.isPopoverVisible = false;
91482
+ this.typeaheadTimeoutMs = 500;
91795
91483
 
91796
91484
  // Layout Config
91797
91485
  this.layout = 'classic';
@@ -92095,6 +91783,16 @@ class AuroSelect extends AuroElement$1 {
92095
91783
  attribute: false
92096
91784
  },
92097
91785
 
91786
+ /**
91787
+ * Milliseconds of keyboard inactivity before the type-ahead buffer resets.
91788
+ * Increase for users who type slowly.
91789
+ * @default 500
91790
+ */
91791
+ typeaheadTimeoutMs: {
91792
+ type: Number,
91793
+ reflect: true
91794
+ },
91795
+
92098
91796
  /**
92099
91797
  * Specifies the `validityState` this element is in.
92100
91798
  */
@@ -92534,6 +92232,7 @@ class AuroSelect extends AuroElement$1 {
92534
92232
  this.addEventListener('blur', () => {
92535
92233
  this.validate();
92536
92234
  this.hasFocus = false;
92235
+ this._clearTypeaheadBuffer();
92537
92236
  });
92538
92237
  }
92539
92238
 
@@ -92547,41 +92246,89 @@ class AuroSelect extends AuroElement$1 {
92547
92246
  }
92548
92247
  }
92549
92248
 
92249
+ /**
92250
+ * Returns the lowercase, trimmed text content of a menu option.
92251
+ * @private
92252
+ * @param {HTMLElement} option - The menu option element.
92253
+ * @returns {string}
92254
+ */
92255
+ _getOptionDisplayText(option) {
92256
+ return (option.textContent || '').trim().toLowerCase();
92257
+ }
92258
+
92259
+ /**
92260
+ * Empties the type-ahead buffer and cancels any pending reset timeout.
92261
+ * Called when focus leaves the component, when Escape closes the bib, and on disconnect
92262
+ * so a stale buffer never bridges into a fresh interaction.
92263
+ * @private
92264
+ */
92265
+ _clearTypeaheadBuffer() {
92266
+ if (this._typeaheadTimeout) {
92267
+ clearTimeout(this._typeaheadTimeout);
92268
+ this._typeaheadTimeout = null;
92269
+ }
92270
+ this.typeaheadBuffer = '';
92271
+ }
92272
+
92550
92273
  /**
92551
92274
  * Updates the active option in the menu based on keyboard input.
92275
+ *
92276
+ * Implements the WAI-ARIA APG Listbox type-ahead pattern: accumulates printable
92277
+ * keystrokes into a buffer that resets after `typeaheadTimeoutMs` of inactivity.
92278
+ * A multi-character buffer matches the first option whose displayed text starts
92279
+ * with the buffer; repeating a single character cycles through options that start
92280
+ * with that character.
92552
92281
  * @private
92553
92282
  * @param {string} _key - The key pressed by the user.
92554
92283
  * @returns {void}
92555
92284
  */
92556
92285
  updateActiveOptionBasedOnKey(_key) {
92286
+ // Ignore non-printable keys (Shift, ArrowDown, Tab, etc.)
92287
+ if (typeof _key !== 'string' || _key.length !== 1) {
92288
+ return;
92289
+ }
92557
92290
 
92558
- // Get a lowercase version of the key pressed
92559
- const key = _key.toLowerCase();
92560
-
92561
- // Calculate how many times the same letter has been pressed
92562
- this.sameLetterTimes = key === this.lastLetter ? this.sameLetterTimes + 1 : 0;
92291
+ // No selectable options to match against clear any stale buffer/timer so
92292
+ // Space stays a bib toggle and the next keystroke after fresh options load
92293
+ // starts cleanly. `getActiveOptions` excludes disabled, hidden, and static
92294
+ // options (e.g. `static nomatch` placeholders). Checked BEFORE mutating
92295
+ // the buffer.
92296
+ const options = getActiveOptions(this.menu);
92297
+ if (!options.length) {
92298
+ this._clearTypeaheadBuffer();
92299
+ return;
92300
+ }
92563
92301
 
92564
- // Set last letter for tracking
92565
- this.lastLetter = key;
92302
+ const key = _key.toLowerCase();
92566
92303
 
92567
- // Get all the options that start with the last letter pressed
92568
- const letterOptions = this.menu.options.filter((option) => {
92569
- const optionText = option.value || '';
92570
- return optionText.toLowerCase().startsWith(this.lastLetter);
92571
- });
92304
+ // Reset the buffer after a period of inactivity
92305
+ if (this._typeaheadTimeout) {
92306
+ clearTimeout(this._typeaheadTimeout);
92307
+ }
92308
+ this._typeaheadTimeout = setTimeout(() => {
92309
+ this._clearTypeaheadBuffer();
92310
+ }, this.typeaheadTimeoutMs);
92572
92311
 
92573
- // If we have options that match the letter pressed
92574
- if (letterOptions.length) {
92312
+ this.typeaheadBuffer += key;
92575
92313
 
92576
- // Show the dropdown if it is not already visible
92577
- this.dropdown.show();
92314
+ const isRepeatedChar = this.typeaheadBuffer.length > 1 && new Set(this.typeaheadBuffer).size === 1;
92578
92315
 
92579
- // Get the index we're after based on how many times the letter has been pressed and the length of the letterOptions array
92580
- const index = this.sameLetterTimes < letterOptions.length ? this.sameLetterTimes : this.sameLetterTimes % letterOptions.length;
92316
+ let match = null;
92317
+ if (isRepeatedChar) {
92318
+ const matches = options.filter((option) => this._getOptionDisplayText(option).startsWith(key));
92319
+ if (matches.length) {
92320
+ const cycleIndex = (this.typeaheadBuffer.length - 1) % matches.length;
92321
+ match = matches[cycleIndex];
92322
+ }
92323
+ } else {
92324
+ match = options.find((option) => this._getOptionDisplayText(option).startsWith(this.typeaheadBuffer));
92325
+ }
92581
92326
 
92582
- // Select the new option in the menu
92583
- const newOption = letterOptions[index];
92584
- this.menu.updateActiveOption(newOption);
92327
+ if (match) {
92328
+ if (!this.dropdown.isPopoverVisible) {
92329
+ this.dropdown.show();
92330
+ }
92331
+ this.menu.updateActiveOption(match);
92585
92332
  }
92586
92333
  }
92587
92334
 
@@ -92695,6 +92442,11 @@ class AuroSelect extends AuroElement$1 {
92695
92442
  }
92696
92443
  }
92697
92444
 
92445
+ disconnectedCallback() {
92446
+ super.disconnectedCallback();
92447
+ this._clearTypeaheadBuffer();
92448
+ }
92449
+
92698
92450
  // lifecycle runs only after the element's DOM has been updated the first time
92699
92451
  firstUpdated() {
92700
92452
  // Add the tag name as an attribute if it is different than the component name