@aurodesignsystem-dev/auro-formkit 0.0.0-pr1508.0 → 0.0.0-pr1509.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 (46) 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 +293 -141
  7. package/components/combobox/demo/getting-started.min.js +293 -141
  8. package/components/combobox/demo/index.min.js +293 -141
  9. package/components/combobox/dist/auro-combobox.d.ts +0 -9
  10. package/components/combobox/dist/index.js +293 -141
  11. package/components/combobox/dist/registered.js +293 -141
  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 +167 -44
  17. package/components/datepicker/demo/index.min.js +167 -44
  18. package/components/datepicker/dist/index.js +167 -44
  19. package/components/datepicker/dist/registered.js +167 -44
  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 +631 -232
  26. package/components/form/demo/getting-started.min.js +631 -232
  27. package/components/form/demo/index.min.js +631 -232
  28. package/components/form/demo/registerDemoDeps.min.js +631 -232
  29. package/components/input/demo/customize.min.js +165 -41
  30. package/components/input/demo/getting-started.min.js +165 -41
  31. package/components/input/demo/index.min.js +165 -41
  32. package/components/input/dist/base-input.d.ts +49 -1
  33. package/components/input/dist/index.js +165 -41
  34. package/components/input/dist/registered.js +165 -41
  35. package/components/radio/demo/customize.min.js +1 -1
  36. package/components/radio/demo/getting-started.min.js +1 -1
  37. package/components/radio/demo/index.min.js +1 -1
  38. package/components/radio/dist/index.js +1 -1
  39. package/components/radio/dist/registered.js +1 -1
  40. package/components/select/demo/customize.min.js +2 -2
  41. package/components/select/demo/getting-started.min.js +2 -2
  42. package/components/select/demo/index.min.js +2 -2
  43. package/components/select/dist/index.js +2 -2
  44. package/components/select/dist/registered.js +2 -2
  45. package/custom-elements.json +264 -20
  46. 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,15 @@ 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
+ // COVERAGE: the body of this branch is unreachable in WTR — connectedCallback
11204
+ // performs the same `setAttribute('auro-input', '')` earlier (see L665-667),
11205
+ // so by the time firstUpdated runs the attribute is already present and the
11206
+ // `!hasAttribute('auro-input')` guard is false. Retained as a defensive
11207
+ // safety net in case connectedCallback is ever short-circuited.
11208
+ if (this.tagName.toLowerCase() !== 'auro-input' && !this.hasAttribute('auro-input')) {
11209
+ this.setAttribute('auro-input', '');
11210
+ }
11156
11211
  this.inputId = this.id ? `${this.id}-input` : window.crypto.randomUUID();
11157
11212
 
11158
11213
  // use validity message override if declared when initializing the component
@@ -11163,6 +11218,7 @@ class BaseInput extends AuroElement {
11163
11218
  this.setCustomHelpTextMessage();
11164
11219
  this.configureAutoFormatting();
11165
11220
  this.configureDataForType();
11221
+ this.syncDateValues();
11166
11222
  }
11167
11223
 
11168
11224
  /**
@@ -11238,6 +11294,13 @@ class BaseInput extends AuroElement {
11238
11294
 
11239
11295
  if (typeToI18n.includes(this.type)) {
11240
11296
  this.setCustomValidityForType = i18n(this.lang, this.type);
11297
+ // COVERAGE: this `else if` branch is unreachable in WTR. connectedCallback
11298
+ // (L682) calls configureDataForType, which at L1266-1268 assigns
11299
+ // `this.format = this.util.getDateMaskFromLocale().toLowerCase()` for any
11300
+ // type=date input whose `format` attribute is unset. That runs before
11301
+ // firstUpdated invokes setCustomHelpTextMessage, so `!this.format` is
11302
+ // always false here. Retained as a defensive fallback; the whole function
11303
+ // is @deprecated per AB#1557296 and slated for removal.
11241
11304
  } else if (!this.format && this.type === 'date') {
11242
11305
  this.setCustomValidityForType = i18n(this.lang, 'dateMMDDYYYY');
11243
11306
  } else if (this.dateFormatMap[this.format]) {
@@ -11299,6 +11362,8 @@ class BaseInput extends AuroElement {
11299
11362
  this.configureDataForType();
11300
11363
  }
11301
11364
 
11365
+ this.syncDateValues(changedProperties);
11366
+
11302
11367
  if (changedProperties.has('value')) {
11303
11368
  if (this.value && this.value.length > 0) {
11304
11369
  this.hasValue = true;
@@ -11320,14 +11385,14 @@ class BaseInput extends AuroElement {
11320
11385
 
11321
11386
  if (formattedValue !== this.inputElement.value) {
11322
11387
  this.skipNextProgrammaticInputEvent = true;
11323
- if (this.maskInstance && this.type !== 'date') {
11388
+ if (this.maskInstance && this.type === 'credit-card') {
11324
11389
  // Route through the mask so its _value and el.value stay in lock-step
11325
11390
  // (set value calls updateControl which writes el.value = displayValue).
11326
11391
  // 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.
11392
+ // stale; _saveSelection on the next focus/click then warns. Scoped to
11393
+ // credit-card so date's own formattedValue (raw ISO when calendar-invalid)
11394
+ // isn't re-masked through the mm/dd/yyyy mask, which would truncate it
11395
+ // and flip validity from patternMismatch to tooShort.
11331
11396
  this.maskInstance.value = formattedValue || '';
11332
11397
  } else if (formattedValue) {
11333
11398
  this.inputElement.value = formattedValue;
@@ -11369,65 +11434,120 @@ class BaseInput extends AuroElement {
11369
11434
  }));
11370
11435
  }
11371
11436
 
11437
+
11438
+ /**
11439
+ * Synchronizes the ISO string values and Date object representations for date-related properties.
11440
+ * This keeps the model and display values aligned when either side changes.
11441
+ *
11442
+ * When a full date format is in use, this method updates `value`, `min`, and `max` from their corresponding
11443
+ * Date objects or vice versa, based on which properties have changed. It only runs when the current configuration
11444
+ * represents a full year/month/day date format.
11445
+ *
11446
+ * @param {Map<string, unknown>|undefined} [changedProperties=undefined] - Optional map of changed properties used to limit which values are synchronized.
11447
+ * @returns {void}
11448
+ * @private
11449
+ */
11450
+ syncDateValues(changedProperties = undefined) {
11451
+ if (!this.util.isFullDateFormat(this.type, this.format)) {
11452
+ return;
11453
+ }
11454
+
11455
+ this.syncSingleDateValue(changedProperties, 'valueObject', 'value');
11456
+ this.syncSingleDateValue(changedProperties, 'minObject', 'min');
11457
+ this.syncSingleDateValue(changedProperties, 'maxObject', 'max');
11458
+ }
11459
+
11460
+ /**
11461
+ * Synchronizes one date object/string property pair.
11462
+ * @private
11463
+ * @param {Map<string, unknown>|undefined} changedProperties - Map of changed properties from Lit.
11464
+ * @param {string} objectProperty - Date object property name.
11465
+ * @param {string} valueProperty - ISO string property name.
11466
+ * @returns {void}
11467
+ */
11468
+ syncSingleDateValue(changedProperties, objectProperty, valueProperty) {
11469
+ const objectPropertyChanged = !changedProperties || changedProperties.has(objectProperty);
11470
+
11471
+ // objectProperty wins over valueProperty when both changed
11472
+ if (objectPropertyChanged && this[objectProperty]) {
11473
+ this[valueProperty] = dateFormatter.toISOFormatString(this[objectProperty]);
11474
+ return;
11475
+ }
11476
+
11477
+ const valuePropertyChanged = !changedProperties || changedProperties.has(valueProperty);
11478
+ if (!valuePropertyChanged) {
11479
+ return;
11480
+ }
11481
+
11482
+ // 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)
11483
+ if (
11484
+ changedProperties &&
11485
+ valueProperty === 'value' &&
11486
+ changedProperties.get('value') === undefined &&
11487
+ this[objectProperty] instanceof Date &&
11488
+ this[valueProperty] === dateFormatter.toISOFormatString(this[objectProperty])
11489
+ ) {
11490
+ return;
11491
+ }
11492
+
11493
+ if (dateFormatter.isValidDate(this[valueProperty])) {
11494
+ this.setDateObjectProperty(objectProperty, dateFormatter.stringToDateInstance(this[valueProperty]));
11495
+ } else {
11496
+ this.setDateObjectProperty(objectProperty, undefined);
11497
+ }
11498
+ }
11499
+
11372
11500
  /**
11373
11501
  * Sets up IMasks and logic based on auto-formatting requirements.
11374
11502
  * @private
11375
11503
  * @returns {void}
11376
11504
  */
11377
11505
  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.
11506
+ // Re-entrancy guard. The patched-setter's synthetic input event (suppressed
11507
+ // by _configuringMask above) could otherwise trigger handleInput
11508
+ // processCreditCard configureAutoFormatting before the outer call's
11509
+ // set value has finished its alignCursor pass.
11382
11510
  if (this._configuringMask) return;
11383
11511
  this._configuringMask = true;
11384
11512
  try {
11385
- // Destroy any prior mask so IMask can attach fresh under the new format.
11386
- // Null the reference too — if the new maskOptions.mask is falsy (e.g.
11387
- // type switched from credit-card to text) the IMask() reassignment
11388
- // below is skipped, and downstream writes at line ~823 would otherwise
11389
- // route through the destroyed instance.
11390
11513
  if (this.maskInstance) {
11391
11514
  this.maskInstance.destroy();
11392
- this.maskInstance = null;
11393
11515
  }
11394
11516
 
11517
+ // Pass new format to util
11395
11518
  this.util.updateFormat(this.format);
11396
11519
 
11397
11520
  const maskOptions = this.util.getMaskOptions(this.type, this.format);
11398
11521
 
11399
11522
  if (this.inputElement && maskOptions.mask) {
11400
- // Capture the current display so it can be re-applied after IMask
11401
- // attaches. The restore at the bottom goes through maskInstance.value
11402
- // (not inputElement.value directly) so the mask's internal state and
11403
- // the input's displayed text stay in lock-step.
11404
- let existingValue = this.inputElement.value;
11405
11523
 
11406
- // Format-change case (e.g. locale switch): existingValue is the OLD
11407
- // mask's display string and may not parse under the new mask. When
11408
- // we have a valid date model, rebuild the display from valueObject
11409
- // (the canonical source) using the new mask's format function.
11524
+ // Stash and clear any existing value before IMask init.
11525
+ // IMask's constructor processes the current input value which requires
11526
+ // selection state clearing first avoids that scenario entirely.
11527
+ // When the format changes (e.g. locale switch) and we have a valid ISO
11528
+ // model value, compute the display string for the NEW format instead of
11529
+ // re-using the old display string, which may be invalid in the new mask.
11530
+ let existingValue = this.inputElement.value;
11410
11531
  if (
11411
11532
  this.util.isFullDateFormat(this.type, this.format) &&
11412
11533
  this.value &&
11413
- this.valueObject &&
11534
+ dateFormatter.isValidDate(this.value) &&
11535
+ this.valueObject instanceof Date &&
11536
+ !Number.isNaN(this.valueObject.getTime()) &&
11414
11537
  typeof maskOptions.format === 'function'
11415
11538
  ) {
11416
11539
  existingValue = maskOptions.format(this.valueObject);
11417
11540
  }
11418
11541
 
11419
- // Clear before IMask attaches so the constructor seeds an empty
11420
- // internal value. Otherwise IMask reads the stale unmasked string
11421
- // and emits a spurious 'accept' before the restore below runs.
11422
11542
  this.skipNextProgrammaticInputEvent = true;
11423
11543
  this.inputElement.value = '';
11424
11544
 
11425
11545
  this.maskInstance = IMask(this.inputElement, maskOptions);
11426
11546
 
11427
- // Mask fires 'accept' on every value change, including the restore
11428
- // step below. Skip events fired during configureAutoFormatting so
11429
- // we don't overwrite a value the parent just pushed.
11430
11547
  this.maskInstance.on('accept', () => {
11548
+ // Suppress propagation during configureAutoFormatting's own value-restoration
11549
+ // (line below) — the mask emits 'accept' on every value-set, including ours,
11550
+ // and we don't want to overwrite a value the parent just pushed.
11431
11551
  if (this._configuringMask) return;
11432
11552
  this.value = this.util.toModelValue(this.maskInstance.value, this.format);
11433
11553
  if (this.type === "date") {
@@ -11435,8 +11555,6 @@ class BaseInput extends AuroElement {
11435
11555
  }
11436
11556
  });
11437
11557
 
11438
- // Mask fires 'complete' on the restore step below for any value that
11439
- // happens to be a complete match. Same setup-suppression as 'accept'.
11440
11558
  this.maskInstance.on('complete', () => {
11441
11559
  if (this._configuringMask) return;
11442
11560
  this.value = this.util.toModelValue(this.maskInstance.value, this.format);
@@ -11445,9 +11563,7 @@ class BaseInput extends AuroElement {
11445
11563
  }
11446
11564
  });
11447
11565
 
11448
- // Write existingValue through the mask (not the input directly) so
11449
- // the mask reformats it under the new rules and keeps its internal
11450
- // _value aligned with the input's displayed text.
11566
+ // Restore the stashed value through IMask so it's properly masked
11451
11567
  if (existingValue) {
11452
11568
  this.maskInstance.value = existingValue;
11453
11569
  }
@@ -11615,6 +11731,7 @@ class BaseInput extends AuroElement {
11615
11731
  */
11616
11732
  reset() {
11617
11733
  this.value = undefined;
11734
+ this.setDateObjectProperty('valueObject', undefined);
11618
11735
  this.validation.reset(this);
11619
11736
  }
11620
11737
 
@@ -11623,6 +11740,7 @@ class BaseInput extends AuroElement {
11623
11740
  */
11624
11741
  clear() {
11625
11742
  this.value = undefined;
11743
+ this.setDateObjectProperty('valueObject', undefined);
11626
11744
  }
11627
11745
 
11628
11746
  /**
@@ -11660,6 +11778,12 @@ class BaseInput extends AuroElement {
11660
11778
  */
11661
11779
  get placeholderStr() {
11662
11780
  if (!this.placeholder && this.type === 'date') {
11781
+ // COVERAGE: the `'MM/DD/YYYY'` literal fallback is unreachable in WTR.
11782
+ // connectedCallback (L682) calls configureDataForType, which at L1266-1268
11783
+ // assigns `this.format = this.util.getDateMaskFromLocale().toLowerCase()`
11784
+ // when type=date and format is unset. That runs before the first render
11785
+ // reads this getter, so the ternary's truthy arm always wins. Retained
11786
+ // as a defensive fallback for direct getter calls before connection.
11663
11787
  return this.format ? this.format.toUpperCase() : 'MM/DD/YYYY';
11664
11788
  }
11665
11789
  return this.placeholder || "";
@@ -12151,7 +12275,7 @@ class AuroHelpText extends i$3 {
12151
12275
  }
12152
12276
  }
12153
12277
 
12154
- var formkitVersion = '202606231948';
12278
+ var formkitVersion = '202606232113';
12155
12279
 
12156
12280
  /**
12157
12281
  * @license