@aurodesignsystem-dev/auro-formkit 0.0.0-pr1506.1 → 0.0.0-pr1507.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (49) 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 +268 -140
  7. package/components/combobox/demo/getting-started.min.js +268 -140
  8. package/components/combobox/demo/index.min.js +268 -140
  9. package/components/combobox/dist/auro-combobox.d.ts +0 -9
  10. package/components/combobox/dist/index.js +266 -138
  11. package/components/combobox/dist/registered.js +266 -138
  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/customize.min.js +149 -39
  17. package/components/datepicker/demo/index.min.js +149 -39
  18. package/components/datepicker/dist/index.js +149 -39
  19. package/components/datepicker/dist/registered.js +149 -39
  20. package/components/dropdown/demo/customize.min.js +1 -1
  21. package/components/dropdown/demo/getting-started.min.js +1 -1
  22. package/components/dropdown/demo/index.min.js +1 -1
  23. package/components/dropdown/dist/index.js +1 -1
  24. package/components/dropdown/dist/registered.js +1 -1
  25. package/components/form/demo/customize.min.js +570 -221
  26. package/components/form/demo/getting-started.min.js +570 -221
  27. package/components/form/demo/index.min.js +570 -221
  28. package/components/form/demo/registerDemoDeps.min.js +570 -221
  29. package/components/input/demo/customize.min.js +147 -36
  30. package/components/input/demo/getting-started.min.js +147 -36
  31. package/components/input/demo/index.min.js +147 -36
  32. package/components/input/dist/base-input.d.ts +48 -0
  33. package/components/input/dist/index.js +147 -36
  34. package/components/input/dist/registered.js +147 -36
  35. package/components/menu/demo/index.min.js +2 -2
  36. package/components/menu/dist/index.js +2 -2
  37. package/components/menu/dist/registered.js +2 -2
  38. package/components/radio/demo/customize.min.js +1 -1
  39. package/components/radio/demo/getting-started.min.js +1 -1
  40. package/components/radio/demo/index.min.js +1 -1
  41. package/components/radio/dist/index.js +1 -1
  42. package/components/radio/dist/registered.js +1 -1
  43. package/components/select/demo/customize.min.js +4 -4
  44. package/components/select/demo/getting-started.min.js +4 -4
  45. package/components/select/demo/index.min.js +4 -4
  46. package/components/select/dist/index.js +2 -2
  47. package/components/select/dist/registered.js +2 -2
  48. package/custom-elements.json +264 -20
  49. package/package.json +1 -1
@@ -10389,7 +10389,6 @@ class AuroInputUtilities {
10389
10389
  const maskOptions = this.getMaskOptions('date', normalizedFormat);
10390
10390
 
10391
10391
  if (!(valueObject instanceof Date) || Number.isNaN(valueObject.getTime()) || !maskOptions || typeof maskOptions.format !== 'function') {
10392
- console.debug('Invalid date object or mask options for formatting', { valueObject, maskOptions }); // eslint-disable-line no-console
10393
10392
  return undefined;
10394
10393
  }
10395
10394
 
@@ -10541,8 +10540,10 @@ class BaseInput extends AuroElement {
10541
10540
  this.layout = 'classic';
10542
10541
  this.locale = 'en-US';
10543
10542
  this.max = undefined;
10543
+ this._maxObject = undefined;
10544
10544
  this.maxLength = undefined;
10545
10545
  this.min = undefined;
10546
+ this._minObject = undefined;
10546
10547
  this.minLength = undefined;
10547
10548
  this.required = false;
10548
10549
  this.onDark = false;
@@ -10550,6 +10551,7 @@ class BaseInput extends AuroElement {
10550
10551
  this.size = 'lg';
10551
10552
  this.shape = 'classic';
10552
10553
  this.value = undefined;
10554
+ this._valueObject = undefined;
10553
10555
 
10554
10556
  this._initializePrivateDefaults();
10555
10557
  }
@@ -11089,7 +11091,7 @@ class BaseInput extends AuroElement {
11089
11091
  * @returns {Date|undefined}
11090
11092
  */
11091
11093
  get valueObject() {
11092
- return this.value && dateFormatter.isValidDate(this.value) ? dateFormatter.stringToDateInstance(this.value) : undefined;
11094
+ return this._valueObject || this._computeDateObjectFallback(this.value);
11093
11095
  }
11094
11096
 
11095
11097
  /**
@@ -11097,7 +11099,7 @@ class BaseInput extends AuroElement {
11097
11099
  * @returns {Date|undefined}
11098
11100
  */
11099
11101
  get minObject() {
11100
- return this.min && dateFormatter.isValidDate(this.min) ? dateFormatter.stringToDateInstance(this.min) : undefined;
11102
+ return this._minObject || this._computeDateObjectFallback(this.min);
11101
11103
  }
11102
11104
 
11103
11105
  /**
@@ -11105,7 +11107,50 @@ class BaseInput extends AuroElement {
11105
11107
  * @returns {Date|undefined}
11106
11108
  */
11107
11109
  get maxObject() {
11108
- return this.max && dateFormatter.isValidDate(this.max) ? dateFormatter.stringToDateInstance(this.max) : undefined;
11110
+ return this._maxObject || this._computeDateObjectFallback(this.max);
11111
+ }
11112
+
11113
+ /**
11114
+ * Parses a date string into a Date object when the corresponding `_*Object`
11115
+ * field hasn't been synced yet by `updated()`. Returns undefined when the
11116
+ * input type/format isn't a full date or the string is not a valid date.
11117
+ *
11118
+ * Why this exists: a parent (datepicker) can call `inputN.validate()` from
11119
+ * inside its own `updated()` before this input's `updated()` has run
11120
+ * `syncDateValues()` — so `_valueObject`/`_maxObject` are still `undefined`
11121
+ * and range checks would otherwise silently no-op (flipping the result to
11122
+ * `valid` or `patternMismatch`).
11123
+ * @private
11124
+ * @param {string|undefined} dateStr - ISO date string from `value`/`min`/`max`.
11125
+ * @returns {Date|undefined}
11126
+ */
11127
+ _computeDateObjectFallback(dateStr) {
11128
+ if (!dateStr || !this.util || !this.util.isFullDateFormat(this.type, this.format)) {
11129
+ return undefined;
11130
+ }
11131
+ if (!dateFormatter.isValidDate(dateStr)) {
11132
+ return undefined;
11133
+ }
11134
+ return dateFormatter.stringToDateInstance(dateStr);
11135
+ }
11136
+
11137
+ /**
11138
+ * Internal setter for readonly date object properties.
11139
+ * @private
11140
+ * @param {'valueObject'|'minObject'|'maxObject'} propertyName - Public object property name.
11141
+ * @param {Date|undefined} propertyValue - Value to assign.
11142
+ * @returns {void}
11143
+ */
11144
+ setDateObjectProperty(propertyName, propertyValue) {
11145
+ const internalPropertyName = `_${propertyName}`;
11146
+ const previousValue = this[internalPropertyName];
11147
+
11148
+ if (previousValue === propertyValue) {
11149
+ return;
11150
+ }
11151
+
11152
+ this[internalPropertyName] = propertyValue;
11153
+ this.requestUpdate(propertyName, previousValue);
11109
11154
  }
11110
11155
 
11111
11156
  connectedCallback() {
@@ -11134,6 +11179,7 @@ class BaseInput extends AuroElement {
11134
11179
  format: this.format
11135
11180
  });
11136
11181
  this.configureDataForType();
11182
+ this.syncDateValues();
11137
11183
  }
11138
11184
 
11139
11185
  disconnectedCallback() {
@@ -11153,6 +11199,10 @@ class BaseInput extends AuroElement {
11153
11199
  this.wrapperElement.addEventListener('click', this.handleClick);
11154
11200
  }
11155
11201
 
11202
+ // add attribute for query selectors when auro-input is registered under a custom name
11203
+ if (this.tagName.toLowerCase() !== 'auro-input' && !this.hasAttribute('auro-input')) {
11204
+ this.setAttribute('auro-input', '');
11205
+ }
11156
11206
  this.inputId = this.id ? `${this.id}-input` : window.crypto.randomUUID();
11157
11207
 
11158
11208
  // use validity message override if declared when initializing the component
@@ -11163,6 +11213,7 @@ class BaseInput extends AuroElement {
11163
11213
  this.setCustomHelpTextMessage();
11164
11214
  this.configureAutoFormatting();
11165
11215
  this.configureDataForType();
11216
+ this.syncDateValues();
11166
11217
  }
11167
11218
 
11168
11219
  /**
@@ -11299,6 +11350,8 @@ class BaseInput extends AuroElement {
11299
11350
  this.configureDataForType();
11300
11351
  }
11301
11352
 
11353
+ this.syncDateValues(changedProperties);
11354
+
11302
11355
  if (changedProperties.has('value')) {
11303
11356
  if (this.value && this.value.length > 0) {
11304
11357
  this.hasValue = true;
@@ -11320,14 +11373,14 @@ class BaseInput extends AuroElement {
11320
11373
 
11321
11374
  if (formattedValue !== this.inputElement.value) {
11322
11375
  this.skipNextProgrammaticInputEvent = true;
11323
- if (this.maskInstance && this.type !== 'date') {
11376
+ if (this.maskInstance && this.type === 'credit-card') {
11324
11377
  // Route through the mask so its _value and el.value stay in lock-step
11325
11378
  // (set value calls updateControl which writes el.value = displayValue).
11326
11379
  // Writing el.value directly leaves the mask thinking displayValue is
11327
- // stale; _saveSelection on the next focus/click then warns. Date is
11328
- // excluded because its formattedValue can be raw ISO when the calendar
11329
- // is invalid, and re-masking through mm/dd/yyyy would truncate it and
11330
- // flip validity from patternMismatch to tooShort.
11380
+ // stale; _saveSelection on the next focus/click then warns. Scoped to
11381
+ // credit-card so date's own formattedValue (raw ISO when calendar-invalid)
11382
+ // isn't re-masked through the mm/dd/yyyy mask, which would truncate it
11383
+ // and flip validity from patternMismatch to tooShort.
11331
11384
  this.maskInstance.value = formattedValue || '';
11332
11385
  } else if (formattedValue) {
11333
11386
  this.inputElement.value = formattedValue;
@@ -11369,60 +11422,120 @@ class BaseInput extends AuroElement {
11369
11422
  }));
11370
11423
  }
11371
11424
 
11425
+
11426
+ /**
11427
+ * Synchronizes the ISO string values and Date object representations for date-related properties.
11428
+ * This keeps the model and display values aligned when either side changes.
11429
+ *
11430
+ * When a full date format is in use, this method updates `value`, `min`, and `max` from their corresponding
11431
+ * Date objects or vice versa, based on which properties have changed. It only runs when the current configuration
11432
+ * represents a full year/month/day date format.
11433
+ *
11434
+ * @param {Map<string, unknown>|undefined} [changedProperties=undefined] - Optional map of changed properties used to limit which values are synchronized.
11435
+ * @returns {void}
11436
+ * @private
11437
+ */
11438
+ syncDateValues(changedProperties = undefined) {
11439
+ if (!this.util.isFullDateFormat(this.type, this.format)) {
11440
+ return;
11441
+ }
11442
+
11443
+ this.syncSingleDateValue(changedProperties, 'valueObject', 'value');
11444
+ this.syncSingleDateValue(changedProperties, 'minObject', 'min');
11445
+ this.syncSingleDateValue(changedProperties, 'maxObject', 'max');
11446
+ }
11447
+
11448
+ /**
11449
+ * Synchronizes one date object/string property pair.
11450
+ * @private
11451
+ * @param {Map<string, unknown>|undefined} changedProperties - Map of changed properties from Lit.
11452
+ * @param {string} objectProperty - Date object property name.
11453
+ * @param {string} valueProperty - ISO string property name.
11454
+ * @returns {void}
11455
+ */
11456
+ syncSingleDateValue(changedProperties, objectProperty, valueProperty) {
11457
+ const objectPropertyChanged = !changedProperties || changedProperties.has(objectProperty);
11458
+
11459
+ // objectProperty wins over valueProperty when both changed
11460
+ if (objectPropertyChanged && this[objectProperty]) {
11461
+ this[valueProperty] = dateFormatter.toISOFormatString(this[objectProperty]);
11462
+ return;
11463
+ }
11464
+
11465
+ const valuePropertyChanged = !changedProperties || changedProperties.has(valueProperty);
11466
+ if (!valuePropertyChanged) {
11467
+ return;
11468
+ }
11469
+
11470
+ // 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)
11471
+ if (
11472
+ changedProperties &&
11473
+ valueProperty === 'value' &&
11474
+ changedProperties.get('value') === undefined &&
11475
+ this[objectProperty] instanceof Date &&
11476
+ this[valueProperty] === dateFormatter.toISOFormatString(this[objectProperty])
11477
+ ) {
11478
+ return;
11479
+ }
11480
+
11481
+ if (dateFormatter.isValidDate(this[valueProperty])) {
11482
+ this.setDateObjectProperty(objectProperty, dateFormatter.stringToDateInstance(this[valueProperty]));
11483
+ } else {
11484
+ this.setDateObjectProperty(objectProperty, undefined);
11485
+ }
11486
+ }
11487
+
11372
11488
  /**
11373
11489
  * Sets up IMasks and logic based on auto-formatting requirements.
11374
11490
  * @private
11375
11491
  * @returns {void}
11376
11492
  */
11377
11493
  configureAutoFormatting() {
11378
- // _configuringMask gates two things: external re-entry into this method
11379
- // while setup is mid-flight (from property changes that call back here),
11380
- // and the accept/complete listeners below both need to ignore the mask
11381
- // events fired by our own value-restore step.
11494
+ // Re-entrancy guard. The patched-setter's synthetic input event (suppressed
11495
+ // by _configuringMask above) could otherwise trigger handleInput
11496
+ // processCreditCard configureAutoFormatting before the outer call's
11497
+ // set value has finished its alignCursor pass.
11382
11498
  if (this._configuringMask) return;
11383
11499
  this._configuringMask = true;
11384
11500
  try {
11385
- // Destroy any prior mask so IMask can attach fresh under the new format.
11386
11501
  if (this.maskInstance) {
11387
11502
  this.maskInstance.destroy();
11388
11503
  }
11389
11504
 
11505
+ // Pass new format to util
11390
11506
  this.util.updateFormat(this.format);
11391
11507
 
11392
11508
  const maskOptions = this.util.getMaskOptions(this.type, this.format);
11393
11509
 
11394
11510
  if (this.inputElement && maskOptions.mask) {
11395
- // Capture the current display so it can be re-applied after IMask
11396
- // attaches. The restore at the bottom goes through maskInstance.value
11397
- // (not inputElement.value directly) so the mask's internal state and
11398
- // the input's displayed text stay in lock-step.
11399
- let existingValue = this.inputElement.value;
11400
11511
 
11401
- // Format-change case (e.g. locale switch): existingValue is the OLD
11402
- // mask's display string and may not parse under the new mask. When
11403
- // we have a valid date model, rebuild the display from valueObject
11404
- // (the canonical source) using the new mask's format function.
11512
+ // Stash and clear any existing value before IMask init.
11513
+ // IMask's constructor processes the current input value which requires
11514
+ // selection state clearing first avoids that scenario entirely.
11515
+ // When the format changes (e.g. locale switch) and we have a valid ISO
11516
+ // model value, compute the display string for the NEW format instead of
11517
+ // re-using the old display string, which may be invalid in the new mask.
11518
+ let existingValue = this.inputElement.value;
11405
11519
  if (
11406
11520
  this.util.isFullDateFormat(this.type, this.format) &&
11407
11521
  this.value &&
11408
- this.valueObject &&
11522
+ dateFormatter.isValidDate(this.value) &&
11523
+ this.valueObject instanceof Date &&
11524
+ !Number.isNaN(this.valueObject.getTime()) &&
11409
11525
  typeof maskOptions.format === 'function'
11410
11526
  ) {
11411
11527
  existingValue = maskOptions.format(this.valueObject);
11412
11528
  }
11413
11529
 
11414
- // Clear before IMask attaches so the constructor seeds an empty
11415
- // internal value. Otherwise IMask reads the stale unmasked string
11416
- // and emits a spurious 'accept' before the restore below runs.
11417
11530
  this.skipNextProgrammaticInputEvent = true;
11418
11531
  this.inputElement.value = '';
11419
11532
 
11420
11533
  this.maskInstance = IMask(this.inputElement, maskOptions);
11421
11534
 
11422
- // Mask fires 'accept' on every value change, including the restore
11423
- // step below. Skip events fired during configureAutoFormatting so
11424
- // we don't overwrite a value the parent just pushed.
11425
11535
  this.maskInstance.on('accept', () => {
11536
+ // Suppress propagation during configureAutoFormatting's own value-restoration
11537
+ // (line below) — the mask emits 'accept' on every value-set, including ours,
11538
+ // and we don't want to overwrite a value the parent just pushed.
11426
11539
  if (this._configuringMask) return;
11427
11540
  this.value = this.util.toModelValue(this.maskInstance.value, this.format);
11428
11541
  if (this.type === "date") {
@@ -11430,8 +11543,6 @@ class BaseInput extends AuroElement {
11430
11543
  }
11431
11544
  });
11432
11545
 
11433
- // Mask fires 'complete' on the restore step below for any value that
11434
- // happens to be a complete match. Same setup-suppression as 'accept'.
11435
11546
  this.maskInstance.on('complete', () => {
11436
11547
  if (this._configuringMask) return;
11437
11548
  this.value = this.util.toModelValue(this.maskInstance.value, this.format);
@@ -11440,9 +11551,7 @@ class BaseInput extends AuroElement {
11440
11551
  }
11441
11552
  });
11442
11553
 
11443
- // Write existingValue through the mask (not the input directly) so
11444
- // the mask reformats it under the new rules and keeps its internal
11445
- // _value aligned with the input's displayed text.
11554
+ // Restore the stashed value through IMask so it's properly masked
11446
11555
  if (existingValue) {
11447
11556
  this.maskInstance.value = existingValue;
11448
11557
  }
@@ -11610,6 +11719,7 @@ class BaseInput extends AuroElement {
11610
11719
  */
11611
11720
  reset() {
11612
11721
  this.value = undefined;
11722
+ this.setDateObjectProperty('valueObject', undefined);
11613
11723
  this.validation.reset(this);
11614
11724
  }
11615
11725
 
@@ -11618,6 +11728,7 @@ class BaseInput extends AuroElement {
11618
11728
  */
11619
11729
  clear() {
11620
11730
  this.value = undefined;
11731
+ this.setDateObjectProperty('valueObject', undefined);
11621
11732
  }
11622
11733
 
11623
11734
  /**
@@ -12146,7 +12257,7 @@ class AuroHelpText extends i$3 {
12146
12257
  }
12147
12258
  }
12148
12259
 
12149
- var formkitVersion = '202606192004';
12260
+ var formkitVersion = '202606192121';
12150
12261
 
12151
12262
  /**
12152
12263
  * @license
@@ -10389,7 +10389,6 @@ class AuroInputUtilities {
10389
10389
  const maskOptions = this.getMaskOptions('date', normalizedFormat);
10390
10390
 
10391
10391
  if (!(valueObject instanceof Date) || Number.isNaN(valueObject.getTime()) || !maskOptions || typeof maskOptions.format !== 'function') {
10392
- console.debug('Invalid date object or mask options for formatting', { valueObject, maskOptions }); // eslint-disable-line no-console
10393
10392
  return undefined;
10394
10393
  }
10395
10394
 
@@ -10541,8 +10540,10 @@ class BaseInput extends AuroElement {
10541
10540
  this.layout = 'classic';
10542
10541
  this.locale = 'en-US';
10543
10542
  this.max = undefined;
10543
+ this._maxObject = undefined;
10544
10544
  this.maxLength = undefined;
10545
10545
  this.min = undefined;
10546
+ this._minObject = undefined;
10546
10547
  this.minLength = undefined;
10547
10548
  this.required = false;
10548
10549
  this.onDark = false;
@@ -10550,6 +10551,7 @@ class BaseInput extends AuroElement {
10550
10551
  this.size = 'lg';
10551
10552
  this.shape = 'classic';
10552
10553
  this.value = undefined;
10554
+ this._valueObject = undefined;
10553
10555
 
10554
10556
  this._initializePrivateDefaults();
10555
10557
  }
@@ -11089,7 +11091,7 @@ class BaseInput extends AuroElement {
11089
11091
  * @returns {Date|undefined}
11090
11092
  */
11091
11093
  get valueObject() {
11092
- return this.value && dateFormatter.isValidDate(this.value) ? dateFormatter.stringToDateInstance(this.value) : undefined;
11094
+ return this._valueObject || this._computeDateObjectFallback(this.value);
11093
11095
  }
11094
11096
 
11095
11097
  /**
@@ -11097,7 +11099,7 @@ class BaseInput extends AuroElement {
11097
11099
  * @returns {Date|undefined}
11098
11100
  */
11099
11101
  get minObject() {
11100
- return this.min && dateFormatter.isValidDate(this.min) ? dateFormatter.stringToDateInstance(this.min) : undefined;
11102
+ return this._minObject || this._computeDateObjectFallback(this.min);
11101
11103
  }
11102
11104
 
11103
11105
  /**
@@ -11105,7 +11107,50 @@ class BaseInput extends AuroElement {
11105
11107
  * @returns {Date|undefined}
11106
11108
  */
11107
11109
  get maxObject() {
11108
- return this.max && dateFormatter.isValidDate(this.max) ? dateFormatter.stringToDateInstance(this.max) : undefined;
11110
+ return this._maxObject || this._computeDateObjectFallback(this.max);
11111
+ }
11112
+
11113
+ /**
11114
+ * Parses a date string into a Date object when the corresponding `_*Object`
11115
+ * field hasn't been synced yet by `updated()`. Returns undefined when the
11116
+ * input type/format isn't a full date or the string is not a valid date.
11117
+ *
11118
+ * Why this exists: a parent (datepicker) can call `inputN.validate()` from
11119
+ * inside its own `updated()` before this input's `updated()` has run
11120
+ * `syncDateValues()` — so `_valueObject`/`_maxObject` are still `undefined`
11121
+ * and range checks would otherwise silently no-op (flipping the result to
11122
+ * `valid` or `patternMismatch`).
11123
+ * @private
11124
+ * @param {string|undefined} dateStr - ISO date string from `value`/`min`/`max`.
11125
+ * @returns {Date|undefined}
11126
+ */
11127
+ _computeDateObjectFallback(dateStr) {
11128
+ if (!dateStr || !this.util || !this.util.isFullDateFormat(this.type, this.format)) {
11129
+ return undefined;
11130
+ }
11131
+ if (!dateFormatter.isValidDate(dateStr)) {
11132
+ return undefined;
11133
+ }
11134
+ return dateFormatter.stringToDateInstance(dateStr);
11135
+ }
11136
+
11137
+ /**
11138
+ * Internal setter for readonly date object properties.
11139
+ * @private
11140
+ * @param {'valueObject'|'minObject'|'maxObject'} propertyName - Public object property name.
11141
+ * @param {Date|undefined} propertyValue - Value to assign.
11142
+ * @returns {void}
11143
+ */
11144
+ setDateObjectProperty(propertyName, propertyValue) {
11145
+ const internalPropertyName = `_${propertyName}`;
11146
+ const previousValue = this[internalPropertyName];
11147
+
11148
+ if (previousValue === propertyValue) {
11149
+ return;
11150
+ }
11151
+
11152
+ this[internalPropertyName] = propertyValue;
11153
+ this.requestUpdate(propertyName, previousValue);
11109
11154
  }
11110
11155
 
11111
11156
  connectedCallback() {
@@ -11134,6 +11179,7 @@ class BaseInput extends AuroElement {
11134
11179
  format: this.format
11135
11180
  });
11136
11181
  this.configureDataForType();
11182
+ this.syncDateValues();
11137
11183
  }
11138
11184
 
11139
11185
  disconnectedCallback() {
@@ -11153,6 +11199,10 @@ class BaseInput extends AuroElement {
11153
11199
  this.wrapperElement.addEventListener('click', this.handleClick);
11154
11200
  }
11155
11201
 
11202
+ // add attribute for query selectors when auro-input is registered under a custom name
11203
+ if (this.tagName.toLowerCase() !== 'auro-input' && !this.hasAttribute('auro-input')) {
11204
+ this.setAttribute('auro-input', '');
11205
+ }
11156
11206
  this.inputId = this.id ? `${this.id}-input` : window.crypto.randomUUID();
11157
11207
 
11158
11208
  // use validity message override if declared when initializing the component
@@ -11163,6 +11213,7 @@ class BaseInput extends AuroElement {
11163
11213
  this.setCustomHelpTextMessage();
11164
11214
  this.configureAutoFormatting();
11165
11215
  this.configureDataForType();
11216
+ this.syncDateValues();
11166
11217
  }
11167
11218
 
11168
11219
  /**
@@ -11299,6 +11350,8 @@ class BaseInput extends AuroElement {
11299
11350
  this.configureDataForType();
11300
11351
  }
11301
11352
 
11353
+ this.syncDateValues(changedProperties);
11354
+
11302
11355
  if (changedProperties.has('value')) {
11303
11356
  if (this.value && this.value.length > 0) {
11304
11357
  this.hasValue = true;
@@ -11320,14 +11373,14 @@ class BaseInput extends AuroElement {
11320
11373
 
11321
11374
  if (formattedValue !== this.inputElement.value) {
11322
11375
  this.skipNextProgrammaticInputEvent = true;
11323
- if (this.maskInstance && this.type !== 'date') {
11376
+ if (this.maskInstance && this.type === 'credit-card') {
11324
11377
  // Route through the mask so its _value and el.value stay in lock-step
11325
11378
  // (set value calls updateControl which writes el.value = displayValue).
11326
11379
  // Writing el.value directly leaves the mask thinking displayValue is
11327
- // stale; _saveSelection on the next focus/click then warns. Date is
11328
- // excluded because its formattedValue can be raw ISO when the calendar
11329
- // is invalid, and re-masking through mm/dd/yyyy would truncate it and
11330
- // flip validity from patternMismatch to tooShort.
11380
+ // stale; _saveSelection on the next focus/click then warns. Scoped to
11381
+ // credit-card so date's own formattedValue (raw ISO when calendar-invalid)
11382
+ // isn't re-masked through the mm/dd/yyyy mask, which would truncate it
11383
+ // and flip validity from patternMismatch to tooShort.
11331
11384
  this.maskInstance.value = formattedValue || '';
11332
11385
  } else if (formattedValue) {
11333
11386
  this.inputElement.value = formattedValue;
@@ -11369,60 +11422,120 @@ class BaseInput extends AuroElement {
11369
11422
  }));
11370
11423
  }
11371
11424
 
11425
+
11426
+ /**
11427
+ * Synchronizes the ISO string values and Date object representations for date-related properties.
11428
+ * This keeps the model and display values aligned when either side changes.
11429
+ *
11430
+ * When a full date format is in use, this method updates `value`, `min`, and `max` from their corresponding
11431
+ * Date objects or vice versa, based on which properties have changed. It only runs when the current configuration
11432
+ * represents a full year/month/day date format.
11433
+ *
11434
+ * @param {Map<string, unknown>|undefined} [changedProperties=undefined] - Optional map of changed properties used to limit which values are synchronized.
11435
+ * @returns {void}
11436
+ * @private
11437
+ */
11438
+ syncDateValues(changedProperties = undefined) {
11439
+ if (!this.util.isFullDateFormat(this.type, this.format)) {
11440
+ return;
11441
+ }
11442
+
11443
+ this.syncSingleDateValue(changedProperties, 'valueObject', 'value');
11444
+ this.syncSingleDateValue(changedProperties, 'minObject', 'min');
11445
+ this.syncSingleDateValue(changedProperties, 'maxObject', 'max');
11446
+ }
11447
+
11448
+ /**
11449
+ * Synchronizes one date object/string property pair.
11450
+ * @private
11451
+ * @param {Map<string, unknown>|undefined} changedProperties - Map of changed properties from Lit.
11452
+ * @param {string} objectProperty - Date object property name.
11453
+ * @param {string} valueProperty - ISO string property name.
11454
+ * @returns {void}
11455
+ */
11456
+ syncSingleDateValue(changedProperties, objectProperty, valueProperty) {
11457
+ const objectPropertyChanged = !changedProperties || changedProperties.has(objectProperty);
11458
+
11459
+ // objectProperty wins over valueProperty when both changed
11460
+ if (objectPropertyChanged && this[objectProperty]) {
11461
+ this[valueProperty] = dateFormatter.toISOFormatString(this[objectProperty]);
11462
+ return;
11463
+ }
11464
+
11465
+ const valuePropertyChanged = !changedProperties || changedProperties.has(valueProperty);
11466
+ if (!valuePropertyChanged) {
11467
+ return;
11468
+ }
11469
+
11470
+ // 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)
11471
+ if (
11472
+ changedProperties &&
11473
+ valueProperty === 'value' &&
11474
+ changedProperties.get('value') === undefined &&
11475
+ this[objectProperty] instanceof Date &&
11476
+ this[valueProperty] === dateFormatter.toISOFormatString(this[objectProperty])
11477
+ ) {
11478
+ return;
11479
+ }
11480
+
11481
+ if (dateFormatter.isValidDate(this[valueProperty])) {
11482
+ this.setDateObjectProperty(objectProperty, dateFormatter.stringToDateInstance(this[valueProperty]));
11483
+ } else {
11484
+ this.setDateObjectProperty(objectProperty, undefined);
11485
+ }
11486
+ }
11487
+
11372
11488
  /**
11373
11489
  * Sets up IMasks and logic based on auto-formatting requirements.
11374
11490
  * @private
11375
11491
  * @returns {void}
11376
11492
  */
11377
11493
  configureAutoFormatting() {
11378
- // _configuringMask gates two things: external re-entry into this method
11379
- // while setup is mid-flight (from property changes that call back here),
11380
- // and the accept/complete listeners below both need to ignore the mask
11381
- // events fired by our own value-restore step.
11494
+ // Re-entrancy guard. The patched-setter's synthetic input event (suppressed
11495
+ // by _configuringMask above) could otherwise trigger handleInput
11496
+ // processCreditCard configureAutoFormatting before the outer call's
11497
+ // set value has finished its alignCursor pass.
11382
11498
  if (this._configuringMask) return;
11383
11499
  this._configuringMask = true;
11384
11500
  try {
11385
- // Destroy any prior mask so IMask can attach fresh under the new format.
11386
11501
  if (this.maskInstance) {
11387
11502
  this.maskInstance.destroy();
11388
11503
  }
11389
11504
 
11505
+ // Pass new format to util
11390
11506
  this.util.updateFormat(this.format);
11391
11507
 
11392
11508
  const maskOptions = this.util.getMaskOptions(this.type, this.format);
11393
11509
 
11394
11510
  if (this.inputElement && maskOptions.mask) {
11395
- // Capture the current display so it can be re-applied after IMask
11396
- // attaches. The restore at the bottom goes through maskInstance.value
11397
- // (not inputElement.value directly) so the mask's internal state and
11398
- // the input's displayed text stay in lock-step.
11399
- let existingValue = this.inputElement.value;
11400
11511
 
11401
- // Format-change case (e.g. locale switch): existingValue is the OLD
11402
- // mask's display string and may not parse under the new mask. When
11403
- // we have a valid date model, rebuild the display from valueObject
11404
- // (the canonical source) using the new mask's format function.
11512
+ // Stash and clear any existing value before IMask init.
11513
+ // IMask's constructor processes the current input value which requires
11514
+ // selection state clearing first avoids that scenario entirely.
11515
+ // When the format changes (e.g. locale switch) and we have a valid ISO
11516
+ // model value, compute the display string for the NEW format instead of
11517
+ // re-using the old display string, which may be invalid in the new mask.
11518
+ let existingValue = this.inputElement.value;
11405
11519
  if (
11406
11520
  this.util.isFullDateFormat(this.type, this.format) &&
11407
11521
  this.value &&
11408
- this.valueObject &&
11522
+ dateFormatter.isValidDate(this.value) &&
11523
+ this.valueObject instanceof Date &&
11524
+ !Number.isNaN(this.valueObject.getTime()) &&
11409
11525
  typeof maskOptions.format === 'function'
11410
11526
  ) {
11411
11527
  existingValue = maskOptions.format(this.valueObject);
11412
11528
  }
11413
11529
 
11414
- // Clear before IMask attaches so the constructor seeds an empty
11415
- // internal value. Otherwise IMask reads the stale unmasked string
11416
- // and emits a spurious 'accept' before the restore below runs.
11417
11530
  this.skipNextProgrammaticInputEvent = true;
11418
11531
  this.inputElement.value = '';
11419
11532
 
11420
11533
  this.maskInstance = IMask(this.inputElement, maskOptions);
11421
11534
 
11422
- // Mask fires 'accept' on every value change, including the restore
11423
- // step below. Skip events fired during configureAutoFormatting so
11424
- // we don't overwrite a value the parent just pushed.
11425
11535
  this.maskInstance.on('accept', () => {
11536
+ // Suppress propagation during configureAutoFormatting's own value-restoration
11537
+ // (line below) — the mask emits 'accept' on every value-set, including ours,
11538
+ // and we don't want to overwrite a value the parent just pushed.
11426
11539
  if (this._configuringMask) return;
11427
11540
  this.value = this.util.toModelValue(this.maskInstance.value, this.format);
11428
11541
  if (this.type === "date") {
@@ -11430,8 +11543,6 @@ class BaseInput extends AuroElement {
11430
11543
  }
11431
11544
  });
11432
11545
 
11433
- // Mask fires 'complete' on the restore step below for any value that
11434
- // happens to be a complete match. Same setup-suppression as 'accept'.
11435
11546
  this.maskInstance.on('complete', () => {
11436
11547
  if (this._configuringMask) return;
11437
11548
  this.value = this.util.toModelValue(this.maskInstance.value, this.format);
@@ -11440,9 +11551,7 @@ class BaseInput extends AuroElement {
11440
11551
  }
11441
11552
  });
11442
11553
 
11443
- // Write existingValue through the mask (not the input directly) so
11444
- // the mask reformats it under the new rules and keeps its internal
11445
- // _value aligned with the input's displayed text.
11554
+ // Restore the stashed value through IMask so it's properly masked
11446
11555
  if (existingValue) {
11447
11556
  this.maskInstance.value = existingValue;
11448
11557
  }
@@ -11610,6 +11719,7 @@ class BaseInput extends AuroElement {
11610
11719
  */
11611
11720
  reset() {
11612
11721
  this.value = undefined;
11722
+ this.setDateObjectProperty('valueObject', undefined);
11613
11723
  this.validation.reset(this);
11614
11724
  }
11615
11725
 
@@ -11618,6 +11728,7 @@ class BaseInput extends AuroElement {
11618
11728
  */
11619
11729
  clear() {
11620
11730
  this.value = undefined;
11731
+ this.setDateObjectProperty('valueObject', undefined);
11621
11732
  }
11622
11733
 
11623
11734
  /**
@@ -12146,7 +12257,7 @@ class AuroHelpText extends i$3 {
12146
12257
  }
12147
12258
  }
12148
12259
 
12149
- var formkitVersion = '202606192004';
12260
+ var formkitVersion = '202606192121';
12150
12261
 
12151
12262
  /**
12152
12263
  * @license