@aurodesignsystem-dev/auro-formkit 0.0.0-pr1507.0 → 0.0.0-pr1508.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 (63) hide show
  1. package/components/checkbox/demo/customize.html +1 -2
  2. package/components/checkbox/demo/customize.min.js +1 -1
  3. package/components/checkbox/demo/getting-started.min.js +1 -1
  4. package/components/checkbox/demo/index.min.js +1 -1
  5. package/components/checkbox/dist/index.js +1 -1
  6. package/components/checkbox/dist/registered.js +1 -1
  7. package/components/combobox/demo/customize.html +1 -2
  8. package/components/combobox/demo/customize.md +108 -132
  9. package/components/combobox/demo/customize.min.js +150 -293
  10. package/components/combobox/demo/getting-started.min.js +150 -293
  11. package/components/combobox/demo/index.min.js +150 -293
  12. package/components/combobox/dist/auro-combobox.d.ts +9 -0
  13. package/components/combobox/dist/index.js +150 -293
  14. package/components/combobox/dist/registered.js +150 -293
  15. package/components/counter/demo/customize.min.js +10 -2
  16. package/components/counter/demo/index.min.js +10 -2
  17. package/components/counter/dist/index.js +10 -2
  18. package/components/counter/dist/registered.js +10 -2
  19. package/components/datepicker/demo/api.md +2 -0
  20. package/components/datepicker/demo/customize.js +0 -2
  21. package/components/datepicker/demo/customize.md +138 -38
  22. package/components/datepicker/demo/customize.min.js +59 -168
  23. package/components/datepicker/demo/index.min.js +59 -150
  24. package/components/datepicker/dist/index.js +59 -150
  25. package/components/datepicker/dist/registered.js +59 -150
  26. package/components/datepicker/dist/src/auro-datepicker.d.ts +2 -0
  27. package/components/dropdown/demo/customize.min.js +9 -1
  28. package/components/dropdown/demo/getting-started.min.js +9 -1
  29. package/components/dropdown/demo/index.min.js +9 -1
  30. package/components/dropdown/dist/auro-dropdown.d.ts +1 -0
  31. package/components/dropdown/dist/index.js +9 -1
  32. package/components/dropdown/dist/registered.js +9 -1
  33. package/components/form/demo/customize.html +6 -6
  34. package/components/form/demo/customize.js +19 -0
  35. package/components/form/demo/customize.md +203 -51
  36. package/components/form/demo/customize.min.js +707 -633
  37. package/components/form/demo/getting-started.min.js +635 -633
  38. package/components/form/demo/index.min.js +635 -633
  39. package/components/form/demo/registerDemoDeps.min.js +272 -596
  40. package/components/form/dist/auro-form.d.ts +122 -4
  41. package/components/form/dist/index.js +363 -37
  42. package/components/form/dist/registered.js +363 -37
  43. package/components/input/demo/customize.html +1 -2
  44. package/components/input/demo/customize.md +54 -53
  45. package/components/input/demo/customize.min.js +41 -147
  46. package/components/input/demo/getting-started.min.js +41 -147
  47. package/components/input/demo/index.min.js +41 -147
  48. package/components/input/dist/base-input.d.ts +1 -49
  49. package/components/input/dist/index.js +41 -147
  50. package/components/input/dist/registered.js +41 -147
  51. package/components/radio/demo/customize.min.js +1 -1
  52. package/components/radio/demo/getting-started.min.js +1 -1
  53. package/components/radio/demo/index.min.js +1 -1
  54. package/components/radio/dist/index.js +1 -1
  55. package/components/radio/dist/registered.js +1 -1
  56. package/components/select/demo/customize.html +1 -2
  57. package/components/select/demo/customize.min.js +10 -2
  58. package/components/select/demo/getting-started.min.js +10 -2
  59. package/components/select/demo/index.min.js +10 -2
  60. package/components/select/dist/index.js +10 -2
  61. package/components/select/dist/registered.js +10 -2
  62. package/custom-elements.json +1592 -1707
  63. 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,65 @@ 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.
11328
+ // Null the reference too — if the new maskOptions.mask is falsy (e.g.
11329
+ // type switched from credit-card to text) the IMask() reassignment
11330
+ // below is skipped, and downstream writes at line ~823 would otherwise
11331
+ // route through the destroyed instance.
11443
11332
  if (this.maskInstance) {
11444
11333
  this.maskInstance.destroy();
11334
+ this.maskInstance = null;
11445
11335
  }
11446
11336
 
11447
- // Pass new format to util
11448
11337
  this.util.updateFormat(this.format);
11449
11338
 
11450
11339
  const maskOptions = this.util.getMaskOptions(this.type, this.format);
11451
11340
 
11452
11341
  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.
11342
+ // Capture the current display so it can be re-applied after IMask
11343
+ // attaches. The restore at the bottom goes through maskInstance.value
11344
+ // (not inputElement.value directly) so the mask's internal state and
11345
+ // the input's displayed text stay in lock-step.
11460
11346
  let existingValue = this.inputElement.value;
11347
+
11348
+ // Format-change case (e.g. locale switch): existingValue is the OLD
11349
+ // mask's display string and may not parse under the new mask. When
11350
+ // we have a valid date model, rebuild the display from valueObject
11351
+ // (the canonical source) using the new mask's format function.
11461
11352
  if (
11462
11353
  this.util.isFullDateFormat(this.type, this.format) &&
11463
11354
  this.value &&
11464
- dateFormatter.isValidDate(this.value) &&
11465
- this.valueObject instanceof Date &&
11466
- !Number.isNaN(this.valueObject.getTime()) &&
11355
+ this.valueObject &&
11467
11356
  typeof maskOptions.format === 'function'
11468
11357
  ) {
11469
11358
  existingValue = maskOptions.format(this.valueObject);
11470
11359
  }
11471
11360
 
11361
+ // Clear before IMask attaches so the constructor seeds an empty
11362
+ // internal value. Otherwise IMask reads the stale unmasked string
11363
+ // and emits a spurious 'accept' before the restore below runs.
11472
11364
  this.skipNextProgrammaticInputEvent = true;
11473
11365
  this.inputElement.value = '';
11474
11366
 
11475
11367
  this.maskInstance = IMask(this.inputElement, maskOptions);
11476
11368
 
11369
+ // Mask fires 'accept' on every value change, including the restore
11370
+ // step below. Skip events fired during configureAutoFormatting so
11371
+ // we don't overwrite a value the parent just pushed.
11477
11372
  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
11373
  if (this._configuringMask) return;
11482
11374
  this.value = this.util.toModelValue(this.maskInstance.value, this.format);
11483
11375
  if (this.type === "date") {
@@ -11485,6 +11377,8 @@ class BaseInput extends AuroElement {
11485
11377
  }
11486
11378
  });
11487
11379
 
11380
+ // Mask fires 'complete' on the restore step below for any value that
11381
+ // happens to be a complete match. Same setup-suppression as 'accept'.
11488
11382
  this.maskInstance.on('complete', () => {
11489
11383
  if (this._configuringMask) return;
11490
11384
  this.value = this.util.toModelValue(this.maskInstance.value, this.format);
@@ -11493,7 +11387,9 @@ class BaseInput extends AuroElement {
11493
11387
  }
11494
11388
  });
11495
11389
 
11496
- // Restore the stashed value through IMask so it's properly masked
11390
+ // Write existingValue through the mask (not the input directly) so
11391
+ // the mask reformats it under the new rules and keeps its internal
11392
+ // _value aligned with the input's displayed text.
11497
11393
  if (existingValue) {
11498
11394
  this.maskInstance.value = existingValue;
11499
11395
  }
@@ -11661,7 +11557,6 @@ class BaseInput extends AuroElement {
11661
11557
  */
11662
11558
  reset() {
11663
11559
  this.value = undefined;
11664
- this.setDateObjectProperty('valueObject', undefined);
11665
11560
  this.validation.reset(this);
11666
11561
  }
11667
11562
 
@@ -11670,7 +11565,6 @@ class BaseInput extends AuroElement {
11670
11565
  */
11671
11566
  clear() {
11672
11567
  this.value = undefined;
11673
- this.setDateObjectProperty('valueObject', undefined);
11674
11568
  }
11675
11569
 
11676
11570
  /**
@@ -12199,7 +12093,7 @@ class AuroHelpText extends LitElement {
12199
12093
  }
12200
12094
  }
12201
12095
 
12202
- var formkitVersion = '202606192121';
12096
+ var formkitVersion = '202606231948';
12203
12097
 
12204
12098
  // Copyright (c) 2025 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
12205
12099
  // See LICENSE in the project root for license information.