@aurodesignsystem-dev/auro-formkit 0.0.0-pr1619.0 → 0.0.0-pr1621.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 (48) 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 +3 -3
  7. package/components/combobox/demo/getting-started.min.js +3 -3
  8. package/components/combobox/demo/index.min.js +3 -3
  9. package/components/combobox/dist/index.js +3 -3
  10. package/components/combobox/dist/registered.js +3 -3
  11. package/components/counter/demo/api.md +4 -3
  12. package/components/counter/demo/customize.min.js +85 -50
  13. package/components/counter/demo/getting-started.min.js +85 -50
  14. package/components/counter/demo/index.min.js +85 -50
  15. package/components/counter/dist/auro-counter-group.d.ts +11 -8
  16. package/components/counter/dist/index.js +85 -50
  17. package/components/counter/dist/registered.js +85 -50
  18. package/components/datepicker/demo/customize.min.js +3 -3
  19. package/components/datepicker/demo/getting-started.min.js +3 -3
  20. package/components/datepicker/demo/index.min.js +3 -3
  21. package/components/datepicker/dist/index.js +3 -3
  22. package/components/datepicker/dist/registered.js +3 -3
  23. package/components/dropdown/demo/customize.min.js +1 -1
  24. package/components/dropdown/demo/getting-started.min.js +2 -2
  25. package/components/dropdown/demo/index.min.js +1 -1
  26. package/components/dropdown/dist/index.js +1 -1
  27. package/components/dropdown/dist/registered.js +1 -1
  28. package/components/form/demo/customize.min.js +96 -61
  29. package/components/form/demo/getting-started.min.js +96 -61
  30. package/components/form/demo/index.min.js +96 -61
  31. package/components/form/demo/registerDemoDeps.min.js +96 -61
  32. package/components/input/demo/customize.min.js +1 -1
  33. package/components/input/demo/getting-started.min.js +1 -1
  34. package/components/input/demo/index.min.js +1 -1
  35. package/components/input/dist/index.js +1 -1
  36. package/components/input/dist/registered.js +1 -1
  37. package/components/radio/demo/customize.min.js +1 -1
  38. package/components/radio/demo/getting-started.min.js +1 -1
  39. package/components/radio/demo/index.min.js +1 -1
  40. package/components/radio/dist/index.js +1 -1
  41. package/components/radio/dist/registered.js +1 -1
  42. package/components/select/demo/customize.min.js +2 -2
  43. package/components/select/demo/getting-started.min.js +2 -2
  44. package/components/select/demo/index.min.js +2 -2
  45. package/components/select/dist/index.js +2 -2
  46. package/components/select/dist/registered.js +2 -2
  47. package/custom-elements.json +1549 -1551
  48. package/package.json +1 -1
@@ -1326,7 +1326,7 @@ class AuroHelpText extends i$2 {
1326
1326
  }
1327
1327
  }
1328
1328
 
1329
- var formkitVersion = '202609231954';
1329
+ var formkitVersion = '202609232032';
1330
1330
 
1331
1331
  // Copyright (c) 2026 Alaska Airlines. All rights reserved. Licensed under the Apache-2.0 license
1332
1332
  // See LICENSE in the project root for license information.
@@ -1326,7 +1326,7 @@ class AuroHelpText extends i$2 {
1326
1326
  }
1327
1327
  }
1328
1328
 
1329
- var formkitVersion = '202609231954';
1329
+ var formkitVersion = '202609232032';
1330
1330
 
1331
1331
  // Copyright (c) 2026 Alaska Airlines. All rights reserved. Licensed under the Apache-2.0 license
1332
1332
  // See LICENSE in the project root for license information.
@@ -1326,7 +1326,7 @@ class AuroHelpText extends i$2 {
1326
1326
  }
1327
1327
  }
1328
1328
 
1329
- var formkitVersion = '202609231954';
1329
+ var formkitVersion = '202609232032';
1330
1330
 
1331
1331
  // Copyright (c) 2026 Alaska Airlines. All rights reserved. Licensed under the Apache-2.0 license
1332
1332
  // See LICENSE in the project root for license information.
@@ -1279,7 +1279,7 @@ class AuroHelpText extends LitElement {
1279
1279
  }
1280
1280
  }
1281
1281
 
1282
- var formkitVersion = '202609231954';
1282
+ var formkitVersion = '202609232032';
1283
1283
 
1284
1284
  // Copyright (c) 2026 Alaska Airlines. All rights reserved. Licensed under the Apache-2.0 license
1285
1285
  // See LICENSE in the project root for license information.
@@ -1279,7 +1279,7 @@ class AuroHelpText extends LitElement {
1279
1279
  }
1280
1280
  }
1281
1281
 
1282
- var formkitVersion = '202609231954';
1282
+ var formkitVersion = '202609232032';
1283
1283
 
1284
1284
  // Copyright (c) 2026 Alaska Airlines. All rights reserved. Licensed under the Apache-2.0 license
1285
1285
  // See LICENSE in the project root for license information.
@@ -5108,7 +5108,7 @@ let AuroHelpText$2 = class AuroHelpText extends i$3 {
5108
5108
  }
5109
5109
  };
5110
5110
 
5111
- var formkitVersion$2 = '202609231954';
5111
+ var formkitVersion$2 = '202609232032';
5112
5112
 
5113
5113
  /**
5114
5114
  * AuroElement is the shared base class for layout-aware Auro form components.
@@ -18977,7 +18977,7 @@ let AuroHelpText$1 = class AuroHelpText extends i$3 {
18977
18977
  }
18978
18978
  };
18979
18979
 
18980
- var formkitVersion$1 = '202609231954';
18980
+ var formkitVersion$1 = '202609232032';
18981
18981
 
18982
18982
  // Copyright (c) 2025 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
18983
18983
  // See LICENSE in the project root for license information.
@@ -20169,7 +20169,7 @@ class AuroBibtemplate extends i$3 {
20169
20169
  }
20170
20170
  }
20171
20171
 
20172
- var formkitVersion = '202609231954';
20172
+ var formkitVersion = '202609232032';
20173
20173
 
20174
20174
  var styleCss$3 = i$6`.util_displayInline{display:inline}.util_displayInlineBlock{display:inline-block}.util_displayBlock{display:block}.util_displayFlex{display:flex}.util_displayHidden{display:none}.util_displayHiddenVisually{position:absolute;overflow:hidden;clip:rect(1px, 1px, 1px, 1px);width:1px;height:1px;padding:0;border:0}:host{display:block;text-align:left}:host [auro-dropdown]{--ds-auro-dropdown-trigger-background-color: transparent}:host #inputInBib::part(wrapper){box-shadow:none}:host #inputInBib::part(accent-left){display:none}:host([layout*=classic]) [auro-input]{width:100%}:host([layout*=classic]) [auro-input]::part(helpText){display:none}:host([layout*=classic]) #slotHolder{display:none}`;
20175
20175
 
@@ -5108,7 +5108,7 @@ let AuroHelpText$2 = class AuroHelpText extends i$3 {
5108
5108
  }
5109
5109
  };
5110
5110
 
5111
- var formkitVersion$2 = '202609231954';
5111
+ var formkitVersion$2 = '202609232032';
5112
5112
 
5113
5113
  /**
5114
5114
  * AuroElement is the shared base class for layout-aware Auro form components.
@@ -18977,7 +18977,7 @@ let AuroHelpText$1 = class AuroHelpText extends i$3 {
18977
18977
  }
18978
18978
  };
18979
18979
 
18980
- var formkitVersion$1 = '202609231954';
18980
+ var formkitVersion$1 = '202609232032';
18981
18981
 
18982
18982
  // Copyright (c) 2025 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
18983
18983
  // See LICENSE in the project root for license information.
@@ -20169,7 +20169,7 @@ class AuroBibtemplate extends i$3 {
20169
20169
  }
20170
20170
  }
20171
20171
 
20172
- var formkitVersion = '202609231954';
20172
+ var formkitVersion = '202609232032';
20173
20173
 
20174
20174
  var styleCss$3 = i$6`.util_displayInline{display:inline}.util_displayInlineBlock{display:inline-block}.util_displayBlock{display:block}.util_displayFlex{display:flex}.util_displayHidden{display:none}.util_displayHiddenVisually{position:absolute;overflow:hidden;clip:rect(1px, 1px, 1px, 1px);width:1px;height:1px;padding:0;border:0}:host{display:block;text-align:left}:host [auro-dropdown]{--ds-auro-dropdown-trigger-background-color: transparent}:host #inputInBib::part(wrapper){box-shadow:none}:host #inputInBib::part(accent-left){display:none}:host([layout*=classic]) [auro-input]{width:100%}:host([layout*=classic]) [auro-input]::part(helpText){display:none}:host([layout*=classic]) #slotHolder{display:none}`;
20175
20175
 
@@ -5123,7 +5123,7 @@ let AuroHelpText$2 = class AuroHelpText extends i$3 {
5123
5123
  }
5124
5124
  };
5125
5125
 
5126
- var formkitVersion$2 = '202609231954';
5126
+ var formkitVersion$2 = '202609232032';
5127
5127
 
5128
5128
  /**
5129
5129
  * AuroElement is the shared base class for layout-aware Auro form components.
@@ -18992,7 +18992,7 @@ let AuroHelpText$1 = class AuroHelpText extends i$3 {
18992
18992
  }
18993
18993
  };
18994
18994
 
18995
- var formkitVersion$1 = '202609231954';
18995
+ var formkitVersion$1 = '202609232032';
18996
18996
 
18997
18997
  // Copyright (c) 2025 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
18998
18998
  // See LICENSE in the project root for license information.
@@ -20184,7 +20184,7 @@ class AuroBibtemplate extends i$3 {
20184
20184
  }
20185
20185
  }
20186
20186
 
20187
- var formkitVersion = '202609231954';
20187
+ var formkitVersion = '202609232032';
20188
20188
 
20189
20189
  var styleCss$3 = i$6`.util_displayInline{display:inline}.util_displayInlineBlock{display:inline-block}.util_displayBlock{display:block}.util_displayFlex{display:flex}.util_displayHidden{display:none}.util_displayHiddenVisually{position:absolute;overflow:hidden;clip:rect(1px, 1px, 1px, 1px);width:1px;height:1px;padding:0;border:0}:host{display:block;text-align:left}:host [auro-dropdown]{--ds-auro-dropdown-trigger-background-color: transparent}:host #inputInBib::part(wrapper){box-shadow:none}:host #inputInBib::part(accent-left){display:none}:host([layout*=classic]) [auro-input]{width:100%}:host([layout*=classic]) [auro-input]::part(helpText){display:none}:host([layout*=classic]) #slotHolder{display:none}`;
20190
20190
 
@@ -5041,7 +5041,7 @@ let AuroHelpText$2 = class AuroHelpText extends LitElement {
5041
5041
  }
5042
5042
  };
5043
5043
 
5044
- var formkitVersion$2 = '202609231954';
5044
+ var formkitVersion$2 = '202609232032';
5045
5045
 
5046
5046
  /**
5047
5047
  * AuroElement is the shared base class for layout-aware Auro form components.
@@ -18903,7 +18903,7 @@ let AuroHelpText$1 = class AuroHelpText extends LitElement {
18903
18903
  }
18904
18904
  };
18905
18905
 
18906
- var formkitVersion$1 = '202609231954';
18906
+ var formkitVersion$1 = '202609232032';
18907
18907
 
18908
18908
  // Copyright (c) 2025 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
18909
18909
  // See LICENSE in the project root for license information.
@@ -20095,7 +20095,7 @@ class AuroBibtemplate extends LitElement {
20095
20095
  }
20096
20096
  }
20097
20097
 
20098
- var formkitVersion = '202609231954';
20098
+ var formkitVersion = '202609232032';
20099
20099
 
20100
20100
  var styleCss$1 = css`.util_displayInline{display:inline}.util_displayInlineBlock{display:inline-block}.util_displayBlock{display:block}.util_displayFlex{display:flex}.util_displayHidden{display:none}.util_displayHiddenVisually{position:absolute;overflow:hidden;clip:rect(1px, 1px, 1px, 1px);width:1px;height:1px;padding:0;border:0}:host{display:block;text-align:left}:host [auro-dropdown]{--ds-auro-dropdown-trigger-background-color: transparent}:host #inputInBib::part(wrapper){box-shadow:none}:host #inputInBib::part(accent-left){display:none}:host([layout*=classic]) [auro-input]{width:100%}:host([layout*=classic]) [auro-input]::part(helpText){display:none}:host([layout*=classic]) #slotHolder{display:none}`;
20101
20101
 
@@ -5041,7 +5041,7 @@ let AuroHelpText$2 = class AuroHelpText extends LitElement {
5041
5041
  }
5042
5042
  };
5043
5043
 
5044
- var formkitVersion$2 = '202609231954';
5044
+ var formkitVersion$2 = '202609232032';
5045
5045
 
5046
5046
  /**
5047
5047
  * AuroElement is the shared base class for layout-aware Auro form components.
@@ -18903,7 +18903,7 @@ let AuroHelpText$1 = class AuroHelpText extends LitElement {
18903
18903
  }
18904
18904
  };
18905
18905
 
18906
- var formkitVersion$1 = '202609231954';
18906
+ var formkitVersion$1 = '202609232032';
18907
18907
 
18908
18908
  // Copyright (c) 2025 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
18909
18909
  // See LICENSE in the project root for license information.
@@ -20095,7 +20095,7 @@ class AuroBibtemplate extends LitElement {
20095
20095
  }
20096
20096
  }
20097
20097
 
20098
- var formkitVersion = '202609231954';
20098
+ var formkitVersion = '202609232032';
20099
20099
 
20100
20100
  var styleCss$1 = css`.util_displayInline{display:inline}.util_displayInlineBlock{display:inline-block}.util_displayBlock{display:block}.util_displayFlex{display:flex}.util_displayHidden{display:none}.util_displayHiddenVisually{position:absolute;overflow:hidden;clip:rect(1px, 1px, 1px, 1px);width:1px;height:1px;padding:0;border:0}:host{display:block;text-align:left}:host [auro-dropdown]{--ds-auro-dropdown-trigger-background-color: transparent}:host #inputInBib::part(wrapper){box-shadow:none}:host #inputInBib::part(accent-left){display:none}:host([layout*=classic]) [auro-input]{width:100%}:host([layout*=classic]) [auro-input]::part(helpText){display:none}:host([layout*=classic]) #slotHolder{display:none}`;
20101
20101
 
@@ -41,9 +41,10 @@ The `auro-counter-group` element provides a flexible interface for grouping mult
41
41
 
42
42
  ## Events
43
43
 
44
- | Event | Type | Description |
45
- |---------|--------------------------------------------------|--------------------------------------------------|
46
- | `input` | `CustomEvent<{ total: number \| undefined; value: {} \| undefined; }>` | Notifies that the counter group's value has changed. |
44
+ | Event | Type | Description |
45
+ |-----------------------------|--------------------------------------------------|--------------------------------------------------|
46
+ | `auroFormElement-validated` | `CustomEvent<{ validity: any; message: string \| undefined; }>` | Notifies that the `validity` and `errorMessage` values have changed. |
47
+ | `input` | `CustomEvent<{ total: number \| undefined; value: {} \| undefined; }>` | Notifies that the counter group's value has changed. |
47
48
 
48
49
  ## Slots
49
50
 
@@ -1129,7 +1129,7 @@ let AuroHelpText$1 = class AuroHelpText extends i$1 {
1129
1129
  }
1130
1130
  };
1131
1131
 
1132
- var formkitVersion$1 = '202609231954';
1132
+ var formkitVersion$1 = '202609232032';
1133
1133
 
1134
1134
  // Copyright (c) 2026 Alaska Airlines. All rights reserved. Licensed under the Apache-2.0 license
1135
1135
  // See LICENSE in the project root for license information.
@@ -5489,7 +5489,7 @@ class AuroHelpText extends i$1 {
5489
5489
  }
5490
5490
  }
5491
5491
 
5492
- var formkitVersion = '202609231954';
5492
+ var formkitVersion = '202609232032';
5493
5493
 
5494
5494
  /**
5495
5495
  * AuroElement is the shared base class for layout-aware Auro form components.
@@ -7885,6 +7885,7 @@ const counterGroupKeyboardStrategy = {
7885
7885
  * @csspart dropdown - The dropdown element rendered when `isDropdown` is true.
7886
7886
  * @csspart helpText - The help text and error message container.
7887
7887
  *
7888
+ * @event auroFormElement-validated - Notifies that the `validity` and `errorMessage` values have changed.
7888
7889
  * @event input - Notifies that the counter group's value has changed.
7889
7890
  */
7890
7891
  class AuroCounterGroup extends AuroElement {
@@ -8235,21 +8236,6 @@ class AuroCounterGroup extends AuroElement {
8235
8236
  this.updateValidity();
8236
8237
  }
8237
8238
 
8238
- /**
8239
- * Renders help text error messages.
8240
- * @param {Array<string>} messages - The error messages to render.
8241
- * @returns {TemplateResult[]} - The rendered error messages rendered in a TemplateResult.
8242
- * @private
8243
- */
8244
- renderHelpTextErrors(messages) {
8245
-
8246
- // Return empty template if no messages are provided
8247
- if (!messages || messages.length === 0) return u$6``;
8248
-
8249
- // Return messages as a TemplateResult
8250
- return messages.map(message => u$6`<p>${message}</p>`);
8251
- }
8252
-
8253
8239
  /**
8254
8240
  * Gets and returns an array of counters in an invalid state.
8255
8241
  * @returns {Array<HTMLElement>} - Returns an array of invalid counters.
@@ -8273,55 +8259,70 @@ class AuroCounterGroup extends AuroElement {
8273
8259
  };
8274
8260
 
8275
8261
  /**
8276
- * Updates the validity of the counter group based on the validity of its counters.
8277
- * This method checks all counters within the group, determines if any are invalid, and updates the group's validity state and error message accordingly.
8278
- * If any counter is invalid, it generates a combined error message from all invalid counters.
8262
+ * Synchronously recomputes this.validity/this.errorMessage from the current
8263
+ * validity of the child counters. Extracted from updateValidity() so that
8264
+ * validate() can re-apply this aggregation immediately after the shared
8265
+ * validation engine runs, instead of waiting on a deferred timer.
8279
8266
  * @returns {void}
8280
8267
  * @private
8281
8268
  */
8282
- updateValidity () {
8269
+ computeValidityFromCounters() {
8283
8270
 
8284
8271
  // We don't need to do anything if there are no counters
8285
8272
  if (!this.counters) return;
8286
8273
 
8287
- // Wait for initial validation to complete before updating validity and error message
8288
- // This is necessary because we need the initial validation to know when to reset the validity and error message
8289
- setTimeout(() => {
8274
+ // Get any invalid counters
8275
+ const invalidCounters = this.getInvalidCounters(this.counters);
8276
+
8277
+ // Determine if we are in an invalid state based on the presence of invalid counters
8278
+ const isInvalid = invalidCounters.length > 0;
8290
8279
 
8291
- // Get any invalid counters
8292
- const invalidCounters = this.getInvalidCounters(this.counters);
8280
+ // If we are in an invalid state
8281
+ if (isInvalid) {
8293
8282
 
8294
- // Determine if we are in an invalid state based on the presence of invalid counters
8295
- const isInvalid = invalidCounters.length > 0;
8283
+ // Generate the error messages as plain text, joined with sentence-ending
8284
+ // punctuation so multiple messages don't run together into one clause.
8285
+ const errorMessages = this.getErrorMessages(invalidCounters);
8286
+ const joinedMessage = errorMessages.join('. ');
8296
8287
 
8297
- // If we are in an invalid state
8298
- if (isInvalid) {
8288
+ // Set the validity and error message
8289
+ // This needs to allow for the initial validation to come through
8290
+ this.validity =
8291
+ invalidCounters[0].validity || // The first invalid counter's validity
8292
+ this.validity || // incoming validity from validation
8293
+ undefined; // fallback
8299
8294
 
8300
- // Generate the error messages
8301
- const errorMessages = this.getErrorMessages(invalidCounters);
8295
+ // Always reflect the current invalid counters' messages, even when that
8296
+ // means clearing to undefined -- falling back to the previous
8297
+ // this.errorMessage here would let a stale message from a prior,
8298
+ // different invalid cause survive a transition into a cause with no
8299
+ // message of its own (e.g. customError -> rangeOverflow).
8300
+ this.errorMessage = joinedMessage || undefined;
8301
+ }
8302
8302
 
8303
- const errorMessage = isInvalid ? this.renderHelpTextErrors(errorMessages) : this.errorMessage;
8303
+ if (!isInvalid && this.validity !== 'valid') {
8304
8304
 
8305
- // Set the validity and error message
8306
- // This needs to allow for the initial validation to come through
8307
- this.validity =
8308
- invalidCounters[0].validity || // The first invalid counter's validity
8309
- this.validity || // incoming validity from validation
8310
- undefined; // fallback
8305
+ // If there are no invalid counters, reset validity and error message
8306
+ this.validity = 'valid';
8307
+ this.errorMessage = undefined;
8308
+ }
8309
+ }
8311
8310
 
8312
- this.errorMessage =
8313
- errorMessage || // our message
8314
- this.errorMessage || // incoming message from validation
8315
- undefined; // fallback
8316
- }
8311
+ /**
8312
+ * Updates the validity of the counter group based on the validity of its counters.
8313
+ * This method checks all counters within the group, determines if any are invalid, and updates the group's validity state and error message accordingly.
8314
+ * If any counter is invalid, it generates a combined error message from all invalid counters.
8315
+ * @returns {void}
8316
+ * @private
8317
+ */
8318
+ updateValidity () {
8317
8319
 
8318
- if (!isInvalid && this.validity !== 'valid') {
8320
+ // We don't need to do anything if there are no counters
8321
+ if (!this.counters) return;
8319
8322
 
8320
- // If there are no invalid counters, reset validity and error message
8321
- this.validity = 'valid';
8322
- this.errorMessage = undefined;
8323
- }
8324
- });
8323
+ // Wait for initial validation to complete before updating validity and error message
8324
+ // This is necessary because we need the initial validation to know when to reset the validity and error message
8325
+ setTimeout(() => this.computeValidityFromCounters());
8325
8326
  }
8326
8327
 
8327
8328
  /**
@@ -8489,6 +8490,40 @@ class AuroCounterGroup extends AuroElement {
8489
8490
  */
8490
8491
  validate(force = false) {
8491
8492
  this.validation.validate(this, force);
8493
+
8494
+ // AuroFormValidation doesn't know how to derive validity from our object-valued
8495
+ // `value`, so it always resolves an otherwise-error-free group to 'valid' -- even
8496
+ // while a child counter is still invalid. Re-derive from the children's current
8497
+ // state immediately afterward so that invalid state survives forced validation,
8498
+ // and re-dispatch the validated event when the correction changes the outcome so
8499
+ // listeners like auro-form's submit path see the corrected result.
8500
+ //
8501
+ // This intentionally also runs for unforced calls (every child value change),
8502
+ // even though updateValidity()'s deferred, listener-driven aggregation computes
8503
+ // the same result a tick later: that deferred path only updates this.validity/
8504
+ // this.errorMessage, it never re-dispatches the event, so auro-form's formState
8505
+ // (and therefore the submit button's disabled state) would otherwise only ever
8506
+ // learn about a child-derived invalid state at the next forced validation --
8507
+ // not at initial load or on ordinary interaction. See docs/post-mortem/1642340.md,
8508
+ // "Iterations That Didn't Work", for the attempt to scope this to `force` and
8509
+ // why it broke that behavior.
8510
+ if (this.counters && !this.hasAttribute('error')) {
8511
+ const previousValidity = this.validity;
8512
+ const previousMessage = this.errorMessage;
8513
+
8514
+ this.computeValidityFromCounters();
8515
+
8516
+ if (this.validity !== previousValidity || this.errorMessage !== previousMessage) {
8517
+ this.dispatchEvent(new CustomEvent('auroFormElement-validated', {
8518
+ bubbles: true,
8519
+ composed: true,
8520
+ detail: {
8521
+ validity: this.validity,
8522
+ message: this.errorMessage
8523
+ }
8524
+ }));
8525
+ }
8526
+ }
8492
8527
  }
8493
8528
 
8494
8529
  /**
@@ -1127,7 +1127,7 @@ let AuroHelpText$1 = class AuroHelpText extends i$2 {
1127
1127
  }
1128
1128
  };
1129
1129
 
1130
- var formkitVersion$1 = '202609231954';
1130
+ var formkitVersion$1 = '202609232032';
1131
1131
 
1132
1132
  // Copyright (c) 2026 Alaska Airlines. All rights reserved. Licensed under the Apache-2.0 license
1133
1133
  // See LICENSE in the project root for license information.
@@ -5487,7 +5487,7 @@ class AuroHelpText extends i$2 {
5487
5487
  }
5488
5488
  }
5489
5489
 
5490
- var formkitVersion = '202609231954';
5490
+ var formkitVersion = '202609232032';
5491
5491
 
5492
5492
  /**
5493
5493
  * AuroElement is the shared base class for layout-aware Auro form components.
@@ -7883,6 +7883,7 @@ const counterGroupKeyboardStrategy = {
7883
7883
  * @csspart dropdown - The dropdown element rendered when `isDropdown` is true.
7884
7884
  * @csspart helpText - The help text and error message container.
7885
7885
  *
7886
+ * @event auroFormElement-validated - Notifies that the `validity` and `errorMessage` values have changed.
7886
7887
  * @event input - Notifies that the counter group's value has changed.
7887
7888
  */
7888
7889
  class AuroCounterGroup extends AuroElement {
@@ -8233,21 +8234,6 @@ class AuroCounterGroup extends AuroElement {
8233
8234
  this.updateValidity();
8234
8235
  }
8235
8236
 
8236
- /**
8237
- * Renders help text error messages.
8238
- * @param {Array<string>} messages - The error messages to render.
8239
- * @returns {TemplateResult[]} - The rendered error messages rendered in a TemplateResult.
8240
- * @private
8241
- */
8242
- renderHelpTextErrors(messages) {
8243
-
8244
- // Return empty template if no messages are provided
8245
- if (!messages || messages.length === 0) return u$5``;
8246
-
8247
- // Return messages as a TemplateResult
8248
- return messages.map(message => u$5`<p>${message}</p>`);
8249
- }
8250
-
8251
8237
  /**
8252
8238
  * Gets and returns an array of counters in an invalid state.
8253
8239
  * @returns {Array<HTMLElement>} - Returns an array of invalid counters.
@@ -8271,55 +8257,70 @@ class AuroCounterGroup extends AuroElement {
8271
8257
  };
8272
8258
 
8273
8259
  /**
8274
- * Updates the validity of the counter group based on the validity of its counters.
8275
- * This method checks all counters within the group, determines if any are invalid, and updates the group's validity state and error message accordingly.
8276
- * If any counter is invalid, it generates a combined error message from all invalid counters.
8260
+ * Synchronously recomputes this.validity/this.errorMessage from the current
8261
+ * validity of the child counters. Extracted from updateValidity() so that
8262
+ * validate() can re-apply this aggregation immediately after the shared
8263
+ * validation engine runs, instead of waiting on a deferred timer.
8277
8264
  * @returns {void}
8278
8265
  * @private
8279
8266
  */
8280
- updateValidity () {
8267
+ computeValidityFromCounters() {
8281
8268
 
8282
8269
  // We don't need to do anything if there are no counters
8283
8270
  if (!this.counters) return;
8284
8271
 
8285
- // Wait for initial validation to complete before updating validity and error message
8286
- // This is necessary because we need the initial validation to know when to reset the validity and error message
8287
- setTimeout(() => {
8272
+ // Get any invalid counters
8273
+ const invalidCounters = this.getInvalidCounters(this.counters);
8274
+
8275
+ // Determine if we are in an invalid state based on the presence of invalid counters
8276
+ const isInvalid = invalidCounters.length > 0;
8288
8277
 
8289
- // Get any invalid counters
8290
- const invalidCounters = this.getInvalidCounters(this.counters);
8278
+ // If we are in an invalid state
8279
+ if (isInvalid) {
8291
8280
 
8292
- // Determine if we are in an invalid state based on the presence of invalid counters
8293
- const isInvalid = invalidCounters.length > 0;
8281
+ // Generate the error messages as plain text, joined with sentence-ending
8282
+ // punctuation so multiple messages don't run together into one clause.
8283
+ const errorMessages = this.getErrorMessages(invalidCounters);
8284
+ const joinedMessage = errorMessages.join('. ');
8294
8285
 
8295
- // If we are in an invalid state
8296
- if (isInvalid) {
8286
+ // Set the validity and error message
8287
+ // This needs to allow for the initial validation to come through
8288
+ this.validity =
8289
+ invalidCounters[0].validity || // The first invalid counter's validity
8290
+ this.validity || // incoming validity from validation
8291
+ undefined; // fallback
8297
8292
 
8298
- // Generate the error messages
8299
- const errorMessages = this.getErrorMessages(invalidCounters);
8293
+ // Always reflect the current invalid counters' messages, even when that
8294
+ // means clearing to undefined -- falling back to the previous
8295
+ // this.errorMessage here would let a stale message from a prior,
8296
+ // different invalid cause survive a transition into a cause with no
8297
+ // message of its own (e.g. customError -> rangeOverflow).
8298
+ this.errorMessage = joinedMessage || undefined;
8299
+ }
8300
8300
 
8301
- const errorMessage = isInvalid ? this.renderHelpTextErrors(errorMessages) : this.errorMessage;
8301
+ if (!isInvalid && this.validity !== 'valid') {
8302
8302
 
8303
- // Set the validity and error message
8304
- // This needs to allow for the initial validation to come through
8305
- this.validity =
8306
- invalidCounters[0].validity || // The first invalid counter's validity
8307
- this.validity || // incoming validity from validation
8308
- undefined; // fallback
8303
+ // If there are no invalid counters, reset validity and error message
8304
+ this.validity = 'valid';
8305
+ this.errorMessage = undefined;
8306
+ }
8307
+ }
8309
8308
 
8310
- this.errorMessage =
8311
- errorMessage || // our message
8312
- this.errorMessage || // incoming message from validation
8313
- undefined; // fallback
8314
- }
8309
+ /**
8310
+ * Updates the validity of the counter group based on the validity of its counters.
8311
+ * This method checks all counters within the group, determines if any are invalid, and updates the group's validity state and error message accordingly.
8312
+ * If any counter is invalid, it generates a combined error message from all invalid counters.
8313
+ * @returns {void}
8314
+ * @private
8315
+ */
8316
+ updateValidity () {
8315
8317
 
8316
- if (!isInvalid && this.validity !== 'valid') {
8318
+ // We don't need to do anything if there are no counters
8319
+ if (!this.counters) return;
8317
8320
 
8318
- // If there are no invalid counters, reset validity and error message
8319
- this.validity = 'valid';
8320
- this.errorMessage = undefined;
8321
- }
8322
- });
8321
+ // Wait for initial validation to complete before updating validity and error message
8322
+ // This is necessary because we need the initial validation to know when to reset the validity and error message
8323
+ setTimeout(() => this.computeValidityFromCounters());
8323
8324
  }
8324
8325
 
8325
8326
  /**
@@ -8487,6 +8488,40 @@ class AuroCounterGroup extends AuroElement {
8487
8488
  */
8488
8489
  validate(force = false) {
8489
8490
  this.validation.validate(this, force);
8491
+
8492
+ // AuroFormValidation doesn't know how to derive validity from our object-valued
8493
+ // `value`, so it always resolves an otherwise-error-free group to 'valid' -- even
8494
+ // while a child counter is still invalid. Re-derive from the children's current
8495
+ // state immediately afterward so that invalid state survives forced validation,
8496
+ // and re-dispatch the validated event when the correction changes the outcome so
8497
+ // listeners like auro-form's submit path see the corrected result.
8498
+ //
8499
+ // This intentionally also runs for unforced calls (every child value change),
8500
+ // even though updateValidity()'s deferred, listener-driven aggregation computes
8501
+ // the same result a tick later: that deferred path only updates this.validity/
8502
+ // this.errorMessage, it never re-dispatches the event, so auro-form's formState
8503
+ // (and therefore the submit button's disabled state) would otherwise only ever
8504
+ // learn about a child-derived invalid state at the next forced validation --
8505
+ // not at initial load or on ordinary interaction. See docs/post-mortem/1642340.md,
8506
+ // "Iterations That Didn't Work", for the attempt to scope this to `force` and
8507
+ // why it broke that behavior.
8508
+ if (this.counters && !this.hasAttribute('error')) {
8509
+ const previousValidity = this.validity;
8510
+ const previousMessage = this.errorMessage;
8511
+
8512
+ this.computeValidityFromCounters();
8513
+
8514
+ if (this.validity !== previousValidity || this.errorMessage !== previousMessage) {
8515
+ this.dispatchEvent(new CustomEvent('auroFormElement-validated', {
8516
+ bubbles: true,
8517
+ composed: true,
8518
+ detail: {
8519
+ validity: this.validity,
8520
+ message: this.errorMessage
8521
+ }
8522
+ }));
8523
+ }
8524
+ }
8490
8525
  }
8491
8526
 
8492
8527
  /**