@aurodesignsystem-dev/auro-formkit 0.0.0-pr1595.8 → 0.0.0-pr1600.1

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 +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/customize.min.js +104 -4
  12. package/components/counter/demo/index.min.js +104 -4
  13. package/components/counter/dist/auro-counter-group.d.ts +12 -0
  14. package/components/counter/dist/auro-counter.d.ts +20 -0
  15. package/components/counter/dist/index.js +104 -4
  16. package/components/counter/dist/registered.js +104 -4
  17. package/components/datepicker/demo/customize.min.js +3 -3
  18. package/components/datepicker/demo/index.min.js +3 -3
  19. package/components/datepicker/dist/index.js +3 -3
  20. package/components/datepicker/dist/registered.js +3 -3
  21. package/components/dropdown/demo/customize.min.js +1 -1
  22. package/components/dropdown/demo/getting-started.min.js +2 -2
  23. package/components/dropdown/demo/index.min.js +1 -1
  24. package/components/dropdown/dist/index.js +1 -1
  25. package/components/dropdown/dist/registered.js +1 -1
  26. package/components/form/demo/customize.min.js +115 -15
  27. package/components/form/demo/getting-started.min.js +115 -15
  28. package/components/form/demo/index.min.js +115 -15
  29. package/components/form/demo/registerDemoDeps.min.js +115 -15
  30. package/components/input/demo/customize.min.js +1 -1
  31. package/components/input/demo/getting-started.min.js +1 -1
  32. package/components/input/demo/index.min.js +1 -1
  33. package/components/input/dist/index.js +1 -1
  34. package/components/input/dist/registered.js +1 -1
  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 +1512 -1466
  46. package/package.json +1 -1
@@ -1284,7 +1284,7 @@ class AuroHelpText extends i$2 {
1284
1284
  }
1285
1285
  }
1286
1286
 
1287
- var formkitVersion = '202608311921';
1287
+ var formkitVersion = '202608312323';
1288
1288
 
1289
1289
  // Copyright (c) 2026 Alaska Airlines. All rights reserved. Licensed under the Apache-2.0 license
1290
1290
  // See LICENSE in the project root for license information.
@@ -1284,7 +1284,7 @@ class AuroHelpText extends i$2 {
1284
1284
  }
1285
1285
  }
1286
1286
 
1287
- var formkitVersion = '202608311921';
1287
+ var formkitVersion = '202608312323';
1288
1288
 
1289
1289
  // Copyright (c) 2026 Alaska Airlines. All rights reserved. Licensed under the Apache-2.0 license
1290
1290
  // See LICENSE in the project root for license information.
@@ -1284,7 +1284,7 @@ class AuroHelpText extends i$2 {
1284
1284
  }
1285
1285
  }
1286
1286
 
1287
- var formkitVersion = '202608311921';
1287
+ var formkitVersion = '202608312323';
1288
1288
 
1289
1289
  // Copyright (c) 2026 Alaska Airlines. All rights reserved. Licensed under the Apache-2.0 license
1290
1290
  // See LICENSE in the project root for license information.
@@ -1237,7 +1237,7 @@ class AuroHelpText extends LitElement {
1237
1237
  }
1238
1238
  }
1239
1239
 
1240
- var formkitVersion = '202608311921';
1240
+ var formkitVersion = '202608312323';
1241
1241
 
1242
1242
  // Copyright (c) 2026 Alaska Airlines. All rights reserved. Licensed under the Apache-2.0 license
1243
1243
  // See LICENSE in the project root for license information.
@@ -1237,7 +1237,7 @@ class AuroHelpText extends LitElement {
1237
1237
  }
1238
1238
  }
1239
1239
 
1240
- var formkitVersion = '202608311921';
1240
+ var formkitVersion = '202608312323';
1241
1241
 
1242
1242
  // Copyright (c) 2026 Alaska Airlines. All rights reserved. Licensed under the Apache-2.0 license
1243
1243
  // See LICENSE in the project root for license information.
@@ -5066,7 +5066,7 @@ let AuroHelpText$2 = class AuroHelpText extends i$3 {
5066
5066
  }
5067
5067
  };
5068
5068
 
5069
- var formkitVersion$2 = '202608311921';
5069
+ var formkitVersion$2 = '202608312323';
5070
5070
 
5071
5071
  /**
5072
5072
  * AuroElement is the shared base class for layout-aware Auro form components.
@@ -18935,7 +18935,7 @@ let AuroHelpText$1 = class AuroHelpText extends i$3 {
18935
18935
  }
18936
18936
  };
18937
18937
 
18938
- var formkitVersion$1 = '202608311921';
18938
+ var formkitVersion$1 = '202608312323';
18939
18939
 
18940
18940
  // Copyright (c) 2025 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
18941
18941
  // See LICENSE in the project root for license information.
@@ -20127,7 +20127,7 @@ class AuroBibtemplate extends i$3 {
20127
20127
  }
20128
20128
  }
20129
20129
 
20130
- var formkitVersion = '202608311921';
20130
+ var formkitVersion = '202608312323';
20131
20131
 
20132
20132
  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}`;
20133
20133
 
@@ -5066,7 +5066,7 @@ let AuroHelpText$2 = class AuroHelpText extends i$3 {
5066
5066
  }
5067
5067
  };
5068
5068
 
5069
- var formkitVersion$2 = '202608311921';
5069
+ var formkitVersion$2 = '202608312323';
5070
5070
 
5071
5071
  /**
5072
5072
  * AuroElement is the shared base class for layout-aware Auro form components.
@@ -18935,7 +18935,7 @@ let AuroHelpText$1 = class AuroHelpText extends i$3 {
18935
18935
  }
18936
18936
  };
18937
18937
 
18938
- var formkitVersion$1 = '202608311921';
18938
+ var formkitVersion$1 = '202608312323';
18939
18939
 
18940
18940
  // Copyright (c) 2025 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
18941
18941
  // See LICENSE in the project root for license information.
@@ -20127,7 +20127,7 @@ class AuroBibtemplate extends i$3 {
20127
20127
  }
20128
20128
  }
20129
20129
 
20130
- var formkitVersion = '202608311921';
20130
+ var formkitVersion = '202608312323';
20131
20131
 
20132
20132
  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}`;
20133
20133
 
@@ -5081,7 +5081,7 @@ let AuroHelpText$2 = class AuroHelpText extends i$3 {
5081
5081
  }
5082
5082
  };
5083
5083
 
5084
- var formkitVersion$2 = '202608311921';
5084
+ var formkitVersion$2 = '202608312323';
5085
5085
 
5086
5086
  /**
5087
5087
  * AuroElement is the shared base class for layout-aware Auro form components.
@@ -18950,7 +18950,7 @@ let AuroHelpText$1 = class AuroHelpText extends i$3 {
18950
18950
  }
18951
18951
  };
18952
18952
 
18953
- var formkitVersion$1 = '202608311921';
18953
+ var formkitVersion$1 = '202608312323';
18954
18954
 
18955
18955
  // Copyright (c) 2025 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
18956
18956
  // See LICENSE in the project root for license information.
@@ -20142,7 +20142,7 @@ class AuroBibtemplate extends i$3 {
20142
20142
  }
20143
20143
  }
20144
20144
 
20145
- var formkitVersion = '202608311921';
20145
+ var formkitVersion = '202608312323';
20146
20146
 
20147
20147
  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}`;
20148
20148
 
@@ -4999,7 +4999,7 @@ let AuroHelpText$2 = class AuroHelpText extends LitElement {
4999
4999
  }
5000
5000
  };
5001
5001
 
5002
- var formkitVersion$2 = '202608311921';
5002
+ var formkitVersion$2 = '202608312323';
5003
5003
 
5004
5004
  /**
5005
5005
  * AuroElement is the shared base class for layout-aware Auro form components.
@@ -18861,7 +18861,7 @@ let AuroHelpText$1 = class AuroHelpText extends LitElement {
18861
18861
  }
18862
18862
  };
18863
18863
 
18864
- var formkitVersion$1 = '202608311921';
18864
+ var formkitVersion$1 = '202608312323';
18865
18865
 
18866
18866
  // Copyright (c) 2025 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
18867
18867
  // See LICENSE in the project root for license information.
@@ -20053,7 +20053,7 @@ class AuroBibtemplate extends LitElement {
20053
20053
  }
20054
20054
  }
20055
20055
 
20056
- var formkitVersion = '202608311921';
20056
+ var formkitVersion = '202608312323';
20057
20057
 
20058
20058
  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}`;
20059
20059
 
@@ -4999,7 +4999,7 @@ let AuroHelpText$2 = class AuroHelpText extends LitElement {
4999
4999
  }
5000
5000
  };
5001
5001
 
5002
- var formkitVersion$2 = '202608311921';
5002
+ var formkitVersion$2 = '202608312323';
5003
5003
 
5004
5004
  /**
5005
5005
  * AuroElement is the shared base class for layout-aware Auro form components.
@@ -18861,7 +18861,7 @@ let AuroHelpText$1 = class AuroHelpText extends LitElement {
18861
18861
  }
18862
18862
  };
18863
18863
 
18864
- var formkitVersion$1 = '202608311921';
18864
+ var formkitVersion$1 = '202608312323';
18865
18865
 
18866
18866
  // Copyright (c) 2025 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
18867
18867
  // See LICENSE in the project root for license information.
@@ -20053,7 +20053,7 @@ class AuroBibtemplate extends LitElement {
20053
20053
  }
20054
20054
  }
20055
20055
 
20056
- var formkitVersion = '202608311921';
20056
+ var formkitVersion = '202608312323';
20057
20057
 
20058
20058
  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}`;
20059
20059
 
@@ -1127,7 +1127,7 @@ let AuroHelpText$1 = class AuroHelpText extends i$2 {
1127
1127
  }
1128
1128
  };
1129
1129
 
1130
- var formkitVersion$1 = '202608311921';
1130
+ var formkitVersion$1 = '202608312323';
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.
@@ -1411,6 +1411,41 @@ class AuroCounter extends i$2 {
1411
1411
  this.value -= value !== undefined ? value : 1;
1412
1412
  }
1413
1413
 
1414
+ /**
1415
+ * Moves focus to the spinbutton control container.
1416
+ * The +/- buttons are internal `tabindex="-1"` controls; the container is the
1417
+ * widget's single focusable element. `focusVisible: true` forces the container's
1418
+ * `:focus-visible` ring to render even though the interaction was a pointer
1419
+ * click, so focus stays visible on the counter after using its buttons.
1420
+ * @private
1421
+ */
1422
+ focusControl() {
1423
+ const control = this.shadowRoot?.querySelector('[part="counterControl"]');
1424
+ if (control && !this.disabled) {
1425
+ // `focusVisible` is a progressive enhancement: it is not yet in the standard
1426
+ // FocusOptions interface (Chrome 86+, Firefox 116+, Safari 15.4+). Browsers
1427
+ // that do not recognize it still move focus correctly — they simply do not
1428
+ // render the `:focus-visible` ring. Do not treat a missing ring on an older
1429
+ // engine as a regression.
1430
+ control.focus({ focusVisible: true });
1431
+ }
1432
+ }
1433
+
1434
+ /**
1435
+ * Handles a pointer click on a control button.
1436
+ * A pointer click focuses the clicked button, so if the value change disables
1437
+ * that button at an extreme the browser would drop focus to the document body.
1438
+ * Move focus to the spinbutton container first, then change the value: focus is
1439
+ * no longer on the button when it becomes disabled, so it is never lost and the
1440
+ * counter (and any enclosing dropdown) stays operable (AB#1634231).
1441
+ * @param {'increment' | 'decrement'} action - The control action to perform.
1442
+ * @private
1443
+ */
1444
+ handleControlClick(action) {
1445
+ this.focusControl();
1446
+ this[action]();
1447
+ }
1448
+
1414
1449
  /**
1415
1450
  * Initializes the value of the counter.
1416
1451
  * If the current value is undefined, it sets the value to the minimum value.
@@ -1553,7 +1588,7 @@ class AuroCounter extends i$2 {
1553
1588
  .tabindex="${'-1'}"
1554
1589
  appearance="${this.onDark ? 'inverse' : this.appearance}"
1555
1590
  part="controlMinus"
1556
- @click="${() => this.decrement()}"
1591
+ @click="${() => this.handleControlClick('decrement')}"
1557
1592
  ?disabled="${this.disabled || this.disableMin || this.isIncrementDisabled(this.min)}"
1558
1593
  >
1559
1594
  <${this.iconTag} class="controlIcon" customSvg> ${IconUtil.generateSvgHtml(minusIcon)} </${this.iconTag}>
@@ -1567,7 +1602,7 @@ class AuroCounter extends i$2 {
1567
1602
  .tabindex="${'-1'}"
1568
1603
  appearance="${this.onDark ? 'inverse' : this.appearance}"
1569
1604
  part="controlPlus"
1570
- @click="${() => this.increment()}"
1605
+ @click="${() => this.handleControlClick('increment')}"
1571
1606
  ?disabled="${this.disabled || this.disableMax || this.isIncrementDisabled(this.max)}"
1572
1607
  >
1573
1608
  <${this.iconTag} class="controlIcon" customSvg> ${IconUtil.generateSvgHtml(plusIcon)} </${this.iconTag}>
@@ -5399,7 +5434,7 @@ class AuroHelpText extends i$2 {
5399
5434
  }
5400
5435
  }
5401
5436
 
5402
- var formkitVersion = '202608311921';
5437
+ var formkitVersion = '202608312323';
5403
5438
 
5404
5439
  /**
5405
5440
  * AuroElement is the shared base class for layout-aware Auro form components.
@@ -7575,6 +7610,16 @@ class AuroCounterGroup extends AuroElement {
7575
7610
  /** @private */
7576
7611
  this.updateValidity = this.updateValidity.bind(this);
7577
7612
 
7613
+ /**
7614
+ * Whether the most recent pointerdown began inside this group's composed tree.
7615
+ * Used to keep the dropdown open when a counter button disables itself on click.
7616
+ * @private
7617
+ */
7618
+ this.pointerdownInsideGroup = false;
7619
+
7620
+ /** @private */
7621
+ this.trackPointerdown = this.trackPointerdown.bind(this);
7622
+
7578
7623
  /**
7579
7624
  * Generate unique names for dependency components.
7580
7625
  * @private
@@ -7960,6 +8005,35 @@ class AuroCounterGroup extends AuroElement {
7960
8005
  });
7961
8006
  }
7962
8007
 
8008
+ /**
8009
+ * Records whether a pointerdown originated inside this group's composed tree.
8010
+ * @param {PointerEvent} event - The pointerdown event.
8011
+ * @private
8012
+ */
8013
+ trackPointerdown(event) {
8014
+ this.pointerdownInsideGroup = event.composedPath().includes(this);
8015
+ }
8016
+
8017
+ connectedCallback() {
8018
+ super.connectedCallback();
8019
+
8020
+ // firstUpdated performs the initial pointerdown registration, but it runs
8021
+ // only once per instance and disconnectedCallback removes the listener. On a
8022
+ // later reconnect (SPA route change, keyed remount) firstUpdated does not run
8023
+ // again, so re-add the document-level listener here. hasUpdated is false
8024
+ // during the initial connect — firstUpdated owns that case — and true on any
8025
+ // reconnect. remove-before-add keeps it idempotent. (AB#1634231)
8026
+ if (this.hasUpdated && this.isDropdown) {
8027
+ document.removeEventListener('pointerdown', this.trackPointerdown, true);
8028
+ document.addEventListener('pointerdown', this.trackPointerdown, true);
8029
+ }
8030
+ }
8031
+
8032
+ disconnectedCallback() {
8033
+ super.disconnectedCallback();
8034
+ document.removeEventListener('pointerdown', this.trackPointerdown, true);
8035
+ }
8036
+
7963
8037
  /**
7964
8038
  * Hides the dropdown bib if its open.
7965
8039
  * @returns {void}
@@ -8157,6 +8231,12 @@ class AuroCounterGroup extends AuroElement {
8157
8231
  if (this.isDropdown) {
8158
8232
  applyKeyboardStrategy$1(this, counterGroupKeyboardStrategy);
8159
8233
 
8234
+ // Track where the most recent pointer interaction began so the focusout
8235
+ // handler below can tell a counter-button click apart from an outside
8236
+ // click. Capture phase + composedPath so clicks inside the bib's nested
8237
+ // shadow roots still resolve to this group. (AB#1634231)
8238
+ document.addEventListener('pointerdown', this.trackPointerdown, true);
8239
+
8160
8240
  // noHideOnThisFocusLoss=true on the dropdown prevents handleFocusLoss from
8161
8241
  // closing the bib when focus moves out via Tab. Close explicitly via focusout:
8162
8242
  // if relatedTarget is outside the counter-group's light DOM, focus has left.
@@ -8164,9 +8244,29 @@ class AuroCounterGroup extends AuroElement {
8164
8244
  if (!this.dropdown?.isPopoverVisible || this.dropdown?.isBibFullscreen) {
8165
8245
  return;
8166
8246
  }
8247
+
8248
+ // Focus moved to a specific element still inside the group — keep the bib open.
8167
8249
  if (event.relatedTarget && this.contains(event.relatedTarget)) {
8168
8250
  return;
8169
8251
  }
8252
+
8253
+ // A null relatedTarget means focus was dropped without landing on a
8254
+ // specific element. This fires when a counter's +/- button becomes
8255
+ // disabled at an extreme immediately after being clicked: the browser
8256
+ // blurs the now-disabled button, closing the bib as an unwanted side
8257
+ // effect of using the counters. If that blur was triggered by a pointer
8258
+ // interaction that began inside the group, keep the bib open. A genuine
8259
+ // outside click also yields a null relatedTarget, but its pointerdown
8260
+ // originated outside the group, so we still close. (AB#1634231)
8261
+ if (!event.relatedTarget) {
8262
+ if (this.pointerdownInsideGroup) {
8263
+ return;
8264
+ }
8265
+ this.hideBib();
8266
+ return;
8267
+ }
8268
+
8269
+ // Focus moved to a known element outside the group (e.g. Tab to the next field).
8170
8270
  this.hideBib();
8171
8271
  });
8172
8272
  }
@@ -1127,7 +1127,7 @@ let AuroHelpText$1 = class AuroHelpText extends i$2 {
1127
1127
  }
1128
1128
  };
1129
1129
 
1130
- var formkitVersion$1 = '202608311921';
1130
+ var formkitVersion$1 = '202608312323';
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.
@@ -1411,6 +1411,41 @@ class AuroCounter extends i$2 {
1411
1411
  this.value -= value !== undefined ? value : 1;
1412
1412
  }
1413
1413
 
1414
+ /**
1415
+ * Moves focus to the spinbutton control container.
1416
+ * The +/- buttons are internal `tabindex="-1"` controls; the container is the
1417
+ * widget's single focusable element. `focusVisible: true` forces the container's
1418
+ * `:focus-visible` ring to render even though the interaction was a pointer
1419
+ * click, so focus stays visible on the counter after using its buttons.
1420
+ * @private
1421
+ */
1422
+ focusControl() {
1423
+ const control = this.shadowRoot?.querySelector('[part="counterControl"]');
1424
+ if (control && !this.disabled) {
1425
+ // `focusVisible` is a progressive enhancement: it is not yet in the standard
1426
+ // FocusOptions interface (Chrome 86+, Firefox 116+, Safari 15.4+). Browsers
1427
+ // that do not recognize it still move focus correctly — they simply do not
1428
+ // render the `:focus-visible` ring. Do not treat a missing ring on an older
1429
+ // engine as a regression.
1430
+ control.focus({ focusVisible: true });
1431
+ }
1432
+ }
1433
+
1434
+ /**
1435
+ * Handles a pointer click on a control button.
1436
+ * A pointer click focuses the clicked button, so if the value change disables
1437
+ * that button at an extreme the browser would drop focus to the document body.
1438
+ * Move focus to the spinbutton container first, then change the value: focus is
1439
+ * no longer on the button when it becomes disabled, so it is never lost and the
1440
+ * counter (and any enclosing dropdown) stays operable (AB#1634231).
1441
+ * @param {'increment' | 'decrement'} action - The control action to perform.
1442
+ * @private
1443
+ */
1444
+ handleControlClick(action) {
1445
+ this.focusControl();
1446
+ this[action]();
1447
+ }
1448
+
1414
1449
  /**
1415
1450
  * Initializes the value of the counter.
1416
1451
  * If the current value is undefined, it sets the value to the minimum value.
@@ -1553,7 +1588,7 @@ class AuroCounter extends i$2 {
1553
1588
  .tabindex="${'-1'}"
1554
1589
  appearance="${this.onDark ? 'inverse' : this.appearance}"
1555
1590
  part="controlMinus"
1556
- @click="${() => this.decrement()}"
1591
+ @click="${() => this.handleControlClick('decrement')}"
1557
1592
  ?disabled="${this.disabled || this.disableMin || this.isIncrementDisabled(this.min)}"
1558
1593
  >
1559
1594
  <${this.iconTag} class="controlIcon" customSvg> ${IconUtil.generateSvgHtml(minusIcon)} </${this.iconTag}>
@@ -1567,7 +1602,7 @@ class AuroCounter extends i$2 {
1567
1602
  .tabindex="${'-1'}"
1568
1603
  appearance="${this.onDark ? 'inverse' : this.appearance}"
1569
1604
  part="controlPlus"
1570
- @click="${() => this.increment()}"
1605
+ @click="${() => this.handleControlClick('increment')}"
1571
1606
  ?disabled="${this.disabled || this.disableMax || this.isIncrementDisabled(this.max)}"
1572
1607
  >
1573
1608
  <${this.iconTag} class="controlIcon" customSvg> ${IconUtil.generateSvgHtml(plusIcon)} </${this.iconTag}>
@@ -5399,7 +5434,7 @@ class AuroHelpText extends i$2 {
5399
5434
  }
5400
5435
  }
5401
5436
 
5402
- var formkitVersion = '202608311921';
5437
+ var formkitVersion = '202608312323';
5403
5438
 
5404
5439
  /**
5405
5440
  * AuroElement is the shared base class for layout-aware Auro form components.
@@ -7575,6 +7610,16 @@ class AuroCounterGroup extends AuroElement {
7575
7610
  /** @private */
7576
7611
  this.updateValidity = this.updateValidity.bind(this);
7577
7612
 
7613
+ /**
7614
+ * Whether the most recent pointerdown began inside this group's composed tree.
7615
+ * Used to keep the dropdown open when a counter button disables itself on click.
7616
+ * @private
7617
+ */
7618
+ this.pointerdownInsideGroup = false;
7619
+
7620
+ /** @private */
7621
+ this.trackPointerdown = this.trackPointerdown.bind(this);
7622
+
7578
7623
  /**
7579
7624
  * Generate unique names for dependency components.
7580
7625
  * @private
@@ -7960,6 +8005,35 @@ class AuroCounterGroup extends AuroElement {
7960
8005
  });
7961
8006
  }
7962
8007
 
8008
+ /**
8009
+ * Records whether a pointerdown originated inside this group's composed tree.
8010
+ * @param {PointerEvent} event - The pointerdown event.
8011
+ * @private
8012
+ */
8013
+ trackPointerdown(event) {
8014
+ this.pointerdownInsideGroup = event.composedPath().includes(this);
8015
+ }
8016
+
8017
+ connectedCallback() {
8018
+ super.connectedCallback();
8019
+
8020
+ // firstUpdated performs the initial pointerdown registration, but it runs
8021
+ // only once per instance and disconnectedCallback removes the listener. On a
8022
+ // later reconnect (SPA route change, keyed remount) firstUpdated does not run
8023
+ // again, so re-add the document-level listener here. hasUpdated is false
8024
+ // during the initial connect — firstUpdated owns that case — and true on any
8025
+ // reconnect. remove-before-add keeps it idempotent. (AB#1634231)
8026
+ if (this.hasUpdated && this.isDropdown) {
8027
+ document.removeEventListener('pointerdown', this.trackPointerdown, true);
8028
+ document.addEventListener('pointerdown', this.trackPointerdown, true);
8029
+ }
8030
+ }
8031
+
8032
+ disconnectedCallback() {
8033
+ super.disconnectedCallback();
8034
+ document.removeEventListener('pointerdown', this.trackPointerdown, true);
8035
+ }
8036
+
7963
8037
  /**
7964
8038
  * Hides the dropdown bib if its open.
7965
8039
  * @returns {void}
@@ -8157,6 +8231,12 @@ class AuroCounterGroup extends AuroElement {
8157
8231
  if (this.isDropdown) {
8158
8232
  applyKeyboardStrategy$1(this, counterGroupKeyboardStrategy);
8159
8233
 
8234
+ // Track where the most recent pointer interaction began so the focusout
8235
+ // handler below can tell a counter-button click apart from an outside
8236
+ // click. Capture phase + composedPath so clicks inside the bib's nested
8237
+ // shadow roots still resolve to this group. (AB#1634231)
8238
+ document.addEventListener('pointerdown', this.trackPointerdown, true);
8239
+
8160
8240
  // noHideOnThisFocusLoss=true on the dropdown prevents handleFocusLoss from
8161
8241
  // closing the bib when focus moves out via Tab. Close explicitly via focusout:
8162
8242
  // if relatedTarget is outside the counter-group's light DOM, focus has left.
@@ -8164,9 +8244,29 @@ class AuroCounterGroup extends AuroElement {
8164
8244
  if (!this.dropdown?.isPopoverVisible || this.dropdown?.isBibFullscreen) {
8165
8245
  return;
8166
8246
  }
8247
+
8248
+ // Focus moved to a specific element still inside the group — keep the bib open.
8167
8249
  if (event.relatedTarget && this.contains(event.relatedTarget)) {
8168
8250
  return;
8169
8251
  }
8252
+
8253
+ // A null relatedTarget means focus was dropped without landing on a
8254
+ // specific element. This fires when a counter's +/- button becomes
8255
+ // disabled at an extreme immediately after being clicked: the browser
8256
+ // blurs the now-disabled button, closing the bib as an unwanted side
8257
+ // effect of using the counters. If that blur was triggered by a pointer
8258
+ // interaction that began inside the group, keep the bib open. A genuine
8259
+ // outside click also yields a null relatedTarget, but its pointerdown
8260
+ // originated outside the group, so we still close. (AB#1634231)
8261
+ if (!event.relatedTarget) {
8262
+ if (this.pointerdownInsideGroup) {
8263
+ return;
8264
+ }
8265
+ this.hideBib();
8266
+ return;
8267
+ }
8268
+
8269
+ // Focus moved to a known element outside the group (e.g. Tab to the next field).
8170
8270
  this.hideBib();
8171
8271
  });
8172
8272
  }
@@ -239,6 +239,18 @@ export class AuroCounterGroup extends AuroElement {
239
239
  * @private
240
240
  */
241
241
  private updateValidity;
242
+ /**
243
+ * Whether the most recent pointerdown began inside this group's composed tree.
244
+ * Used to keep the dropdown open when a counter button disables itself on click.
245
+ * @private
246
+ */
247
+ private pointerdownInsideGroup;
248
+ /**
249
+ * Records whether a pointerdown originated inside this group's composed tree.
250
+ * @param {PointerEvent} event - The pointerdown event.
251
+ * @private
252
+ */
253
+ private trackPointerdown;
242
254
  /**
243
255
  * Dynamically generated dropdown tag.
244
256
  * @private
@@ -90,6 +90,26 @@ export class AuroCounter extends LitElement {
90
90
  * @returns {void}
91
91
  */
92
92
  decrement(value?: number): void;
93
+ /**
94
+ * Moves focus to the spinbutton control container.
95
+ * The +/- buttons are internal `tabindex="-1"` controls; the container is the
96
+ * widget's single focusable element. `focusVisible: true` forces the container's
97
+ * `:focus-visible` ring to render even though the interaction was a pointer
98
+ * click, so focus stays visible on the counter after using its buttons.
99
+ * @private
100
+ */
101
+ private focusControl;
102
+ /**
103
+ * Handles a pointer click on a control button.
104
+ * A pointer click focuses the clicked button, so if the value change disables
105
+ * that button at an extreme the browser would drop focus to the document body.
106
+ * Move focus to the spinbutton container first, then change the value: focus is
107
+ * no longer on the button when it becomes disabled, so it is never lost and the
108
+ * counter (and any enclosing dropdown) stays operable (AB#1634231).
109
+ * @param {'increment' | 'decrement'} action - The control action to perform.
110
+ * @private
111
+ */
112
+ private handleControlClick;
93
113
  /**
94
114
  * Initializes the value of the counter.
95
115
  * If the current value is undefined, it sets the value to the minimum value.