@aurodesignsystem-dev/auro-formkit 0.0.0-pr1497.6 → 0.0.0-pr1498.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 (58) hide show
  1. package/components/checkbox/demo/customize.min.js +2 -2
  2. package/components/checkbox/demo/getting-started.min.js +2 -2
  3. package/components/checkbox/demo/index.min.js +2 -2
  4. package/components/checkbox/dist/index.js +2 -2
  5. package/components/checkbox/dist/registered.js +2 -2
  6. package/components/combobox/demo/customize.md +7 -3
  7. package/components/combobox/demo/customize.min.js +1438 -1668
  8. package/components/combobox/demo/getting-started.min.js +1440 -1670
  9. package/components/combobox/demo/index.min.js +1440 -1670
  10. package/components/combobox/dist/auro-combobox.d.ts +5 -0
  11. package/components/combobox/dist/index.js +485 -140
  12. package/components/combobox/dist/registered.js +485 -140
  13. package/components/counter/demo/customize.min.js +20 -3
  14. package/components/counter/demo/index.min.js +20 -3
  15. package/components/counter/dist/index.js +5447 -192
  16. package/components/counter/dist/registered.js +5447 -192
  17. package/components/datepicker/demo/customize.min.js +149 -58
  18. package/components/datepicker/demo/index.min.js +149 -58
  19. package/components/datepicker/dist/index.js +149 -58
  20. package/components/datepicker/dist/registered.js +149 -58
  21. package/components/dropdown/demo/customize.min.js +18 -1
  22. package/components/dropdown/demo/getting-started.min.js +18 -1
  23. package/components/dropdown/demo/index.min.js +18 -1
  24. package/components/dropdown/dist/auro-dropdown.d.ts +1 -0
  25. package/components/dropdown/dist/index.js +18 -1
  26. package/components/dropdown/dist/registered.js +18 -1
  27. package/components/form/demo/customize.min.js +7910 -7909
  28. package/components/form/demo/getting-started.min.js +7910 -7909
  29. package/components/form/demo/index.min.js +7910 -7909
  30. package/components/form/demo/registerDemoDeps.min.js +7872 -7871
  31. package/components/input/demo/customize.min.js +131 -56
  32. package/components/input/demo/getting-started.min.js +131 -56
  33. package/components/input/demo/index.min.js +131 -56
  34. package/components/input/dist/base-input.d.ts +16 -0
  35. package/components/input/dist/index.js +131 -56
  36. package/components/input/dist/registered.js +131 -56
  37. package/components/menu/demo/api.md +41 -45
  38. package/components/menu/demo/customize.md +0 -28
  39. package/components/menu/demo/index.min.js +779 -1354
  40. package/components/menu/dist/auro-menu.d.ts +95 -110
  41. package/components/menu/dist/auro-menuoption.d.ts +32 -138
  42. package/components/menu/dist/index.js +753 -1308
  43. package/components/menu/dist/registered.js +765 -1308
  44. package/components/radio/demo/customize.min.js +2 -2
  45. package/components/radio/demo/getting-started.min.js +2 -2
  46. package/components/radio/demo/index.min.js +2 -2
  47. package/components/radio/dist/index.js +2 -2
  48. package/components/radio/dist/registered.js +2 -2
  49. package/components/select/demo/customize.md +7 -3
  50. package/components/select/demo/customize.min.js +1088 -1615
  51. package/components/select/demo/getting-started.min.js +1088 -1615
  52. package/components/select/demo/index.min.js +1088 -1615
  53. package/components/select/dist/index.js +63 -15
  54. package/components/select/dist/registered.js +63 -15
  55. package/components/select/dist/selectUtils.d.ts +12 -0
  56. package/custom-elements.json +379 -1025
  57. package/package.json +1 -1
  58. package/components/menu/dist/auro-menu.context.d.ts +0 -238
@@ -4548,7 +4548,7 @@ class AuroFormValidation {
4548
4548
  } else if (this.runtimeUtils.elementMatch(elem, 'auro-input') && elem.errorMessage === '') {
4549
4549
  const input = elem.renderRoot.querySelector('input');
4550
4550
 
4551
- if (input.validationMessage.length > 0) {
4551
+ if (input && input.validationMessage.length > 0) {
4552
4552
  elem.errorMessage = input.validationMessage;
4553
4553
  }
4554
4554
  } else if (this.runtimeUtils.elementMatch(elem, 'auro-combobox') && elem.errorMessage === '') {
@@ -10385,7 +10385,6 @@ class AuroInputUtilities {
10385
10385
  const maskOptions = this.getMaskOptions('date', normalizedFormat);
10386
10386
 
10387
10387
  if (!(valueObject instanceof Date) || Number.isNaN(valueObject.getTime()) || !maskOptions || typeof maskOptions.format !== 'function') {
10388
- console.debug('Invalid date object or mask options for formatting', { valueObject, maskOptions }); // eslint-disable-line no-console
10389
10388
  return undefined;
10390
10389
  }
10391
10390
 
@@ -11088,7 +11087,7 @@ class BaseInput extends AuroElement {
11088
11087
  * @returns {Date|undefined}
11089
11088
  */
11090
11089
  get valueObject() {
11091
- return this._valueObject;
11090
+ return this._valueObject || this._computeDateObjectFallback(this.value);
11092
11091
  }
11093
11092
 
11094
11093
  /**
@@ -11096,7 +11095,7 @@ class BaseInput extends AuroElement {
11096
11095
  * @returns {Date|undefined}
11097
11096
  */
11098
11097
  get minObject() {
11099
- return this._minObject;
11098
+ return this._minObject || this._computeDateObjectFallback(this.min);
11100
11099
  }
11101
11100
 
11102
11101
  /**
@@ -11104,7 +11103,31 @@ class BaseInput extends AuroElement {
11104
11103
  * @returns {Date|undefined}
11105
11104
  */
11106
11105
  get maxObject() {
11107
- return this._maxObject;
11106
+ return this._maxObject || this._computeDateObjectFallback(this.max);
11107
+ }
11108
+
11109
+ /**
11110
+ * Parses a date string into a Date object when the corresponding `_*Object`
11111
+ * field hasn't been synced yet by `updated()`. Returns undefined when the
11112
+ * input type/format isn't a full date or the string is not a valid date.
11113
+ *
11114
+ * Why this exists: a parent (datepicker) can call `inputN.validate()` from
11115
+ * inside its own `updated()` before this input's `updated()` has run
11116
+ * `syncDateValues()` — so `_valueObject`/`_maxObject` are still `undefined`
11117
+ * and range checks would otherwise silently no-op (flipping the result to
11118
+ * `valid` or `patternMismatch`).
11119
+ * @private
11120
+ * @param {string|undefined} dateStr - ISO date string from `value`/`min`/`max`.
11121
+ * @returns {Date|undefined}
11122
+ */
11123
+ _computeDateObjectFallback(dateStr) {
11124
+ if (!dateStr || !this.util || !this.util.isFullDateFormat(this.type, this.format)) {
11125
+ return undefined;
11126
+ }
11127
+ if (!dateFormatter.isValidDate(dateStr)) {
11128
+ return undefined;
11129
+ }
11130
+ return dateFormatter.stringToDateInstance(dateStr);
11108
11131
  }
11109
11132
 
11110
11133
  /**
@@ -11129,8 +11152,30 @@ class BaseInput extends AuroElement {
11129
11152
  connectedCallback() {
11130
11153
  super.connectedCallback();
11131
11154
 
11155
+ // Mark for query selectors when registered under a versioned tag (e.g. inside
11156
+ // a datepicker/combobox). Must run before parent components call validate() on
11157
+ // their inner inputs — the validation framework matches via tag-or-attribute,
11158
+ // and parents trigger validation during their own updated() cycle, which can
11159
+ // precede this input's firstUpdated().
11160
+ if (this.tagName.toLowerCase() !== 'auro-input' && !this.hasAttribute('auro-input')) {
11161
+ this.setAttribute('auro-input', '');
11162
+ }
11163
+
11132
11164
  this.locale = this.domHandler.getLocale(this);
11133
11165
  notifyOnLangChange(this);
11166
+
11167
+ // Pre-compute lengthForType and date-object fields so a parent (e.g. datepicker)
11168
+ // calling our validate() synchronously during its own updated() cycle sees
11169
+ // populated values. Without this, range validation silently no-ops because
11170
+ // `max.length === lengthForType` fails when lengthForType is still undefined.
11171
+ // Rebuild util here (constructor seeded with en-US default) so configureDataForType's
11172
+ // locale-derived format lookup uses the actual locale just resolved above.
11173
+ this.util = new AuroInputUtilities({
11174
+ locale: this.locale,
11175
+ format: this.format
11176
+ });
11177
+ this.configureDataForType();
11178
+ this.syncDateValues();
11134
11179
  }
11135
11180
 
11136
11181
  disconnectedCallback() {
@@ -11151,8 +11196,8 @@ class BaseInput extends AuroElement {
11151
11196
  }
11152
11197
 
11153
11198
  // add attribute for query selectors when auro-input is registered under a custom name
11154
- if (this.tagName.toLowerCase() !== 'auro-input') {
11155
- this.setAttribute('auro-input', true);
11199
+ if (this.tagName.toLowerCase() !== 'auro-input' && !this.hasAttribute('auro-input')) {
11200
+ this.setAttribute('auro-input', '');
11156
11201
  }
11157
11202
  this.inputId = this.id ? `${this.id}-input` : window.crypto.randomUUID();
11158
11203
 
@@ -11200,6 +11245,12 @@ class BaseInput extends AuroElement {
11200
11245
  return;
11201
11246
  }
11202
11247
 
11248
+ // While configureAutoFormatting is running, imask's internal updateControl
11249
+ // writes el.value to align display with the masked value. A synthetic input
11250
+ // event from that write would re-enter handleInput → processCreditCard mid-setup
11251
+ // and clobber a Lit value that was just pushed by the parent combobox.
11252
+ if (component._configuringMask) return;
11253
+
11203
11254
  // If all guard clauses are passed, dispatch the event
11204
11255
  const inputEvent = new InputEvent('input', {
11205
11256
  bubbles: true,
@@ -11318,7 +11369,16 @@ class BaseInput extends AuroElement {
11318
11369
 
11319
11370
  if (formattedValue !== this.inputElement.value) {
11320
11371
  this.skipNextProgrammaticInputEvent = true;
11321
- if (formattedValue) {
11372
+ if (this.maskInstance && this.type === 'credit-card') {
11373
+ // Route through the mask so its _value and el.value stay in lock-step
11374
+ // (set value calls updateControl which writes el.value = displayValue).
11375
+ // Writing el.value directly leaves the mask thinking displayValue is
11376
+ // stale; _saveSelection on the next focus/click then warns. Scoped to
11377
+ // credit-card so date's own formattedValue (raw ISO when calendar-invalid)
11378
+ // isn't re-masked through the mm/dd/yyyy mask, which would truncate it
11379
+ // and flip validity from patternMismatch to tooShort.
11380
+ this.maskInstance.value = formattedValue || '';
11381
+ } else if (formattedValue) {
11322
11382
  this.inputElement.value = formattedValue;
11323
11383
  } else {
11324
11384
  this.inputElement.value = '';
@@ -11427,58 +11487,73 @@ class BaseInput extends AuroElement {
11427
11487
  * @returns {void}
11428
11488
  */
11429
11489
  configureAutoFormatting() {
11430
- if (this.maskInstance) {
11431
- this.maskInstance.destroy();
11432
- }
11433
-
11434
- // Pass new format to util
11435
- this.util.updateFormat(this.format);
11436
-
11437
- const maskOptions = this.util.getMaskOptions(this.type, this.format);
11438
-
11439
- if (this.inputElement && maskOptions.mask) {
11440
-
11441
- // Stash and clear any existing value before IMask init.
11442
- // IMask's constructor processes the current input value which requires
11443
- // selection state — clearing first avoids that scenario entirely.
11444
- // When the format changes (e.g. locale switch) and we have a valid ISO
11445
- // model value, compute the display string for the NEW format instead of
11446
- // re-using the old display string, which may be invalid in the new mask.
11447
- let existingValue = this.inputElement.value;
11448
- if (
11449
- this.util.isFullDateFormat(this.type, this.format) &&
11450
- this.value &&
11451
- dateFormatter.isValidDate(this.value) &&
11452
- this.valueObject instanceof Date &&
11453
- !Number.isNaN(this.valueObject.getTime()) &&
11454
- typeof maskOptions.format === 'function'
11455
- ) {
11456
- existingValue = maskOptions.format(this.valueObject);
11490
+ // Re-entrancy guard. The patched-setter's synthetic input event (suppressed
11491
+ // by _configuringMask above) could otherwise trigger handleInput →
11492
+ // processCreditCard → configureAutoFormatting before the outer call's
11493
+ // set value has finished its alignCursor pass.
11494
+ if (this._configuringMask) return;
11495
+ this._configuringMask = true;
11496
+ try {
11497
+ if (this.maskInstance) {
11498
+ this.maskInstance.destroy();
11457
11499
  }
11458
11500
 
11459
- this.skipNextProgrammaticInputEvent = true;
11460
- this.inputElement.value = '';
11461
-
11462
- this.maskInstance = IMask(this.inputElement, maskOptions);
11501
+ // Pass new format to util
11502
+ this.util.updateFormat(this.format);
11463
11503
 
11464
- this.maskInstance.on('accept', () => {
11465
- this.value = this.util.toModelValue(this.maskInstance.value, this.format);
11466
- if (this.type === "date") {
11467
- this._rawMaskValue = this.maskInstance.value;
11504
+ const maskOptions = this.util.getMaskOptions(this.type, this.format);
11505
+
11506
+ if (this.inputElement && maskOptions.mask) {
11507
+
11508
+ // Stash and clear any existing value before IMask init.
11509
+ // IMask's constructor processes the current input value which requires
11510
+ // selection state — clearing first avoids that scenario entirely.
11511
+ // When the format changes (e.g. locale switch) and we have a valid ISO
11512
+ // model value, compute the display string for the NEW format instead of
11513
+ // re-using the old display string, which may be invalid in the new mask.
11514
+ let existingValue = this.inputElement.value;
11515
+ if (
11516
+ this.util.isFullDateFormat(this.type, this.format) &&
11517
+ this.value &&
11518
+ dateFormatter.isValidDate(this.value) &&
11519
+ this.valueObject instanceof Date &&
11520
+ !Number.isNaN(this.valueObject.getTime()) &&
11521
+ typeof maskOptions.format === 'function'
11522
+ ) {
11523
+ existingValue = maskOptions.format(this.valueObject);
11468
11524
  }
11469
- });
11470
11525
 
11471
- this.maskInstance.on('complete', () => {
11472
- this.value = this.util.toModelValue(this.maskInstance.value, this.format);
11473
- if (this.type === "date") {
11474
- this._rawMaskValue = this.maskInstance.value;
11475
- }
11476
- });
11526
+ this.skipNextProgrammaticInputEvent = true;
11527
+ this.inputElement.value = '';
11528
+
11529
+ this.maskInstance = IMask(this.inputElement, maskOptions);
11530
+
11531
+ this.maskInstance.on('accept', () => {
11532
+ // Suppress propagation during configureAutoFormatting's own value-restoration
11533
+ // (line below) — the mask emits 'accept' on every value-set, including ours,
11534
+ // and we don't want to overwrite a value the parent just pushed.
11535
+ if (this._configuringMask) return;
11536
+ this.value = this.util.toModelValue(this.maskInstance.value, this.format);
11537
+ if (this.type === "date") {
11538
+ this._rawMaskValue = this.maskInstance.value;
11539
+ }
11540
+ });
11477
11541
 
11478
- // Restore the stashed value through IMask so it's properly masked
11479
- if (existingValue) {
11480
- this.maskInstance.value = existingValue;
11542
+ this.maskInstance.on('complete', () => {
11543
+ if (this._configuringMask) return;
11544
+ this.value = this.util.toModelValue(this.maskInstance.value, this.format);
11545
+ if (this.type === "date") {
11546
+ this._rawMaskValue = this.maskInstance.value;
11547
+ }
11548
+ });
11549
+
11550
+ // Restore the stashed value through IMask so it's properly masked
11551
+ if (existingValue) {
11552
+ this.maskInstance.value = existingValue;
11553
+ }
11481
11554
  }
11555
+ } finally {
11556
+ this._configuringMask = false;
11482
11557
  }
11483
11558
  }
11484
11559
 
@@ -11765,10 +11840,10 @@ class BaseInput extends AuroElement {
11765
11840
  },
11766
11841
  {
11767
11842
  name: 'Diners club',
11768
- regex: /^(?<num>36|38)\d{0}/u,
11843
+ regex: /^(?<num>30[0-5]|36|38)\d{0}/u,
11769
11844
  formatLength: 16,
11770
11845
  errorMessage: CreditCardValidationMessage,
11771
- cardIcon: 'credit-card',
11846
+ cardIcon: 'cc-dinersclub',
11772
11847
  maskFormat: "0000 000000 0000"
11773
11848
  },
11774
11849
  {
@@ -12178,7 +12253,7 @@ class AuroHelpText extends i$3 {
12178
12253
  }
12179
12254
  }
12180
12255
 
12181
- var formkitVersion = '202606082053';
12256
+ var formkitVersion = '202606100232';
12182
12257
 
12183
12258
  /**
12184
12259
  * @license
@@ -4548,7 +4548,7 @@ class AuroFormValidation {
4548
4548
  } else if (this.runtimeUtils.elementMatch(elem, 'auro-input') && elem.errorMessage === '') {
4549
4549
  const input = elem.renderRoot.querySelector('input');
4550
4550
 
4551
- if (input.validationMessage.length > 0) {
4551
+ if (input && input.validationMessage.length > 0) {
4552
4552
  elem.errorMessage = input.validationMessage;
4553
4553
  }
4554
4554
  } else if (this.runtimeUtils.elementMatch(elem, 'auro-combobox') && elem.errorMessage === '') {
@@ -10385,7 +10385,6 @@ class AuroInputUtilities {
10385
10385
  const maskOptions = this.getMaskOptions('date', normalizedFormat);
10386
10386
 
10387
10387
  if (!(valueObject instanceof Date) || Number.isNaN(valueObject.getTime()) || !maskOptions || typeof maskOptions.format !== 'function') {
10388
- console.debug('Invalid date object or mask options for formatting', { valueObject, maskOptions }); // eslint-disable-line no-console
10389
10388
  return undefined;
10390
10389
  }
10391
10390
 
@@ -11088,7 +11087,7 @@ class BaseInput extends AuroElement {
11088
11087
  * @returns {Date|undefined}
11089
11088
  */
11090
11089
  get valueObject() {
11091
- return this._valueObject;
11090
+ return this._valueObject || this._computeDateObjectFallback(this.value);
11092
11091
  }
11093
11092
 
11094
11093
  /**
@@ -11096,7 +11095,7 @@ class BaseInput extends AuroElement {
11096
11095
  * @returns {Date|undefined}
11097
11096
  */
11098
11097
  get minObject() {
11099
- return this._minObject;
11098
+ return this._minObject || this._computeDateObjectFallback(this.min);
11100
11099
  }
11101
11100
 
11102
11101
  /**
@@ -11104,7 +11103,31 @@ class BaseInput extends AuroElement {
11104
11103
  * @returns {Date|undefined}
11105
11104
  */
11106
11105
  get maxObject() {
11107
- return this._maxObject;
11106
+ return this._maxObject || this._computeDateObjectFallback(this.max);
11107
+ }
11108
+
11109
+ /**
11110
+ * Parses a date string into a Date object when the corresponding `_*Object`
11111
+ * field hasn't been synced yet by `updated()`. Returns undefined when the
11112
+ * input type/format isn't a full date or the string is not a valid date.
11113
+ *
11114
+ * Why this exists: a parent (datepicker) can call `inputN.validate()` from
11115
+ * inside its own `updated()` before this input's `updated()` has run
11116
+ * `syncDateValues()` — so `_valueObject`/`_maxObject` are still `undefined`
11117
+ * and range checks would otherwise silently no-op (flipping the result to
11118
+ * `valid` or `patternMismatch`).
11119
+ * @private
11120
+ * @param {string|undefined} dateStr - ISO date string from `value`/`min`/`max`.
11121
+ * @returns {Date|undefined}
11122
+ */
11123
+ _computeDateObjectFallback(dateStr) {
11124
+ if (!dateStr || !this.util || !this.util.isFullDateFormat(this.type, this.format)) {
11125
+ return undefined;
11126
+ }
11127
+ if (!dateFormatter.isValidDate(dateStr)) {
11128
+ return undefined;
11129
+ }
11130
+ return dateFormatter.stringToDateInstance(dateStr);
11108
11131
  }
11109
11132
 
11110
11133
  /**
@@ -11129,8 +11152,30 @@ class BaseInput extends AuroElement {
11129
11152
  connectedCallback() {
11130
11153
  super.connectedCallback();
11131
11154
 
11155
+ // Mark for query selectors when registered under a versioned tag (e.g. inside
11156
+ // a datepicker/combobox). Must run before parent components call validate() on
11157
+ // their inner inputs — the validation framework matches via tag-or-attribute,
11158
+ // and parents trigger validation during their own updated() cycle, which can
11159
+ // precede this input's firstUpdated().
11160
+ if (this.tagName.toLowerCase() !== 'auro-input' && !this.hasAttribute('auro-input')) {
11161
+ this.setAttribute('auro-input', '');
11162
+ }
11163
+
11132
11164
  this.locale = this.domHandler.getLocale(this);
11133
11165
  notifyOnLangChange(this);
11166
+
11167
+ // Pre-compute lengthForType and date-object fields so a parent (e.g. datepicker)
11168
+ // calling our validate() synchronously during its own updated() cycle sees
11169
+ // populated values. Without this, range validation silently no-ops because
11170
+ // `max.length === lengthForType` fails when lengthForType is still undefined.
11171
+ // Rebuild util here (constructor seeded with en-US default) so configureDataForType's
11172
+ // locale-derived format lookup uses the actual locale just resolved above.
11173
+ this.util = new AuroInputUtilities({
11174
+ locale: this.locale,
11175
+ format: this.format
11176
+ });
11177
+ this.configureDataForType();
11178
+ this.syncDateValues();
11134
11179
  }
11135
11180
 
11136
11181
  disconnectedCallback() {
@@ -11151,8 +11196,8 @@ class BaseInput extends AuroElement {
11151
11196
  }
11152
11197
 
11153
11198
  // add attribute for query selectors when auro-input is registered under a custom name
11154
- if (this.tagName.toLowerCase() !== 'auro-input') {
11155
- this.setAttribute('auro-input', true);
11199
+ if (this.tagName.toLowerCase() !== 'auro-input' && !this.hasAttribute('auro-input')) {
11200
+ this.setAttribute('auro-input', '');
11156
11201
  }
11157
11202
  this.inputId = this.id ? `${this.id}-input` : window.crypto.randomUUID();
11158
11203
 
@@ -11200,6 +11245,12 @@ class BaseInput extends AuroElement {
11200
11245
  return;
11201
11246
  }
11202
11247
 
11248
+ // While configureAutoFormatting is running, imask's internal updateControl
11249
+ // writes el.value to align display with the masked value. A synthetic input
11250
+ // event from that write would re-enter handleInput → processCreditCard mid-setup
11251
+ // and clobber a Lit value that was just pushed by the parent combobox.
11252
+ if (component._configuringMask) return;
11253
+
11203
11254
  // If all guard clauses are passed, dispatch the event
11204
11255
  const inputEvent = new InputEvent('input', {
11205
11256
  bubbles: true,
@@ -11318,7 +11369,16 @@ class BaseInput extends AuroElement {
11318
11369
 
11319
11370
  if (formattedValue !== this.inputElement.value) {
11320
11371
  this.skipNextProgrammaticInputEvent = true;
11321
- if (formattedValue) {
11372
+ if (this.maskInstance && this.type === 'credit-card') {
11373
+ // Route through the mask so its _value and el.value stay in lock-step
11374
+ // (set value calls updateControl which writes el.value = displayValue).
11375
+ // Writing el.value directly leaves the mask thinking displayValue is
11376
+ // stale; _saveSelection on the next focus/click then warns. Scoped to
11377
+ // credit-card so date's own formattedValue (raw ISO when calendar-invalid)
11378
+ // isn't re-masked through the mm/dd/yyyy mask, which would truncate it
11379
+ // and flip validity from patternMismatch to tooShort.
11380
+ this.maskInstance.value = formattedValue || '';
11381
+ } else if (formattedValue) {
11322
11382
  this.inputElement.value = formattedValue;
11323
11383
  } else {
11324
11384
  this.inputElement.value = '';
@@ -11427,58 +11487,73 @@ class BaseInput extends AuroElement {
11427
11487
  * @returns {void}
11428
11488
  */
11429
11489
  configureAutoFormatting() {
11430
- if (this.maskInstance) {
11431
- this.maskInstance.destroy();
11432
- }
11433
-
11434
- // Pass new format to util
11435
- this.util.updateFormat(this.format);
11436
-
11437
- const maskOptions = this.util.getMaskOptions(this.type, this.format);
11438
-
11439
- if (this.inputElement && maskOptions.mask) {
11440
-
11441
- // Stash and clear any existing value before IMask init.
11442
- // IMask's constructor processes the current input value which requires
11443
- // selection state — clearing first avoids that scenario entirely.
11444
- // When the format changes (e.g. locale switch) and we have a valid ISO
11445
- // model value, compute the display string for the NEW format instead of
11446
- // re-using the old display string, which may be invalid in the new mask.
11447
- let existingValue = this.inputElement.value;
11448
- if (
11449
- this.util.isFullDateFormat(this.type, this.format) &&
11450
- this.value &&
11451
- dateFormatter.isValidDate(this.value) &&
11452
- this.valueObject instanceof Date &&
11453
- !Number.isNaN(this.valueObject.getTime()) &&
11454
- typeof maskOptions.format === 'function'
11455
- ) {
11456
- existingValue = maskOptions.format(this.valueObject);
11490
+ // Re-entrancy guard. The patched-setter's synthetic input event (suppressed
11491
+ // by _configuringMask above) could otherwise trigger handleInput →
11492
+ // processCreditCard → configureAutoFormatting before the outer call's
11493
+ // set value has finished its alignCursor pass.
11494
+ if (this._configuringMask) return;
11495
+ this._configuringMask = true;
11496
+ try {
11497
+ if (this.maskInstance) {
11498
+ this.maskInstance.destroy();
11457
11499
  }
11458
11500
 
11459
- this.skipNextProgrammaticInputEvent = true;
11460
- this.inputElement.value = '';
11461
-
11462
- this.maskInstance = IMask(this.inputElement, maskOptions);
11501
+ // Pass new format to util
11502
+ this.util.updateFormat(this.format);
11463
11503
 
11464
- this.maskInstance.on('accept', () => {
11465
- this.value = this.util.toModelValue(this.maskInstance.value, this.format);
11466
- if (this.type === "date") {
11467
- this._rawMaskValue = this.maskInstance.value;
11504
+ const maskOptions = this.util.getMaskOptions(this.type, this.format);
11505
+
11506
+ if (this.inputElement && maskOptions.mask) {
11507
+
11508
+ // Stash and clear any existing value before IMask init.
11509
+ // IMask's constructor processes the current input value which requires
11510
+ // selection state — clearing first avoids that scenario entirely.
11511
+ // When the format changes (e.g. locale switch) and we have a valid ISO
11512
+ // model value, compute the display string for the NEW format instead of
11513
+ // re-using the old display string, which may be invalid in the new mask.
11514
+ let existingValue = this.inputElement.value;
11515
+ if (
11516
+ this.util.isFullDateFormat(this.type, this.format) &&
11517
+ this.value &&
11518
+ dateFormatter.isValidDate(this.value) &&
11519
+ this.valueObject instanceof Date &&
11520
+ !Number.isNaN(this.valueObject.getTime()) &&
11521
+ typeof maskOptions.format === 'function'
11522
+ ) {
11523
+ existingValue = maskOptions.format(this.valueObject);
11468
11524
  }
11469
- });
11470
11525
 
11471
- this.maskInstance.on('complete', () => {
11472
- this.value = this.util.toModelValue(this.maskInstance.value, this.format);
11473
- if (this.type === "date") {
11474
- this._rawMaskValue = this.maskInstance.value;
11475
- }
11476
- });
11526
+ this.skipNextProgrammaticInputEvent = true;
11527
+ this.inputElement.value = '';
11528
+
11529
+ this.maskInstance = IMask(this.inputElement, maskOptions);
11530
+
11531
+ this.maskInstance.on('accept', () => {
11532
+ // Suppress propagation during configureAutoFormatting's own value-restoration
11533
+ // (line below) — the mask emits 'accept' on every value-set, including ours,
11534
+ // and we don't want to overwrite a value the parent just pushed.
11535
+ if (this._configuringMask) return;
11536
+ this.value = this.util.toModelValue(this.maskInstance.value, this.format);
11537
+ if (this.type === "date") {
11538
+ this._rawMaskValue = this.maskInstance.value;
11539
+ }
11540
+ });
11477
11541
 
11478
- // Restore the stashed value through IMask so it's properly masked
11479
- if (existingValue) {
11480
- this.maskInstance.value = existingValue;
11542
+ this.maskInstance.on('complete', () => {
11543
+ if (this._configuringMask) return;
11544
+ this.value = this.util.toModelValue(this.maskInstance.value, this.format);
11545
+ if (this.type === "date") {
11546
+ this._rawMaskValue = this.maskInstance.value;
11547
+ }
11548
+ });
11549
+
11550
+ // Restore the stashed value through IMask so it's properly masked
11551
+ if (existingValue) {
11552
+ this.maskInstance.value = existingValue;
11553
+ }
11481
11554
  }
11555
+ } finally {
11556
+ this._configuringMask = false;
11482
11557
  }
11483
11558
  }
11484
11559
 
@@ -11765,10 +11840,10 @@ class BaseInput extends AuroElement {
11765
11840
  },
11766
11841
  {
11767
11842
  name: 'Diners club',
11768
- regex: /^(?<num>36|38)\d{0}/u,
11843
+ regex: /^(?<num>30[0-5]|36|38)\d{0}/u,
11769
11844
  formatLength: 16,
11770
11845
  errorMessage: CreditCardValidationMessage,
11771
- cardIcon: 'credit-card',
11846
+ cardIcon: 'cc-dinersclub',
11772
11847
  maskFormat: "0000 000000 0000"
11773
11848
  },
11774
11849
  {
@@ -12178,7 +12253,7 @@ class AuroHelpText extends i$3 {
12178
12253
  }
12179
12254
  }
12180
12255
 
12181
- var formkitVersion = '202606082053';
12256
+ var formkitVersion = '202606100232';
12182
12257
 
12183
12258
  /**
12184
12259
  * @license