@aurodesignsystem-dev/auro-formkit 0.0.0-pr1595.7 → 0.0.0-pr1600.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 (50) hide show
  1. package/components/checkbox/demo/api.md +1 -1
  2. package/components/checkbox/demo/customize.min.js +3 -5
  3. package/components/checkbox/demo/getting-started.min.js +3 -5
  4. package/components/checkbox/demo/index.min.js +3 -5
  5. package/components/checkbox/dist/auro-checkbox.d.ts +2 -2
  6. package/components/checkbox/dist/index.js +3 -5
  7. package/components/checkbox/dist/registered.js +3 -5
  8. package/components/combobox/demo/customize.min.js +14 -3
  9. package/components/combobox/demo/getting-started.min.js +14 -3
  10. package/components/combobox/demo/index.min.js +14 -3
  11. package/components/combobox/dist/auro-combobox.d.ts +10 -5
  12. package/components/combobox/dist/index.js +14 -3
  13. package/components/combobox/dist/registered.js +14 -3
  14. package/components/counter/demo/customize.min.js +87 -4
  15. package/components/counter/demo/index.min.js +87 -4
  16. package/components/counter/dist/auro-counter-group.d.ts +16 -2
  17. package/components/counter/dist/auro-counter.d.ts +20 -0
  18. package/components/counter/dist/index.js +87 -4
  19. package/components/counter/dist/registered.js +87 -4
  20. package/components/datepicker/demo/customize.min.js +6 -3
  21. package/components/datepicker/demo/index.min.js +6 -3
  22. package/components/datepicker/dist/auro-datepicker.d.ts +4 -2
  23. package/components/datepicker/dist/index.js +6 -3
  24. package/components/datepicker/dist/registered.js +6 -3
  25. package/components/dropdown/demo/customize.min.js +1 -1
  26. package/components/dropdown/demo/getting-started.min.js +2 -2
  27. package/components/dropdown/demo/index.min.js +1 -1
  28. package/components/dropdown/dist/index.js +1 -1
  29. package/components/dropdown/dist/registered.js +1 -1
  30. package/components/form/demo/customize.min.js +114 -19
  31. package/components/form/demo/getting-started.min.js +114 -19
  32. package/components/form/demo/index.min.js +114 -19
  33. package/components/form/demo/registerDemoDeps.min.js +114 -19
  34. package/components/input/demo/customize.min.js +1 -1
  35. package/components/input/demo/getting-started.min.js +1 -1
  36. package/components/input/demo/index.min.js +1 -1
  37. package/components/input/dist/index.js +1 -1
  38. package/components/input/dist/registered.js +1 -1
  39. package/components/radio/demo/customize.min.js +1 -1
  40. package/components/radio/demo/getting-started.min.js +1 -1
  41. package/components/radio/demo/index.min.js +1 -1
  42. package/components/radio/dist/index.js +1 -1
  43. package/components/radio/dist/registered.js +1 -1
  44. package/components/select/demo/customize.min.js +2 -2
  45. package/components/select/demo/getting-started.min.js +2 -2
  46. package/components/select/demo/index.min.js +2 -2
  47. package/components/select/dist/index.js +2 -2
  48. package/components/select/dist/registered.js +2 -2
  49. package/custom-elements.json +55 -9
  50. package/package.json +1 -1
@@ -1127,7 +1127,7 @@ let AuroHelpText$1 = class AuroHelpText extends i$2 {
1127
1127
  }
1128
1128
  };
1129
1129
 
1130
- var formkitVersion$1 = '202608300438';
1130
+ var formkitVersion$1 = '202608312237';
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,36 @@ 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
+ control.focus({ focusVisible: true });
1426
+ }
1427
+ }
1428
+
1429
+ /**
1430
+ * Handles a pointer click on a control button.
1431
+ * A pointer click focuses the clicked button, so if the value change disables
1432
+ * that button at an extreme the browser would drop focus to the document body.
1433
+ * Move focus to the spinbutton container first, then change the value: focus is
1434
+ * no longer on the button when it becomes disabled, so it is never lost and the
1435
+ * counter (and any enclosing dropdown) stays operable (AB#1634231).
1436
+ * @param {'increment' | 'decrement'} action - The control action to perform.
1437
+ * @private
1438
+ */
1439
+ handleControlClick(action) {
1440
+ this.focusControl();
1441
+ this[action]();
1442
+ }
1443
+
1414
1444
  /**
1415
1445
  * Initializes the value of the counter.
1416
1446
  * If the current value is undefined, it sets the value to the minimum value.
@@ -1553,7 +1583,7 @@ class AuroCounter extends i$2 {
1553
1583
  .tabindex="${'-1'}"
1554
1584
  appearance="${this.onDark ? 'inverse' : this.appearance}"
1555
1585
  part="controlMinus"
1556
- @click="${() => this.decrement()}"
1586
+ @click="${() => this.handleControlClick('decrement')}"
1557
1587
  ?disabled="${this.disabled || this.disableMin || this.isIncrementDisabled(this.min)}"
1558
1588
  >
1559
1589
  <${this.iconTag} class="controlIcon" customSvg> ${IconUtil.generateSvgHtml(minusIcon)} </${this.iconTag}>
@@ -1567,7 +1597,7 @@ class AuroCounter extends i$2 {
1567
1597
  .tabindex="${'-1'}"
1568
1598
  appearance="${this.onDark ? 'inverse' : this.appearance}"
1569
1599
  part="controlPlus"
1570
- @click="${() => this.increment()}"
1600
+ @click="${() => this.handleControlClick('increment')}"
1571
1601
  ?disabled="${this.disabled || this.disableMax || this.isIncrementDisabled(this.max)}"
1572
1602
  >
1573
1603
  <${this.iconTag} class="controlIcon" customSvg> ${IconUtil.generateSvgHtml(plusIcon)} </${this.iconTag}>
@@ -5399,7 +5429,7 @@ class AuroHelpText extends i$2 {
5399
5429
  }
5400
5430
  }
5401
5431
 
5402
- var formkitVersion = '202608300438';
5432
+ var formkitVersion = '202608312237';
5403
5433
 
5404
5434
  /**
5405
5435
  * AuroElement is the shared base class for layout-aware Auro form components.
@@ -7538,12 +7568,15 @@ class AuroCounterGroup extends AuroElement {
7538
7568
 
7539
7569
  this.matchWidth = false;
7540
7570
  this.isDropdown = false;
7571
+
7572
+ /** @type {'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'disabled'} */
7541
7573
  this.fullscreenBreakpoint = 'sm';
7542
7574
  this.largeFullscreenHeadline = false;
7543
7575
  this.autoPlacement = false;
7544
7576
  this.noFlip = false;
7545
7577
  this.shift = false;
7546
7578
 
7579
+ /** @type {'top' | 'right' | 'bottom' | 'left' | 'bottom-start' | 'top-start' | 'top-end' | 'right-start' | 'right-end' | 'bottom-end' | 'left-start' | 'left-end'} */
7547
7580
  this.placement = 'bottom-start';
7548
7581
 
7549
7582
  /**
@@ -7572,6 +7605,16 @@ class AuroCounterGroup extends AuroElement {
7572
7605
  /** @private */
7573
7606
  this.updateValidity = this.updateValidity.bind(this);
7574
7607
 
7608
+ /**
7609
+ * Whether the most recent pointerdown began inside this group's composed tree.
7610
+ * Used to keep the dropdown open when a counter button disables itself on click.
7611
+ * @private
7612
+ */
7613
+ this.pointerdownInsideGroup = false;
7614
+
7615
+ /** @private */
7616
+ this.trackPointerdown = this.trackPointerdown.bind(this);
7617
+
7575
7618
  /**
7576
7619
  * Generate unique names for dependency components.
7577
7620
  * @private
@@ -7957,6 +8000,20 @@ class AuroCounterGroup extends AuroElement {
7957
8000
  });
7958
8001
  }
7959
8002
 
8003
+ /**
8004
+ * Records whether a pointerdown originated inside this group's composed tree.
8005
+ * @param {PointerEvent} event - The pointerdown event.
8006
+ * @private
8007
+ */
8008
+ trackPointerdown(event) {
8009
+ this.pointerdownInsideGroup = event.composedPath().includes(this);
8010
+ }
8011
+
8012
+ disconnectedCallback() {
8013
+ super.disconnectedCallback();
8014
+ document.removeEventListener('pointerdown', this.trackPointerdown, true);
8015
+ }
8016
+
7960
8017
  /**
7961
8018
  * Hides the dropdown bib if its open.
7962
8019
  * @returns {void}
@@ -8154,6 +8211,12 @@ class AuroCounterGroup extends AuroElement {
8154
8211
  if (this.isDropdown) {
8155
8212
  applyKeyboardStrategy$1(this, counterGroupKeyboardStrategy);
8156
8213
 
8214
+ // Track where the most recent pointer interaction began so the focusout
8215
+ // handler below can tell a counter-button click apart from an outside
8216
+ // click. Capture phase + composedPath so clicks inside the bib's nested
8217
+ // shadow roots still resolve to this group. (AB#1634231)
8218
+ document.addEventListener('pointerdown', this.trackPointerdown, true);
8219
+
8157
8220
  // noHideOnThisFocusLoss=true on the dropdown prevents handleFocusLoss from
8158
8221
  // closing the bib when focus moves out via Tab. Close explicitly via focusout:
8159
8222
  // if relatedTarget is outside the counter-group's light DOM, focus has left.
@@ -8161,9 +8224,29 @@ class AuroCounterGroup extends AuroElement {
8161
8224
  if (!this.dropdown?.isPopoverVisible || this.dropdown?.isBibFullscreen) {
8162
8225
  return;
8163
8226
  }
8227
+
8228
+ // Focus moved to a specific element still inside the group — keep the bib open.
8164
8229
  if (event.relatedTarget && this.contains(event.relatedTarget)) {
8165
8230
  return;
8166
8231
  }
8232
+
8233
+ // A null relatedTarget means focus was dropped without landing on a
8234
+ // specific element. This fires when a counter's +/- button becomes
8235
+ // disabled at an extreme immediately after being clicked: the browser
8236
+ // blurs the now-disabled button, closing the bib as an unwanted side
8237
+ // effect of using the counters. If that blur was triggered by a pointer
8238
+ // interaction that began inside the group, keep the bib open. A genuine
8239
+ // outside click also yields a null relatedTarget, but its pointerdown
8240
+ // originated outside the group, so we still close. (AB#1634231)
8241
+ if (!event.relatedTarget) {
8242
+ if (this.pointerdownInsideGroup) {
8243
+ return;
8244
+ }
8245
+ this.hideBib();
8246
+ return;
8247
+ }
8248
+
8249
+ // Focus moved to a known element outside the group (e.g. Tab to the next field).
8167
8250
  this.hideBib();
8168
8251
  });
8169
8252
  }
@@ -1127,7 +1127,7 @@ let AuroHelpText$1 = class AuroHelpText extends i$2 {
1127
1127
  }
1128
1128
  };
1129
1129
 
1130
- var formkitVersion$1 = '202608300438';
1130
+ var formkitVersion$1 = '202608312237';
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,36 @@ 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
+ control.focus({ focusVisible: true });
1426
+ }
1427
+ }
1428
+
1429
+ /**
1430
+ * Handles a pointer click on a control button.
1431
+ * A pointer click focuses the clicked button, so if the value change disables
1432
+ * that button at an extreme the browser would drop focus to the document body.
1433
+ * Move focus to the spinbutton container first, then change the value: focus is
1434
+ * no longer on the button when it becomes disabled, so it is never lost and the
1435
+ * counter (and any enclosing dropdown) stays operable (AB#1634231).
1436
+ * @param {'increment' | 'decrement'} action - The control action to perform.
1437
+ * @private
1438
+ */
1439
+ handleControlClick(action) {
1440
+ this.focusControl();
1441
+ this[action]();
1442
+ }
1443
+
1414
1444
  /**
1415
1445
  * Initializes the value of the counter.
1416
1446
  * If the current value is undefined, it sets the value to the minimum value.
@@ -1553,7 +1583,7 @@ class AuroCounter extends i$2 {
1553
1583
  .tabindex="${'-1'}"
1554
1584
  appearance="${this.onDark ? 'inverse' : this.appearance}"
1555
1585
  part="controlMinus"
1556
- @click="${() => this.decrement()}"
1586
+ @click="${() => this.handleControlClick('decrement')}"
1557
1587
  ?disabled="${this.disabled || this.disableMin || this.isIncrementDisabled(this.min)}"
1558
1588
  >
1559
1589
  <${this.iconTag} class="controlIcon" customSvg> ${IconUtil.generateSvgHtml(minusIcon)} </${this.iconTag}>
@@ -1567,7 +1597,7 @@ class AuroCounter extends i$2 {
1567
1597
  .tabindex="${'-1'}"
1568
1598
  appearance="${this.onDark ? 'inverse' : this.appearance}"
1569
1599
  part="controlPlus"
1570
- @click="${() => this.increment()}"
1600
+ @click="${() => this.handleControlClick('increment')}"
1571
1601
  ?disabled="${this.disabled || this.disableMax || this.isIncrementDisabled(this.max)}"
1572
1602
  >
1573
1603
  <${this.iconTag} class="controlIcon" customSvg> ${IconUtil.generateSvgHtml(plusIcon)} </${this.iconTag}>
@@ -5399,7 +5429,7 @@ class AuroHelpText extends i$2 {
5399
5429
  }
5400
5430
  }
5401
5431
 
5402
- var formkitVersion = '202608300438';
5432
+ var formkitVersion = '202608312237';
5403
5433
 
5404
5434
  /**
5405
5435
  * AuroElement is the shared base class for layout-aware Auro form components.
@@ -7538,12 +7568,15 @@ class AuroCounterGroup extends AuroElement {
7538
7568
 
7539
7569
  this.matchWidth = false;
7540
7570
  this.isDropdown = false;
7571
+
7572
+ /** @type {'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'disabled'} */
7541
7573
  this.fullscreenBreakpoint = 'sm';
7542
7574
  this.largeFullscreenHeadline = false;
7543
7575
  this.autoPlacement = false;
7544
7576
  this.noFlip = false;
7545
7577
  this.shift = false;
7546
7578
 
7579
+ /** @type {'top' | 'right' | 'bottom' | 'left' | 'bottom-start' | 'top-start' | 'top-end' | 'right-start' | 'right-end' | 'bottom-end' | 'left-start' | 'left-end'} */
7547
7580
  this.placement = 'bottom-start';
7548
7581
 
7549
7582
  /**
@@ -7572,6 +7605,16 @@ class AuroCounterGroup extends AuroElement {
7572
7605
  /** @private */
7573
7606
  this.updateValidity = this.updateValidity.bind(this);
7574
7607
 
7608
+ /**
7609
+ * Whether the most recent pointerdown began inside this group's composed tree.
7610
+ * Used to keep the dropdown open when a counter button disables itself on click.
7611
+ * @private
7612
+ */
7613
+ this.pointerdownInsideGroup = false;
7614
+
7615
+ /** @private */
7616
+ this.trackPointerdown = this.trackPointerdown.bind(this);
7617
+
7575
7618
  /**
7576
7619
  * Generate unique names for dependency components.
7577
7620
  * @private
@@ -7957,6 +8000,20 @@ class AuroCounterGroup extends AuroElement {
7957
8000
  });
7958
8001
  }
7959
8002
 
8003
+ /**
8004
+ * Records whether a pointerdown originated inside this group's composed tree.
8005
+ * @param {PointerEvent} event - The pointerdown event.
8006
+ * @private
8007
+ */
8008
+ trackPointerdown(event) {
8009
+ this.pointerdownInsideGroup = event.composedPath().includes(this);
8010
+ }
8011
+
8012
+ disconnectedCallback() {
8013
+ super.disconnectedCallback();
8014
+ document.removeEventListener('pointerdown', this.trackPointerdown, true);
8015
+ }
8016
+
7960
8017
  /**
7961
8018
  * Hides the dropdown bib if its open.
7962
8019
  * @returns {void}
@@ -8154,6 +8211,12 @@ class AuroCounterGroup extends AuroElement {
8154
8211
  if (this.isDropdown) {
8155
8212
  applyKeyboardStrategy$1(this, counterGroupKeyboardStrategy);
8156
8213
 
8214
+ // Track where the most recent pointer interaction began so the focusout
8215
+ // handler below can tell a counter-button click apart from an outside
8216
+ // click. Capture phase + composedPath so clicks inside the bib's nested
8217
+ // shadow roots still resolve to this group. (AB#1634231)
8218
+ document.addEventListener('pointerdown', this.trackPointerdown, true);
8219
+
8157
8220
  // noHideOnThisFocusLoss=true on the dropdown prevents handleFocusLoss from
8158
8221
  // closing the bib when focus moves out via Tab. Close explicitly via focusout:
8159
8222
  // if relatedTarget is outside the counter-group's light DOM, focus has left.
@@ -8161,9 +8224,29 @@ class AuroCounterGroup extends AuroElement {
8161
8224
  if (!this.dropdown?.isPopoverVisible || this.dropdown?.isBibFullscreen) {
8162
8225
  return;
8163
8226
  }
8227
+
8228
+ // Focus moved to a specific element still inside the group — keep the bib open.
8164
8229
  if (event.relatedTarget && this.contains(event.relatedTarget)) {
8165
8230
  return;
8166
8231
  }
8232
+
8233
+ // A null relatedTarget means focus was dropped without landing on a
8234
+ // specific element. This fires when a counter's +/- button becomes
8235
+ // disabled at an extreme immediately after being clicked: the browser
8236
+ // blurs the now-disabled button, closing the bib as an unwanted side
8237
+ // effect of using the counters. If that blur was triggered by a pointer
8238
+ // interaction that began inside the group, keep the bib open. A genuine
8239
+ // outside click also yields a null relatedTarget, but its pointerdown
8240
+ // originated outside the group, so we still close. (AB#1634231)
8241
+ if (!event.relatedTarget) {
8242
+ if (this.pointerdownInsideGroup) {
8243
+ return;
8244
+ }
8245
+ this.hideBib();
8246
+ return;
8247
+ }
8248
+
8249
+ // Focus moved to a known element outside the group (e.g. Tab to the next field).
8167
8250
  this.hideBib();
8168
8251
  });
8169
8252
  }
@@ -200,12 +200,14 @@ export class AuroCounterGroup extends AuroElement {
200
200
  value: {} | undefined;
201
201
  matchWidth: boolean;
202
202
  isDropdown: boolean;
203
- fullscreenBreakpoint: string;
203
+ /** @type {'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'disabled'} */
204
+ fullscreenBreakpoint: "xs" | "sm" | "md" | "lg" | "xl" | "disabled";
204
205
  largeFullscreenHeadline: boolean;
205
206
  autoPlacement: boolean;
206
207
  noFlip: boolean;
207
208
  shift: boolean;
208
- placement: string;
209
+ /** @type {'top' | 'right' | 'bottom' | 'left' | 'bottom-start' | 'top-start' | 'top-end' | 'right-start' | 'right-end' | 'bottom-end' | 'left-start' | 'left-end'} */
210
+ placement: "top" | "right" | "bottom" | "left" | "bottom-start" | "top-start" | "top-end" | "right-start" | "right-end" | "bottom-end" | "left-start" | "left-end";
209
211
  /**
210
212
  * @private
211
213
  */
@@ -237,6 +239,18 @@ export class AuroCounterGroup extends AuroElement {
237
239
  * @private
238
240
  */
239
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;
240
254
  /**
241
255
  * Dynamically generated dropdown tag.
242
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.
@@ -1077,7 +1077,7 @@ let AuroHelpText$1 = class AuroHelpText extends LitElement {
1077
1077
  }
1078
1078
  };
1079
1079
 
1080
- var formkitVersion$1 = '202608300438';
1080
+ var formkitVersion$1 = '202608312237';
1081
1081
 
1082
1082
  // Copyright (c) 2026 Alaska Airlines. All rights reserved. Licensed under the Apache-2.0 license
1083
1083
  // See LICENSE in the project root for license information.
@@ -1361,6 +1361,36 @@ class AuroCounter extends LitElement {
1361
1361
  this.value -= value !== undefined ? value : 1;
1362
1362
  }
1363
1363
 
1364
+ /**
1365
+ * Moves focus to the spinbutton control container.
1366
+ * The +/- buttons are internal `tabindex="-1"` controls; the container is the
1367
+ * widget's single focusable element. `focusVisible: true` forces the container's
1368
+ * `:focus-visible` ring to render even though the interaction was a pointer
1369
+ * click, so focus stays visible on the counter after using its buttons.
1370
+ * @private
1371
+ */
1372
+ focusControl() {
1373
+ const control = this.shadowRoot?.querySelector('[part="counterControl"]');
1374
+ if (control && !this.disabled) {
1375
+ control.focus({ focusVisible: true });
1376
+ }
1377
+ }
1378
+
1379
+ /**
1380
+ * Handles a pointer click on a control button.
1381
+ * A pointer click focuses the clicked button, so if the value change disables
1382
+ * that button at an extreme the browser would drop focus to the document body.
1383
+ * Move focus to the spinbutton container first, then change the value: focus is
1384
+ * no longer on the button when it becomes disabled, so it is never lost and the
1385
+ * counter (and any enclosing dropdown) stays operable (AB#1634231).
1386
+ * @param {'increment' | 'decrement'} action - The control action to perform.
1387
+ * @private
1388
+ */
1389
+ handleControlClick(action) {
1390
+ this.focusControl();
1391
+ this[action]();
1392
+ }
1393
+
1364
1394
  /**
1365
1395
  * Initializes the value of the counter.
1366
1396
  * If the current value is undefined, it sets the value to the minimum value.
@@ -1503,7 +1533,7 @@ class AuroCounter extends LitElement {
1503
1533
  .tabindex="${'-1'}"
1504
1534
  appearance="${this.onDark ? 'inverse' : this.appearance}"
1505
1535
  part="controlMinus"
1506
- @click="${() => this.decrement()}"
1536
+ @click="${() => this.handleControlClick('decrement')}"
1507
1537
  ?disabled="${this.disabled || this.disableMin || this.isIncrementDisabled(this.min)}"
1508
1538
  >
1509
1539
  <${this.iconTag} class="controlIcon" customSvg> ${IconUtil.generateSvgHtml(minusIcon)} </${this.iconTag}>
@@ -1517,7 +1547,7 @@ class AuroCounter extends LitElement {
1517
1547
  .tabindex="${'-1'}"
1518
1548
  appearance="${this.onDark ? 'inverse' : this.appearance}"
1519
1549
  part="controlPlus"
1520
- @click="${() => this.increment()}"
1550
+ @click="${() => this.handleControlClick('increment')}"
1521
1551
  ?disabled="${this.disabled || this.disableMax || this.isIncrementDisabled(this.max)}"
1522
1552
  >
1523
1553
  <${this.iconTag} class="controlIcon" customSvg> ${IconUtil.generateSvgHtml(plusIcon)} </${this.iconTag}>
@@ -5331,7 +5361,7 @@ class AuroHelpText extends LitElement {
5331
5361
  }
5332
5362
  }
5333
5363
 
5334
- var formkitVersion = '202608300438';
5364
+ var formkitVersion = '202608312237';
5335
5365
 
5336
5366
  /**
5337
5367
  * AuroElement is the shared base class for layout-aware Auro form components.
@@ -7470,12 +7500,15 @@ class AuroCounterGroup extends AuroElement {
7470
7500
 
7471
7501
  this.matchWidth = false;
7472
7502
  this.isDropdown = false;
7503
+
7504
+ /** @type {'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'disabled'} */
7473
7505
  this.fullscreenBreakpoint = 'sm';
7474
7506
  this.largeFullscreenHeadline = false;
7475
7507
  this.autoPlacement = false;
7476
7508
  this.noFlip = false;
7477
7509
  this.shift = false;
7478
7510
 
7511
+ /** @type {'top' | 'right' | 'bottom' | 'left' | 'bottom-start' | 'top-start' | 'top-end' | 'right-start' | 'right-end' | 'bottom-end' | 'left-start' | 'left-end'} */
7479
7512
  this.placement = 'bottom-start';
7480
7513
 
7481
7514
  /**
@@ -7504,6 +7537,16 @@ class AuroCounterGroup extends AuroElement {
7504
7537
  /** @private */
7505
7538
  this.updateValidity = this.updateValidity.bind(this);
7506
7539
 
7540
+ /**
7541
+ * Whether the most recent pointerdown began inside this group's composed tree.
7542
+ * Used to keep the dropdown open when a counter button disables itself on click.
7543
+ * @private
7544
+ */
7545
+ this.pointerdownInsideGroup = false;
7546
+
7547
+ /** @private */
7548
+ this.trackPointerdown = this.trackPointerdown.bind(this);
7549
+
7507
7550
  /**
7508
7551
  * Generate unique names for dependency components.
7509
7552
  * @private
@@ -7889,6 +7932,20 @@ class AuroCounterGroup extends AuroElement {
7889
7932
  });
7890
7933
  }
7891
7934
 
7935
+ /**
7936
+ * Records whether a pointerdown originated inside this group's composed tree.
7937
+ * @param {PointerEvent} event - The pointerdown event.
7938
+ * @private
7939
+ */
7940
+ trackPointerdown(event) {
7941
+ this.pointerdownInsideGroup = event.composedPath().includes(this);
7942
+ }
7943
+
7944
+ disconnectedCallback() {
7945
+ super.disconnectedCallback();
7946
+ document.removeEventListener('pointerdown', this.trackPointerdown, true);
7947
+ }
7948
+
7892
7949
  /**
7893
7950
  * Hides the dropdown bib if its open.
7894
7951
  * @returns {void}
@@ -8086,6 +8143,12 @@ class AuroCounterGroup extends AuroElement {
8086
8143
  if (this.isDropdown) {
8087
8144
  applyKeyboardStrategy$1(this, counterGroupKeyboardStrategy);
8088
8145
 
8146
+ // Track where the most recent pointer interaction began so the focusout
8147
+ // handler below can tell a counter-button click apart from an outside
8148
+ // click. Capture phase + composedPath so clicks inside the bib's nested
8149
+ // shadow roots still resolve to this group. (AB#1634231)
8150
+ document.addEventListener('pointerdown', this.trackPointerdown, true);
8151
+
8089
8152
  // noHideOnThisFocusLoss=true on the dropdown prevents handleFocusLoss from
8090
8153
  // closing the bib when focus moves out via Tab. Close explicitly via focusout:
8091
8154
  // if relatedTarget is outside the counter-group's light DOM, focus has left.
@@ -8093,9 +8156,29 @@ class AuroCounterGroup extends AuroElement {
8093
8156
  if (!this.dropdown?.isPopoverVisible || this.dropdown?.isBibFullscreen) {
8094
8157
  return;
8095
8158
  }
8159
+
8160
+ // Focus moved to a specific element still inside the group — keep the bib open.
8096
8161
  if (event.relatedTarget && this.contains(event.relatedTarget)) {
8097
8162
  return;
8098
8163
  }
8164
+
8165
+ // A null relatedTarget means focus was dropped without landing on a
8166
+ // specific element. This fires when a counter's +/- button becomes
8167
+ // disabled at an extreme immediately after being clicked: the browser
8168
+ // blurs the now-disabled button, closing the bib as an unwanted side
8169
+ // effect of using the counters. If that blur was triggered by a pointer
8170
+ // interaction that began inside the group, keep the bib open. A genuine
8171
+ // outside click also yields a null relatedTarget, but its pointerdown
8172
+ // originated outside the group, so we still close. (AB#1634231)
8173
+ if (!event.relatedTarget) {
8174
+ if (this.pointerdownInsideGroup) {
8175
+ return;
8176
+ }
8177
+ this.hideBib();
8178
+ return;
8179
+ }
8180
+
8181
+ // Focus moved to a known element outside the group (e.g. Tab to the next field).
8099
8182
  this.hideBib();
8100
8183
  });
8101
8184
  }