@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
@@ -10331,6 +10331,7 @@ class AuroInputUtilities {
10331
10331
  const maskOptions = this.getMaskOptions('date', normalizedFormat);
10332
10332
 
10333
10333
  if (!(valueObject instanceof Date) || Number.isNaN(valueObject.getTime()) || !maskOptions || typeof maskOptions.format !== 'function') {
10334
+ console.debug('Invalid date object or mask options for formatting', { valueObject, maskOptions }); // eslint-disable-line no-console
10334
10335
  return undefined;
10335
10336
  }
10336
10337
 
@@ -10482,10 +10483,8 @@ class BaseInput extends AuroElement {
10482
10483
  this.layout = 'classic';
10483
10484
  this.locale = 'en-US';
10484
10485
  this.max = undefined;
10485
- this._maxObject = undefined;
10486
10486
  this.maxLength = undefined;
10487
10487
  this.min = undefined;
10488
- this._minObject = undefined;
10489
10488
  this.minLength = undefined;
10490
10489
  this.required = false;
10491
10490
  this.onDark = false;
@@ -10493,7 +10492,6 @@ class BaseInput extends AuroElement {
10493
10492
  this.size = 'lg';
10494
10493
  this.shape = 'classic';
10495
10494
  this.value = undefined;
10496
- this._valueObject = undefined;
10497
10495
 
10498
10496
  this._initializePrivateDefaults();
10499
10497
  }
@@ -11033,7 +11031,7 @@ class BaseInput extends AuroElement {
11033
11031
  * @returns {Date|undefined}
11034
11032
  */
11035
11033
  get valueObject() {
11036
- return this._valueObject || this._computeDateObjectFallback(this.value);
11034
+ return this.value && dateFormatter.isValidDate(this.value) ? dateFormatter.stringToDateInstance(this.value) : undefined;
11037
11035
  }
11038
11036
 
11039
11037
  /**
@@ -11041,7 +11039,7 @@ class BaseInput extends AuroElement {
11041
11039
  * @returns {Date|undefined}
11042
11040
  */
11043
11041
  get minObject() {
11044
- return this._minObject || this._computeDateObjectFallback(this.min);
11042
+ return this.min && dateFormatter.isValidDate(this.min) ? dateFormatter.stringToDateInstance(this.min) : undefined;
11045
11043
  }
11046
11044
 
11047
11045
  /**
@@ -11049,50 +11047,7 @@ class BaseInput extends AuroElement {
11049
11047
  * @returns {Date|undefined}
11050
11048
  */
11051
11049
  get maxObject() {
11052
- return this._maxObject || this._computeDateObjectFallback(this.max);
11053
- }
11054
-
11055
- /**
11056
- * Parses a date string into a Date object when the corresponding `_*Object`
11057
- * field hasn't been synced yet by `updated()`. Returns undefined when the
11058
- * input type/format isn't a full date or the string is not a valid date.
11059
- *
11060
- * Why this exists: a parent (datepicker) can call `inputN.validate()` from
11061
- * inside its own `updated()` before this input's `updated()` has run
11062
- * `syncDateValues()` — so `_valueObject`/`_maxObject` are still `undefined`
11063
- * and range checks would otherwise silently no-op (flipping the result to
11064
- * `valid` or `patternMismatch`).
11065
- * @private
11066
- * @param {string|undefined} dateStr - ISO date string from `value`/`min`/`max`.
11067
- * @returns {Date|undefined}
11068
- */
11069
- _computeDateObjectFallback(dateStr) {
11070
- if (!dateStr || !this.util || !this.util.isFullDateFormat(this.type, this.format)) {
11071
- return undefined;
11072
- }
11073
- if (!dateFormatter.isValidDate(dateStr)) {
11074
- return undefined;
11075
- }
11076
- return dateFormatter.stringToDateInstance(dateStr);
11077
- }
11078
-
11079
- /**
11080
- * Internal setter for readonly date object properties.
11081
- * @private
11082
- * @param {'valueObject'|'minObject'|'maxObject'} propertyName - Public object property name.
11083
- * @param {Date|undefined} propertyValue - Value to assign.
11084
- * @returns {void}
11085
- */
11086
- setDateObjectProperty(propertyName, propertyValue) {
11087
- const internalPropertyName = `_${propertyName}`;
11088
- const previousValue = this[internalPropertyName];
11089
-
11090
- if (previousValue === propertyValue) {
11091
- return;
11092
- }
11093
-
11094
- this[internalPropertyName] = propertyValue;
11095
- this.requestUpdate(propertyName, previousValue);
11050
+ return this.max && dateFormatter.isValidDate(this.max) ? dateFormatter.stringToDateInstance(this.max) : undefined;
11096
11051
  }
11097
11052
 
11098
11053
  connectedCallback() {
@@ -11121,7 +11076,6 @@ class BaseInput extends AuroElement {
11121
11076
  format: this.format
11122
11077
  });
11123
11078
  this.configureDataForType();
11124
- this.syncDateValues();
11125
11079
  }
11126
11080
 
11127
11081
  disconnectedCallback() {
@@ -11141,10 +11095,6 @@ class BaseInput extends AuroElement {
11141
11095
  this.wrapperElement.addEventListener('click', this.handleClick);
11142
11096
  }
11143
11097
 
11144
- // add attribute for query selectors when auro-input is registered under a custom name
11145
- if (this.tagName.toLowerCase() !== 'auro-input' && !this.hasAttribute('auro-input')) {
11146
- this.setAttribute('auro-input', '');
11147
- }
11148
11098
  this.inputId = this.id ? `${this.id}-input` : window.crypto.randomUUID();
11149
11099
 
11150
11100
  // use validity message override if declared when initializing the component
@@ -11155,7 +11105,6 @@ class BaseInput extends AuroElement {
11155
11105
  this.setCustomHelpTextMessage();
11156
11106
  this.configureAutoFormatting();
11157
11107
  this.configureDataForType();
11158
- this.syncDateValues();
11159
11108
  }
11160
11109
 
11161
11110
  /**
@@ -11292,8 +11241,6 @@ class BaseInput extends AuroElement {
11292
11241
  this.configureDataForType();
11293
11242
  }
11294
11243
 
11295
- this.syncDateValues(changedProperties);
11296
-
11297
11244
  if (changedProperties.has('value')) {
11298
11245
  if (this.value && this.value.length > 0) {
11299
11246
  this.hasValue = true;
@@ -11315,14 +11262,14 @@ class BaseInput extends AuroElement {
11315
11262
 
11316
11263
  if (formattedValue !== this.inputElement.value) {
11317
11264
  this.skipNextProgrammaticInputEvent = true;
11318
- if (this.maskInstance && this.type === 'credit-card') {
11265
+ if (this.maskInstance && this.type !== 'date') {
11319
11266
  // Route through the mask so its _value and el.value stay in lock-step
11320
11267
  // (set value calls updateControl which writes el.value = displayValue).
11321
11268
  // Writing el.value directly leaves the mask thinking displayValue is
11322
- // stale; _saveSelection on the next focus/click then warns. Scoped to
11323
- // credit-card so date's own formattedValue (raw ISO when calendar-invalid)
11324
- // isn't re-masked through the mm/dd/yyyy mask, which would truncate it
11325
- // and flip validity from patternMismatch to tooShort.
11269
+ // stale; _saveSelection on the next focus/click then warns. Date is
11270
+ // excluded because its formattedValue can be raw ISO when the calendar
11271
+ // is invalid, and re-masking through mm/dd/yyyy would truncate it and
11272
+ // flip validity from patternMismatch to tooShort.
11326
11273
  this.maskInstance.value = formattedValue || '';
11327
11274
  } else if (formattedValue) {
11328
11275
  this.inputElement.value = formattedValue;
@@ -11364,120 +11311,60 @@ class BaseInput extends AuroElement {
11364
11311
  }));
11365
11312
  }
11366
11313
 
11367
-
11368
- /**
11369
- * Synchronizes the ISO string values and Date object representations for date-related properties.
11370
- * This keeps the model and display values aligned when either side changes.
11371
- *
11372
- * When a full date format is in use, this method updates `value`, `min`, and `max` from their corresponding
11373
- * Date objects or vice versa, based on which properties have changed. It only runs when the current configuration
11374
- * represents a full year/month/day date format.
11375
- *
11376
- * @param {Map<string, unknown>|undefined} [changedProperties=undefined] - Optional map of changed properties used to limit which values are synchronized.
11377
- * @returns {void}
11378
- * @private
11379
- */
11380
- syncDateValues(changedProperties = undefined) {
11381
- if (!this.util.isFullDateFormat(this.type, this.format)) {
11382
- return;
11383
- }
11384
-
11385
- this.syncSingleDateValue(changedProperties, 'valueObject', 'value');
11386
- this.syncSingleDateValue(changedProperties, 'minObject', 'min');
11387
- this.syncSingleDateValue(changedProperties, 'maxObject', 'max');
11388
- }
11389
-
11390
- /**
11391
- * Synchronizes one date object/string property pair.
11392
- * @private
11393
- * @param {Map<string, unknown>|undefined} changedProperties - Map of changed properties from Lit.
11394
- * @param {string} objectProperty - Date object property name.
11395
- * @param {string} valueProperty - ISO string property name.
11396
- * @returns {void}
11397
- */
11398
- syncSingleDateValue(changedProperties, objectProperty, valueProperty) {
11399
- const objectPropertyChanged = !changedProperties || changedProperties.has(objectProperty);
11400
-
11401
- // objectProperty wins over valueProperty when both changed
11402
- if (objectPropertyChanged && this[objectProperty]) {
11403
- this[valueProperty] = dateFormatter.toISOFormatString(this[objectProperty]);
11404
- return;
11405
- }
11406
-
11407
- const valuePropertyChanged = !changedProperties || changedProperties.has(valueProperty);
11408
- if (!valuePropertyChanged) {
11409
- return;
11410
- }
11411
-
11412
- // 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)
11413
- if (
11414
- changedProperties &&
11415
- valueProperty === 'value' &&
11416
- changedProperties.get('value') === undefined &&
11417
- this[objectProperty] instanceof Date &&
11418
- this[valueProperty] === dateFormatter.toISOFormatString(this[objectProperty])
11419
- ) {
11420
- return;
11421
- }
11422
-
11423
- if (dateFormatter.isValidDate(this[valueProperty])) {
11424
- this.setDateObjectProperty(objectProperty, dateFormatter.stringToDateInstance(this[valueProperty]));
11425
- } else {
11426
- this.setDateObjectProperty(objectProperty, undefined);
11427
- }
11428
- }
11429
-
11430
11314
  /**
11431
11315
  * Sets up IMasks and logic based on auto-formatting requirements.
11432
11316
  * @private
11433
11317
  * @returns {void}
11434
11318
  */
11435
11319
  configureAutoFormatting() {
11436
- // Re-entrancy guard. The patched-setter's synthetic input event (suppressed
11437
- // by _configuringMask above) could otherwise trigger handleInput
11438
- // processCreditCard configureAutoFormatting before the outer call's
11439
- // set value has finished its alignCursor pass.
11320
+ // _configuringMask gates two things: external re-entry into this method
11321
+ // while setup is mid-flight (from property changes that call back here),
11322
+ // and the accept/complete listeners below — both need to ignore the mask
11323
+ // events fired by our own value-restore step.
11440
11324
  if (this._configuringMask) return;
11441
11325
  this._configuringMask = true;
11442
11326
  try {
11327
+ // Destroy any prior mask so IMask can attach fresh under the new format.
11443
11328
  if (this.maskInstance) {
11444
11329
  this.maskInstance.destroy();
11445
11330
  }
11446
11331
 
11447
- // Pass new format to util
11448
11332
  this.util.updateFormat(this.format);
11449
11333
 
11450
11334
  const maskOptions = this.util.getMaskOptions(this.type, this.format);
11451
11335
 
11452
11336
  if (this.inputElement && maskOptions.mask) {
11453
-
11454
- // Stash and clear any existing value before IMask init.
11455
- // IMask's constructor processes the current input value which requires
11456
- // selection state clearing first avoids that scenario entirely.
11457
- // When the format changes (e.g. locale switch) and we have a valid ISO
11458
- // model value, compute the display string for the NEW format instead of
11459
- // re-using the old display string, which may be invalid in the new mask.
11337
+ // Capture the current display so it can be re-applied after IMask
11338
+ // attaches. The restore at the bottom goes through maskInstance.value
11339
+ // (not inputElement.value directly) so the mask's internal state and
11340
+ // the input's displayed text stay in lock-step.
11460
11341
  let existingValue = this.inputElement.value;
11342
+
11343
+ // Format-change case (e.g. locale switch): existingValue is the OLD
11344
+ // mask's display string and may not parse under the new mask. When
11345
+ // we have a valid date model, rebuild the display from valueObject
11346
+ // (the canonical source) using the new mask's format function.
11461
11347
  if (
11462
11348
  this.util.isFullDateFormat(this.type, this.format) &&
11463
11349
  this.value &&
11464
- dateFormatter.isValidDate(this.value) &&
11465
- this.valueObject instanceof Date &&
11466
- !Number.isNaN(this.valueObject.getTime()) &&
11350
+ this.valueObject &&
11467
11351
  typeof maskOptions.format === 'function'
11468
11352
  ) {
11469
11353
  existingValue = maskOptions.format(this.valueObject);
11470
11354
  }
11471
11355
 
11356
+ // Clear before IMask attaches so the constructor seeds an empty
11357
+ // internal value. Otherwise IMask reads the stale unmasked string
11358
+ // and emits a spurious 'accept' before the restore below runs.
11472
11359
  this.skipNextProgrammaticInputEvent = true;
11473
11360
  this.inputElement.value = '';
11474
11361
 
11475
11362
  this.maskInstance = IMask(this.inputElement, maskOptions);
11476
11363
 
11364
+ // Mask fires 'accept' on every value change, including the restore
11365
+ // step below. Skip events fired during configureAutoFormatting so
11366
+ // we don't overwrite a value the parent just pushed.
11477
11367
  this.maskInstance.on('accept', () => {
11478
- // Suppress propagation during configureAutoFormatting's own value-restoration
11479
- // (line below) — the mask emits 'accept' on every value-set, including ours,
11480
- // and we don't want to overwrite a value the parent just pushed.
11481
11368
  if (this._configuringMask) return;
11482
11369
  this.value = this.util.toModelValue(this.maskInstance.value, this.format);
11483
11370
  if (this.type === "date") {
@@ -11485,6 +11372,8 @@ class BaseInput extends AuroElement {
11485
11372
  }
11486
11373
  });
11487
11374
 
11375
+ // Mask fires 'complete' on the restore step below for any value that
11376
+ // happens to be a complete match. Same setup-suppression as 'accept'.
11488
11377
  this.maskInstance.on('complete', () => {
11489
11378
  if (this._configuringMask) return;
11490
11379
  this.value = this.util.toModelValue(this.maskInstance.value, this.format);
@@ -11493,7 +11382,9 @@ class BaseInput extends AuroElement {
11493
11382
  }
11494
11383
  });
11495
11384
 
11496
- // Restore the stashed value through IMask so it's properly masked
11385
+ // Write existingValue through the mask (not the input directly) so
11386
+ // the mask reformats it under the new rules and keeps its internal
11387
+ // _value aligned with the input's displayed text.
11497
11388
  if (existingValue) {
11498
11389
  this.maskInstance.value = existingValue;
11499
11390
  }
@@ -11661,7 +11552,6 @@ class BaseInput extends AuroElement {
11661
11552
  */
11662
11553
  reset() {
11663
11554
  this.value = undefined;
11664
- this.setDateObjectProperty('valueObject', undefined);
11665
11555
  this.validation.reset(this);
11666
11556
  }
11667
11557
 
@@ -11670,7 +11560,6 @@ class BaseInput extends AuroElement {
11670
11560
  */
11671
11561
  clear() {
11672
11562
  this.value = undefined;
11673
- this.setDateObjectProperty('valueObject', undefined);
11674
11563
  }
11675
11564
 
11676
11565
  /**
@@ -12199,7 +12088,7 @@ class AuroHelpText extends LitElement {
12199
12088
  }
12200
12089
  }
12201
12090
 
12202
- var formkitVersion = '202606171946';
12091
+ var formkitVersion = '202606192004';
12203
12092
 
12204
12093
  // Copyright (c) 2025 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
12205
12094
  // See LICENSE in the project root for license information.
@@ -10331,6 +10331,7 @@ class AuroInputUtilities {
10331
10331
  const maskOptions = this.getMaskOptions('date', normalizedFormat);
10332
10332
 
10333
10333
  if (!(valueObject instanceof Date) || Number.isNaN(valueObject.getTime()) || !maskOptions || typeof maskOptions.format !== 'function') {
10334
+ console.debug('Invalid date object or mask options for formatting', { valueObject, maskOptions }); // eslint-disable-line no-console
10334
10335
  return undefined;
10335
10336
  }
10336
10337
 
@@ -10482,10 +10483,8 @@ class BaseInput extends AuroElement {
10482
10483
  this.layout = 'classic';
10483
10484
  this.locale = 'en-US';
10484
10485
  this.max = undefined;
10485
- this._maxObject = undefined;
10486
10486
  this.maxLength = undefined;
10487
10487
  this.min = undefined;
10488
- this._minObject = undefined;
10489
10488
  this.minLength = undefined;
10490
10489
  this.required = false;
10491
10490
  this.onDark = false;
@@ -10493,7 +10492,6 @@ class BaseInput extends AuroElement {
10493
10492
  this.size = 'lg';
10494
10493
  this.shape = 'classic';
10495
10494
  this.value = undefined;
10496
- this._valueObject = undefined;
10497
10495
 
10498
10496
  this._initializePrivateDefaults();
10499
10497
  }
@@ -11033,7 +11031,7 @@ class BaseInput extends AuroElement {
11033
11031
  * @returns {Date|undefined}
11034
11032
  */
11035
11033
  get valueObject() {
11036
- return this._valueObject || this._computeDateObjectFallback(this.value);
11034
+ return this.value && dateFormatter.isValidDate(this.value) ? dateFormatter.stringToDateInstance(this.value) : undefined;
11037
11035
  }
11038
11036
 
11039
11037
  /**
@@ -11041,7 +11039,7 @@ class BaseInput extends AuroElement {
11041
11039
  * @returns {Date|undefined}
11042
11040
  */
11043
11041
  get minObject() {
11044
- return this._minObject || this._computeDateObjectFallback(this.min);
11042
+ return this.min && dateFormatter.isValidDate(this.min) ? dateFormatter.stringToDateInstance(this.min) : undefined;
11045
11043
  }
11046
11044
 
11047
11045
  /**
@@ -11049,50 +11047,7 @@ class BaseInput extends AuroElement {
11049
11047
  * @returns {Date|undefined}
11050
11048
  */
11051
11049
  get maxObject() {
11052
- return this._maxObject || this._computeDateObjectFallback(this.max);
11053
- }
11054
-
11055
- /**
11056
- * Parses a date string into a Date object when the corresponding `_*Object`
11057
- * field hasn't been synced yet by `updated()`. Returns undefined when the
11058
- * input type/format isn't a full date or the string is not a valid date.
11059
- *
11060
- * Why this exists: a parent (datepicker) can call `inputN.validate()` from
11061
- * inside its own `updated()` before this input's `updated()` has run
11062
- * `syncDateValues()` — so `_valueObject`/`_maxObject` are still `undefined`
11063
- * and range checks would otherwise silently no-op (flipping the result to
11064
- * `valid` or `patternMismatch`).
11065
- * @private
11066
- * @param {string|undefined} dateStr - ISO date string from `value`/`min`/`max`.
11067
- * @returns {Date|undefined}
11068
- */
11069
- _computeDateObjectFallback(dateStr) {
11070
- if (!dateStr || !this.util || !this.util.isFullDateFormat(this.type, this.format)) {
11071
- return undefined;
11072
- }
11073
- if (!dateFormatter.isValidDate(dateStr)) {
11074
- return undefined;
11075
- }
11076
- return dateFormatter.stringToDateInstance(dateStr);
11077
- }
11078
-
11079
- /**
11080
- * Internal setter for readonly date object properties.
11081
- * @private
11082
- * @param {'valueObject'|'minObject'|'maxObject'} propertyName - Public object property name.
11083
- * @param {Date|undefined} propertyValue - Value to assign.
11084
- * @returns {void}
11085
- */
11086
- setDateObjectProperty(propertyName, propertyValue) {
11087
- const internalPropertyName = `_${propertyName}`;
11088
- const previousValue = this[internalPropertyName];
11089
-
11090
- if (previousValue === propertyValue) {
11091
- return;
11092
- }
11093
-
11094
- this[internalPropertyName] = propertyValue;
11095
- this.requestUpdate(propertyName, previousValue);
11050
+ return this.max && dateFormatter.isValidDate(this.max) ? dateFormatter.stringToDateInstance(this.max) : undefined;
11096
11051
  }
11097
11052
 
11098
11053
  connectedCallback() {
@@ -11121,7 +11076,6 @@ class BaseInput extends AuroElement {
11121
11076
  format: this.format
11122
11077
  });
11123
11078
  this.configureDataForType();
11124
- this.syncDateValues();
11125
11079
  }
11126
11080
 
11127
11081
  disconnectedCallback() {
@@ -11141,10 +11095,6 @@ class BaseInput extends AuroElement {
11141
11095
  this.wrapperElement.addEventListener('click', this.handleClick);
11142
11096
  }
11143
11097
 
11144
- // add attribute for query selectors when auro-input is registered under a custom name
11145
- if (this.tagName.toLowerCase() !== 'auro-input' && !this.hasAttribute('auro-input')) {
11146
- this.setAttribute('auro-input', '');
11147
- }
11148
11098
  this.inputId = this.id ? `${this.id}-input` : window.crypto.randomUUID();
11149
11099
 
11150
11100
  // use validity message override if declared when initializing the component
@@ -11155,7 +11105,6 @@ class BaseInput extends AuroElement {
11155
11105
  this.setCustomHelpTextMessage();
11156
11106
  this.configureAutoFormatting();
11157
11107
  this.configureDataForType();
11158
- this.syncDateValues();
11159
11108
  }
11160
11109
 
11161
11110
  /**
@@ -11292,8 +11241,6 @@ class BaseInput extends AuroElement {
11292
11241
  this.configureDataForType();
11293
11242
  }
11294
11243
 
11295
- this.syncDateValues(changedProperties);
11296
-
11297
11244
  if (changedProperties.has('value')) {
11298
11245
  if (this.value && this.value.length > 0) {
11299
11246
  this.hasValue = true;
@@ -11315,14 +11262,14 @@ class BaseInput extends AuroElement {
11315
11262
 
11316
11263
  if (formattedValue !== this.inputElement.value) {
11317
11264
  this.skipNextProgrammaticInputEvent = true;
11318
- if (this.maskInstance && this.type === 'credit-card') {
11265
+ if (this.maskInstance && this.type !== 'date') {
11319
11266
  // Route through the mask so its _value and el.value stay in lock-step
11320
11267
  // (set value calls updateControl which writes el.value = displayValue).
11321
11268
  // Writing el.value directly leaves the mask thinking displayValue is
11322
- // stale; _saveSelection on the next focus/click then warns. Scoped to
11323
- // credit-card so date's own formattedValue (raw ISO when calendar-invalid)
11324
- // isn't re-masked through the mm/dd/yyyy mask, which would truncate it
11325
- // and flip validity from patternMismatch to tooShort.
11269
+ // stale; _saveSelection on the next focus/click then warns. Date is
11270
+ // excluded because its formattedValue can be raw ISO when the calendar
11271
+ // is invalid, and re-masking through mm/dd/yyyy would truncate it and
11272
+ // flip validity from patternMismatch to tooShort.
11326
11273
  this.maskInstance.value = formattedValue || '';
11327
11274
  } else if (formattedValue) {
11328
11275
  this.inputElement.value = formattedValue;
@@ -11364,120 +11311,60 @@ class BaseInput extends AuroElement {
11364
11311
  }));
11365
11312
  }
11366
11313
 
11367
-
11368
- /**
11369
- * Synchronizes the ISO string values and Date object representations for date-related properties.
11370
- * This keeps the model and display values aligned when either side changes.
11371
- *
11372
- * When a full date format is in use, this method updates `value`, `min`, and `max` from their corresponding
11373
- * Date objects or vice versa, based on which properties have changed. It only runs when the current configuration
11374
- * represents a full year/month/day date format.
11375
- *
11376
- * @param {Map<string, unknown>|undefined} [changedProperties=undefined] - Optional map of changed properties used to limit which values are synchronized.
11377
- * @returns {void}
11378
- * @private
11379
- */
11380
- syncDateValues(changedProperties = undefined) {
11381
- if (!this.util.isFullDateFormat(this.type, this.format)) {
11382
- return;
11383
- }
11384
-
11385
- this.syncSingleDateValue(changedProperties, 'valueObject', 'value');
11386
- this.syncSingleDateValue(changedProperties, 'minObject', 'min');
11387
- this.syncSingleDateValue(changedProperties, 'maxObject', 'max');
11388
- }
11389
-
11390
- /**
11391
- * Synchronizes one date object/string property pair.
11392
- * @private
11393
- * @param {Map<string, unknown>|undefined} changedProperties - Map of changed properties from Lit.
11394
- * @param {string} objectProperty - Date object property name.
11395
- * @param {string} valueProperty - ISO string property name.
11396
- * @returns {void}
11397
- */
11398
- syncSingleDateValue(changedProperties, objectProperty, valueProperty) {
11399
- const objectPropertyChanged = !changedProperties || changedProperties.has(objectProperty);
11400
-
11401
- // objectProperty wins over valueProperty when both changed
11402
- if (objectPropertyChanged && this[objectProperty]) {
11403
- this[valueProperty] = dateFormatter.toISOFormatString(this[objectProperty]);
11404
- return;
11405
- }
11406
-
11407
- const valuePropertyChanged = !changedProperties || changedProperties.has(valueProperty);
11408
- if (!valuePropertyChanged) {
11409
- return;
11410
- }
11411
-
11412
- // 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)
11413
- if (
11414
- changedProperties &&
11415
- valueProperty === 'value' &&
11416
- changedProperties.get('value') === undefined &&
11417
- this[objectProperty] instanceof Date &&
11418
- this[valueProperty] === dateFormatter.toISOFormatString(this[objectProperty])
11419
- ) {
11420
- return;
11421
- }
11422
-
11423
- if (dateFormatter.isValidDate(this[valueProperty])) {
11424
- this.setDateObjectProperty(objectProperty, dateFormatter.stringToDateInstance(this[valueProperty]));
11425
- } else {
11426
- this.setDateObjectProperty(objectProperty, undefined);
11427
- }
11428
- }
11429
-
11430
11314
  /**
11431
11315
  * Sets up IMasks and logic based on auto-formatting requirements.
11432
11316
  * @private
11433
11317
  * @returns {void}
11434
11318
  */
11435
11319
  configureAutoFormatting() {
11436
- // Re-entrancy guard. The patched-setter's synthetic input event (suppressed
11437
- // by _configuringMask above) could otherwise trigger handleInput
11438
- // processCreditCard configureAutoFormatting before the outer call's
11439
- // set value has finished its alignCursor pass.
11320
+ // _configuringMask gates two things: external re-entry into this method
11321
+ // while setup is mid-flight (from property changes that call back here),
11322
+ // and the accept/complete listeners below — both need to ignore the mask
11323
+ // events fired by our own value-restore step.
11440
11324
  if (this._configuringMask) return;
11441
11325
  this._configuringMask = true;
11442
11326
  try {
11327
+ // Destroy any prior mask so IMask can attach fresh under the new format.
11443
11328
  if (this.maskInstance) {
11444
11329
  this.maskInstance.destroy();
11445
11330
  }
11446
11331
 
11447
- // Pass new format to util
11448
11332
  this.util.updateFormat(this.format);
11449
11333
 
11450
11334
  const maskOptions = this.util.getMaskOptions(this.type, this.format);
11451
11335
 
11452
11336
  if (this.inputElement && maskOptions.mask) {
11453
-
11454
- // Stash and clear any existing value before IMask init.
11455
- // IMask's constructor processes the current input value which requires
11456
- // selection state clearing first avoids that scenario entirely.
11457
- // When the format changes (e.g. locale switch) and we have a valid ISO
11458
- // model value, compute the display string for the NEW format instead of
11459
- // re-using the old display string, which may be invalid in the new mask.
11337
+ // Capture the current display so it can be re-applied after IMask
11338
+ // attaches. The restore at the bottom goes through maskInstance.value
11339
+ // (not inputElement.value directly) so the mask's internal state and
11340
+ // the input's displayed text stay in lock-step.
11460
11341
  let existingValue = this.inputElement.value;
11342
+
11343
+ // Format-change case (e.g. locale switch): existingValue is the OLD
11344
+ // mask's display string and may not parse under the new mask. When
11345
+ // we have a valid date model, rebuild the display from valueObject
11346
+ // (the canonical source) using the new mask's format function.
11461
11347
  if (
11462
11348
  this.util.isFullDateFormat(this.type, this.format) &&
11463
11349
  this.value &&
11464
- dateFormatter.isValidDate(this.value) &&
11465
- this.valueObject instanceof Date &&
11466
- !Number.isNaN(this.valueObject.getTime()) &&
11350
+ this.valueObject &&
11467
11351
  typeof maskOptions.format === 'function'
11468
11352
  ) {
11469
11353
  existingValue = maskOptions.format(this.valueObject);
11470
11354
  }
11471
11355
 
11356
+ // Clear before IMask attaches so the constructor seeds an empty
11357
+ // internal value. Otherwise IMask reads the stale unmasked string
11358
+ // and emits a spurious 'accept' before the restore below runs.
11472
11359
  this.skipNextProgrammaticInputEvent = true;
11473
11360
  this.inputElement.value = '';
11474
11361
 
11475
11362
  this.maskInstance = IMask(this.inputElement, maskOptions);
11476
11363
 
11364
+ // Mask fires 'accept' on every value change, including the restore
11365
+ // step below. Skip events fired during configureAutoFormatting so
11366
+ // we don't overwrite a value the parent just pushed.
11477
11367
  this.maskInstance.on('accept', () => {
11478
- // Suppress propagation during configureAutoFormatting's own value-restoration
11479
- // (line below) — the mask emits 'accept' on every value-set, including ours,
11480
- // and we don't want to overwrite a value the parent just pushed.
11481
11368
  if (this._configuringMask) return;
11482
11369
  this.value = this.util.toModelValue(this.maskInstance.value, this.format);
11483
11370
  if (this.type === "date") {
@@ -11485,6 +11372,8 @@ class BaseInput extends AuroElement {
11485
11372
  }
11486
11373
  });
11487
11374
 
11375
+ // Mask fires 'complete' on the restore step below for any value that
11376
+ // happens to be a complete match. Same setup-suppression as 'accept'.
11488
11377
  this.maskInstance.on('complete', () => {
11489
11378
  if (this._configuringMask) return;
11490
11379
  this.value = this.util.toModelValue(this.maskInstance.value, this.format);
@@ -11493,7 +11382,9 @@ class BaseInput extends AuroElement {
11493
11382
  }
11494
11383
  });
11495
11384
 
11496
- // Restore the stashed value through IMask so it's properly masked
11385
+ // Write existingValue through the mask (not the input directly) so
11386
+ // the mask reformats it under the new rules and keeps its internal
11387
+ // _value aligned with the input's displayed text.
11497
11388
  if (existingValue) {
11498
11389
  this.maskInstance.value = existingValue;
11499
11390
  }
@@ -11661,7 +11552,6 @@ class BaseInput extends AuroElement {
11661
11552
  */
11662
11553
  reset() {
11663
11554
  this.value = undefined;
11664
- this.setDateObjectProperty('valueObject', undefined);
11665
11555
  this.validation.reset(this);
11666
11556
  }
11667
11557
 
@@ -11670,7 +11560,6 @@ class BaseInput extends AuroElement {
11670
11560
  */
11671
11561
  clear() {
11672
11562
  this.value = undefined;
11673
- this.setDateObjectProperty('valueObject', undefined);
11674
11563
  }
11675
11564
 
11676
11565
  /**
@@ -12199,7 +12088,7 @@ class AuroHelpText extends LitElement {
12199
12088
  }
12200
12089
  }
12201
12090
 
12202
- var formkitVersion = '202606171946';
12091
+ var formkitVersion = '202606192004';
12203
12092
 
12204
12093
  // Copyright (c) 2025 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
12205
12094
  // See LICENSE in the project root for license information.