@aurodesignsystem-dev/auro-formkit 0.0.0-pr1514.2 → 0.0.0-pr1514.4

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 (47) 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 +4 -3
  7. package/components/combobox/demo/getting-started.min.js +4 -3
  8. package/components/combobox/demo/index.min.js +4 -3
  9. package/components/combobox/dist/index.js +4 -3
  10. package/components/combobox/dist/registered.js +4 -3
  11. package/components/counter/demo/customize.min.js +10 -2
  12. package/components/counter/demo/index.min.js +10 -2
  13. package/components/counter/dist/index.js +10 -2
  14. package/components/counter/dist/registered.js +10 -2
  15. package/components/datepicker/demo/customize.min.js +17 -7
  16. package/components/datepicker/demo/index.min.js +17 -7
  17. package/components/datepicker/dist/auro-calendar.d.ts +4 -2
  18. package/components/datepicker/dist/index.js +17 -7
  19. package/components/datepicker/dist/registered.js +17 -7
  20. package/components/dropdown/demo/customize.min.js +2 -1
  21. package/components/dropdown/demo/getting-started.min.js +2 -1
  22. package/components/dropdown/demo/index.min.js +2 -1
  23. package/components/dropdown/dist/index.js +2 -1
  24. package/components/dropdown/dist/registered.js +2 -1
  25. package/components/form/demo/customize.min.js +220 -77
  26. package/components/form/demo/getting-started.min.js +220 -77
  27. package/components/form/demo/index.min.js +220 -77
  28. package/components/form/demo/registerDemoDeps.min.js +220 -77
  29. package/components/input/demo/customize.min.js +1 -1
  30. package/components/input/demo/getting-started.min.js +1 -1
  31. package/components/input/demo/index.min.js +1 -1
  32. package/components/input/dist/index.js +1 -1
  33. package/components/input/dist/registered.js +1 -1
  34. package/components/radio/demo/customize.min.js +1 -1
  35. package/components/radio/demo/getting-started.min.js +1 -1
  36. package/components/radio/demo/index.min.js +1 -1
  37. package/components/radio/dist/index.js +1 -1
  38. package/components/radio/dist/registered.js +1 -1
  39. package/components/select/demo/customize.min.js +186 -62
  40. package/components/select/demo/getting-started.min.js +186 -62
  41. package/components/select/demo/index.min.js +186 -62
  42. package/components/select/demo/keyboard-behavior.md +18 -4
  43. package/components/select/dist/auro-select.d.ts +20 -8
  44. package/components/select/dist/index.js +186 -62
  45. package/components/select/dist/registered.js +186 -62
  46. package/custom-elements.json +14 -18
  47. package/package.json +1 -1
@@ -990,19 +990,28 @@ const selectKeyboardStrategy = {
990
990
  },
991
991
 
992
992
  End(component, evt, ctx) {
993
- if (!ctx.isExpanded) {
994
- return;
995
- }
996
993
  evt.preventDefault();
997
994
  evt.stopPropagation();
998
995
  // `pop()` is safe here: getEnabledOptions returns a fresh filtered array.
999
996
  const lastOption = getEnabledOptions(component.menu).pop();
1000
- if (lastOption) {
1001
- component.menu.updateActiveOption(lastOption);
997
+ if (!lastOption) {
998
+ return;
999
+ }
1000
+ // Pre-stash before show() so the auroDropdown-toggled handler's
1001
+ // `!optionActive` guard short-circuits the firstActive/selected fallback —
1002
+ // otherwise show() synchronously fires the handler and writes
1003
+ // aria-activedescendant once before we overwrite it.
1004
+ component.menu.updateActiveOption(lastOption);
1005
+ if (!ctx.isExpanded) {
1006
+ component.dropdown.show();
1002
1007
  }
1003
1008
  },
1004
1009
 
1005
1010
  Enter(component, evt, ctx) {
1011
+ // Prevent the keypress from bubbling to parent containers (e.g., forms)
1012
+ // which could interpret Enter as a submit. Matches APG select-only combobox
1013
+ // and native <select> behavior: Enter opens the listbox when closed, selects
1014
+ // the active option when open — it does not submit a parent form.
1006
1015
  evt.preventDefault();
1007
1016
  evt.stopPropagation();
1008
1017
  if (!ctx.isExpanded) {
@@ -1013,14 +1022,16 @@ const selectKeyboardStrategy = {
1013
1022
  },
1014
1023
 
1015
1024
  Home(component, evt, ctx) {
1016
- if (!ctx.isExpanded) {
1017
- return;
1018
- }
1019
1025
  evt.preventDefault();
1020
1026
  evt.stopPropagation();
1021
1027
  const [firstOption] = getEnabledOptions(component.menu);
1022
- if (firstOption) {
1023
- component.menu.updateActiveOption(firstOption);
1028
+ if (!firstOption) {
1029
+ return;
1030
+ }
1031
+ // See End() for why this must run before show().
1032
+ component.menu.updateActiveOption(firstOption);
1033
+ if (!ctx.isExpanded) {
1034
+ component.dropdown.show();
1024
1035
  }
1025
1036
  },
1026
1037
 
@@ -4992,7 +5003,7 @@ let AuroHelpText$1 = class AuroHelpText extends i$2 {
4992
5003
  }
4993
5004
  };
4994
5005
 
4995
- var formkitVersion$1 = '202606291652';
5006
+ var formkitVersion$1 = '202606291737';
4996
5007
 
4997
5008
  class AuroElement extends i$2 {
4998
5009
  static get properties() {
@@ -6264,6 +6275,7 @@ class AuroDropdown extends AuroElement {
6264
6275
  role="${o(this.triggerContentFocusable ? undefined : this.a11yRole)}"
6265
6276
  aria-expanded="${o(this.a11yRole === 'button' || this.triggerContentFocusable ? undefined : this.isPopoverVisible)}"
6266
6277
  aria-controls="${o(this.a11yRole === 'button' || this.triggerContentFocusable ? undefined : this.dropdownId)}"
6278
+ aria-haspopup="${o(this.a11yRole === 'combobox' && !this.triggerContentFocusable ? 'listbox' : undefined)}"
6267
6279
  aria-labelledby="${o(this.triggerContentFocusable ? undefined : 'triggerLabel')}"
6268
6280
  aria-disabled="${o(this.disabled ? 'true' : undefined)}"
6269
6281
  @focusin="${this.handleFocusin}"
@@ -7013,7 +7025,7 @@ class AuroHelpText extends i$2 {
7013
7025
  }
7014
7026
  }
7015
7027
 
7016
- var formkitVersion = '202606291652';
7028
+ var formkitVersion = '202606291737';
7017
7029
 
7018
7030
  var styleCss$2 = i$5`.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}.body-default{font-size:var(--wcss-body-default-font-size, 1rem);font-weight:var(--wcss-body-default-weight, );line-height:var(--wcss-body-default-line-height, 1.5rem)}.body-default,.body-default-emphasized{font-family:var(--wcss-body-family, "AS Circular"),system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;letter-spacing:var(--wcss-body-letter-spacing, 0)}.body-default-emphasized{font-size:var(--wcss-body-default-emphasized-font-size, 1rem);font-weight:var(--wcss-body-default-emphasized-weight, );line-height:var(--wcss-body-default-emphasized-line-height, 1.5rem)}.body-lg{font-size:var(--wcss-body-lg-font-size, 1.125rem);font-weight:var(--wcss-body-lg-weight, );line-height:var(--wcss-body-lg-line-height, 1.625rem)}.body-lg,.body-lg-emphasized{font-family:var(--wcss-body-family, "AS Circular"),system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;letter-spacing:var(--wcss-body-letter-spacing, 0)}.body-lg-emphasized{font-size:var(--wcss-body-lg-emphasized-font-size, 1.125rem);font-weight:var(--wcss-body-lg-emphasized-weight, );line-height:var(--wcss-body-lg-emphasized-line-height, 1.625rem)}.body-sm{font-size:var(--wcss-body-sm-font-size, 0.875rem);font-weight:var(--wcss-body-sm-weight, );line-height:var(--wcss-body-sm-line-height, 1.25rem)}.body-sm,.body-sm-emphasized{font-family:var(--wcss-body-family, "AS Circular"),system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;letter-spacing:var(--wcss-body-letter-spacing, 0)}.body-sm-emphasized{font-size:var(--wcss-body-sm-emphasized-font-size, 0.875rem);font-weight:var(--wcss-body-sm-emphasized-weight, );line-height:var(--wcss-body-sm-emphasized-line-height, 1.25rem)}.body-xs{font-size:var(--wcss-body-xs-font-size, 0.75rem);font-weight:var(--wcss-body-xs-weight, );line-height:var(--wcss-body-xs-line-height, 1rem)}.body-xs,.body-xs-emphasized{font-family:var(--wcss-body-family, "AS Circular"),system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;letter-spacing:var(--wcss-body-letter-spacing, 0)}.body-xs-emphasized{font-size:var(--wcss-body-xs-emphasized-font-size, 0.75rem);font-weight:var(--wcss-body-xs-emphasized-weight, );line-height:var(--wcss-body-xs-emphasized-line-height, 1rem)}.body-2xs{font-size:var(--wcss-body-2xs-font-size, 0.625rem);font-weight:var(--wcss-body-2xs-weight, );line-height:var(--wcss-body-2xs-line-height, 0.875rem)}.body-2xs,.body-2xs-emphasized{font-family:var(--wcss-body-family, "AS Circular"),system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;letter-spacing:var(--wcss-body-letter-spacing, 0)}.body-2xs-emphasized{font-size:var(--wcss-body-2xs-emphasized-font-size, 0.625rem);font-weight:var(--wcss-body-2xs-emphasized-weight, );line-height:var(--wcss-body-2xs-emphasized-line-height, 0.875rem)}.display-2xl{font-family:var(--wcss-display-2xl-family, "AS Circular"),var(--wcss-display-2xl-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-display-2xl-font-size, clamp(3.5rem, 6vw, 5.375rem));font-weight:var(--wcss-display-2xl-weight, 300);letter-spacing:var(--wcss-display-2xl-letter-spacing, 0);line-height:var(--wcss-display-2xl-line-height, 1.3)}.display-xl{font-family:var(--wcss-display-xl-family, "AS Circular"),var(--wcss-display-xl-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-display-xl-font-size, clamp(3rem, 5.3333333333vw, 4.5rem));font-weight:var(--wcss-display-xl-weight, 300);letter-spacing:var(--wcss-display-xl-letter-spacing, 0);line-height:var(--wcss-display-xl-line-height, 1.3)}.display-lg{font-family:var(--wcss-display-lg-family, "AS Circular"),var(--wcss-display-lg-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-display-lg-font-size, clamp(2.75rem, 4.6666666667vw, 4rem));font-weight:var(--wcss-display-lg-weight, 300);letter-spacing:var(--wcss-display-lg-letter-spacing, 0);line-height:var(--wcss-display-lg-line-height, 1.3)}.display-md{font-family:var(--wcss-display-md-family, "AS Circular"),var(--wcss-display-md-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-display-md-font-size, clamp(2.5rem, 4vw, 3.5rem));font-weight:var(--wcss-display-md-weight, 300);letter-spacing:var(--wcss-display-md-letter-spacing, 0);line-height:var(--wcss-display-md-line-height, 1.3)}.display-sm{font-family:var(--wcss-display-sm-family, "AS Circular"),var(--wcss-display-sm-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-display-sm-font-size, clamp(2rem, 3.6666666667vw, 3rem));font-weight:var(--wcss-display-sm-weight, 300);letter-spacing:var(--wcss-display-sm-letter-spacing, 0);line-height:var(--wcss-display-sm-line-height, 1.3)}.display-xs{font-family:var(--wcss-display-xs-family, "AS Circular"),var(--wcss-display-xs-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-display-xs-font-size, clamp(1.75rem, 3vw, 2.375rem));font-weight:var(--wcss-display-xs-weight, 300);letter-spacing:var(--wcss-display-xs-letter-spacing, 0);line-height:var(--wcss-display-xs-line-height, 1.3)}.heading-xl{font-family:var(--wcss-heading-xl-family, "AS Circular"),var(--wcss-heading-xl-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-heading-xl-font-size, clamp(2rem, 3vw, 2.5rem));font-weight:var(--wcss-heading-xl-weight, 300);letter-spacing:var(--wcss-heading-xl-letter-spacing, 0);line-height:var(--wcss-heading-xl-line-height, 1.3)}.heading-lg{font-family:var(--wcss-heading-lg-family, "AS Circular"),var(--wcss-heading-lg-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-heading-lg-font-size, clamp(1.75rem, 2.6666666667vw, 2.25rem));font-weight:var(--wcss-heading-lg-weight, 300);letter-spacing:var(--wcss-heading-lg-letter-spacing, 0);line-height:var(--wcss-heading-lg-line-height, 1.3)}.heading-md{font-family:var(--wcss-heading-md-family, "AS Circular"),var(--wcss-heading-md-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-heading-md-font-size, clamp(1.625rem, 2.3333333333vw, 1.75rem));font-weight:var(--wcss-heading-md-weight, 300);letter-spacing:var(--wcss-heading-md-letter-spacing, 0);line-height:var(--wcss-heading-md-line-height, 1.3)}.heading-sm{font-family:var(--wcss-heading-sm-family, "AS Circular"),var(--wcss-heading-sm-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-heading-sm-font-size, clamp(1.375rem, 2vw, 1.5rem));font-weight:var(--wcss-heading-sm-weight, 300);letter-spacing:var(--wcss-heading-sm-letter-spacing, 0);line-height:var(--wcss-heading-sm-line-height, 1.3)}.heading-xs{font-family:var(--wcss-heading-xs-family, "AS Circular"),var(--wcss-heading-xs-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-heading-xs-font-size, clamp(1.25rem, 1.6666666667vw, 1.25rem));font-weight:var(--wcss-heading-xs-weight, 300);letter-spacing:var(--wcss-heading-xs-letter-spacing, 0);line-height:var(--wcss-heading-xs-line-height, 1.3)}.heading-2xs{font-family:var(--wcss-heading-2xs-family, "AS Circular"),var(--wcss-heading-2xs-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-heading-2xs-font-size, clamp(1.125rem, 1.5vw, 1.125rem));font-weight:var(--wcss-heading-2xs-weight, 300);letter-spacing:var(--wcss-heading-2xs-letter-spacing, 0);line-height:var(--wcss-heading-2xs-line-height, 1.3)}.accent-2xl{font-family:var(--wcss-accent-2xl-family, "Good OT"),var(--wcss-accent-2xl-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-accent-2xl-font-size, clamp(2rem, 3.1666666667vw, 2.375rem));font-weight:var(--wcss-accent-2xl-weight, 450);letter-spacing:var(--wcss-accent-2xl-letter-spacing, 0.05em);line-height:var(--wcss-accent-2xl-line-height, 1)}.accent-2xl,.accent-xl{text-transform:uppercase}.accent-xl{font-family:var(--wcss-accent-xl-family, "Good OT"),var(--wcss-accent-xl-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-accent-xl-font-size, clamp(1.625rem, 2.3333333333vw, 2rem));font-weight:var(--wcss-accent-xl-weight, 450);letter-spacing:var(--wcss-accent-xl-letter-spacing, 0.05em);line-height:var(--wcss-accent-xl-line-height, 1.3)}.accent-lg{font-family:var(--wcss-accent-lg-family, "Good OT"),var(--wcss-accent-lg-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-accent-lg-font-size, clamp(1.5rem, 2.1666666667vw, 1.75rem));font-weight:var(--wcss-accent-lg-weight, 450);letter-spacing:var(--wcss-accent-lg-letter-spacing, 0.05em);line-height:var(--wcss-accent-lg-line-height, 1.3)}.accent-lg,.accent-md{text-transform:uppercase}.accent-md{font-family:var(--wcss-accent-md-family, "Good OT"),var(--wcss-accent-md-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-accent-md-font-size, clamp(1.375rem, 1.8333333333vw, 1.5rem));font-weight:var(--wcss-accent-md-weight, 500);letter-spacing:var(--wcss-accent-md-letter-spacing, 0.05em);line-height:var(--wcss-accent-md-line-height, 1.3)}.accent-sm{font-family:var(--wcss-accent-sm-family, "Good OT"),var(--wcss-accent-sm-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-accent-sm-font-size, clamp(1.125rem, 1.5vw, 1.25rem));font-weight:var(--wcss-accent-sm-weight, 500);letter-spacing:var(--wcss-accent-sm-letter-spacing, 0.05em);line-height:var(--wcss-accent-sm-line-height, 1.3)}.accent-sm,.accent-xs{text-transform:uppercase}.accent-xs{font-family:var(--wcss-accent-xs-family, "Good OT"),var(--wcss-accent-xs-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-accent-xs-font-size, clamp(1rem, 1.3333333333vw, 1rem));font-weight:var(--wcss-accent-xs-weight, 500);letter-spacing:var(--wcss-accent-xs-letter-spacing, 0.1em);line-height:var(--wcss-accent-xs-line-height, 1.3)}.accent-2xs{font-family:var(--wcss-accent-2xs-family, "Good OT"),var(--wcss-accent-2xs-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-size:var(--wcss-accent-2xs-font-size, clamp(0.875rem, 1.1666666667vw, 0.875rem));font-weight:var(--wcss-accent-2xs-weight, 450);letter-spacing:var(--wcss-accent-2xs-letter-spacing, 0.1em);line-height:var(--wcss-accent-2xs-line-height, 1.3);text-transform:uppercase}[auro-dropdown]{--ds-auro-dropdown-trigger-border-color: var(--ds-auro-select-border-color);--ds-auro-dropdown-trigger-background-color: var(--ds-auro-select-background-color);--ds-auro-dropdown-trigger-container-color: var(--ds-auro-select-background-color);--ds-auro-dropdown-trigger-outline-color: var(--ds-auro-select-outline-color)}:host{display:inline-block;text-align:left;vertical-align:top}:host([layout*=emphasized]) [auro-dropdown],:host([layout*=snowflake]) [auro-dropdown]{--ds-auro-select-border-color: transparent}:host([layout*=emphasized]) .mainContent,:host([layout*=snowflake]) .mainContent{text-align:center}.mainContent{position:relative;display:flex;overflow:hidden;flex:1;flex-direction:column;align-items:center;justify-content:center}.valueContainer [slot=displayValue]{display:none}.accents{display:flex;flex-direction:row;align-items:center;justify-content:center}::slotted([slot=typeIcon]){margin-right:var(--ds-size-100, 0.5rem)}.displayValue{display:block}.displayValue:not(.force){display:none}.displayValue:not(.force).hasContent:is(.withValue):not(.hasFocus){display:block}.triggerContent{display:flex;width:100%;align-items:center;justify-content:center}:host([layout*=emphasized]) .triggerContent{padding:0 var(--ds-size-100, 0.5rem) 0 var(--ds-size-300, 1.5rem)}:host([layout*=snowflake]) .triggerContent{padding:0 var(--ds-size-100, 0.5rem) 0 var(--ds-size-200, 1rem)}:host([layout*=snowflake]) label{padding-block:var(--ds-size-25, 0.125rem)}:host([layout*=classic]) .triggerContent{padding:0 var(--ds-size-100, 0.5rem)}:host([layout*=classic]) .mainContent{align-items:start}:host([layout*=classic]) label{overflow:hidden;cursor:text;text-overflow:ellipsis;white-space:nowrap}:host([layout*=classic]) .value{height:auto}label{color:var(--ds-auro-select-label-text-color)}:host(:is([validity]:not([validity=valid]))) [auro-dropdown]{--ds-auro-select-border-color: var(--ds-basic-color-status-error, #e31f26);--ds-auro-select-outline-color: var(--ds-basic-color-status-error, #e31f26);--ds-auro-dropdown-helptext-text-color: var(--ds-basic-color-texticon-default, #2a2a2a)}:host([ondark]:is([validity]:not([validity=valid]))) [auro-dropdown],:host([appearance=inverse]:is([validity]:not([validity=valid]))) [auro-dropdown]{--ds-auro-select-border-color: var(--ds-advanced-color-state-error-inverse, #f9a4a8);--ds-auro-select-outline-color: var(--ds-advanced-color-state-error-inverse, #f9a4a8);--ds-auro-dropdown-helptext-text-color: var(--ds-basic-color-texticon-inverse, #ffffff)}#slotHolder{display:none}:host([fluid]){width:100%}:host([disabled]){pointer-events:none;user-select:none}:host([disabled]:not([ondark])) [auro-dropdown],:host([disabled]:not([appearance=inverse])) [auro-dropdown]{--ds-auro-select-border-color: var(--ds-basic-color-border-subtle, #dddddd)}:host(:not([layout*=classic])[disabled][ondark]) [auro-dropdown],:host(:not([layout*=classic])[disabled][appearance=inverse]) [auro-dropdown]{--ds-auro-select-border-color: transparent}`;
7019
7031
 
@@ -7345,14 +7357,6 @@ class AuroSelect extends AuroElement$1 {
7345
7357
  reflect: true
7346
7358
  },
7347
7359
 
7348
- /**
7349
- * @private
7350
- */
7351
- options: {
7352
- type: Array,
7353
- state: true
7354
- },
7355
-
7356
7360
  /**
7357
7361
  * Specifies the current selected menuOption. Default type is `HTMLElement`, changing to `Array<HTMLElement>` when `multiSelect` is true.
7358
7362
  * @type {HTMLElement|Array<HTMLElement>}
@@ -7640,16 +7644,68 @@ class AuroSelect extends AuroElement$1 {
7640
7644
  this.dropdown.dropdownWidth = this.customBibWidth;
7641
7645
  }
7642
7646
 
7643
- // Pass label text to the dropdown bib for accessible dialog naming
7644
- const labelElement = this.querySelector('span[slot="label"]');
7645
- if (labelElement) {
7646
- this.dropdown.bibDialogLabel = labelElement.textContent.trim() || undefined;
7647
- }
7647
+ this._syncLabelText();
7648
7648
 
7649
7649
  // Exposes the CSS parts from the dropdown for styling
7650
7650
  this.dropdown.exposeCssParts();
7651
7651
  }
7652
7652
 
7653
+ /**
7654
+ * Reads the current label slot text and pushes it to the dropdown bib
7655
+ * (for dialog naming) and the menu (for listbox aria-label). Safe to call
7656
+ * before either child has been wired up — each branch self-guards.
7657
+ * @private
7658
+ */
7659
+ _syncLabelText() {
7660
+ const labelElement = this.querySelector('[slot="label"]');
7661
+ const text = labelElement ? labelElement.textContent.trim() : '';
7662
+ if (this.dropdown) {
7663
+ this.dropdown.bibDialogLabel = text || undefined;
7664
+ }
7665
+ if (this.menu) {
7666
+ if (text) {
7667
+ this.menu.setAttribute('aria-label', text);
7668
+ } else {
7669
+ this.menu.removeAttribute('aria-label');
7670
+ }
7671
+ }
7672
+ }
7673
+
7674
+ /**
7675
+ * Keeps the dialog/menu accessible names in sync when consumers mutate the
7676
+ * label slot at runtime (e.g., i18n locale swap). `slotchange` alone is
7677
+ * insufficient — it doesn't fire when textContent of an already-assigned
7678
+ * slotted node changes, which is the common case. We scope the observer to
7679
+ * the label node itself (not the whole host subtree) so option-content
7680
+ * mutations don't trigger label re-syncs, and re-target on `slotchange`
7681
+ * when consumers add or replace the label element.
7682
+ * @private
7683
+ */
7684
+ _observeLabelChanges() {
7685
+ if (this._labelObserver) return;
7686
+ this._labelObserver = new MutationObserver(() => this._syncLabelText());
7687
+
7688
+ const retarget = () => {
7689
+ this._labelObserver.disconnect();
7690
+ const labelElement = this.querySelector('[slot="label"]');
7691
+ if (labelElement) {
7692
+ this._labelObserver.observe(labelElement, {
7693
+ childList: true,
7694
+ subtree: true,
7695
+ characterData: true
7696
+ });
7697
+ }
7698
+ this._syncLabelText();
7699
+ };
7700
+
7701
+ retarget();
7702
+
7703
+ this._retargetLabelObserver = retarget;
7704
+ this.shadowRoot.querySelectorAll('slot[name="label"]').forEach((slot) => {
7705
+ slot.addEventListener('slotchange', retarget);
7706
+ });
7707
+ }
7708
+
7653
7709
  /**
7654
7710
  * This will register this element with the browser.
7655
7711
  * @param {string} [name="auro-select"] - The name of element that you want to register to.
@@ -7800,11 +7856,7 @@ class AuroSelect extends AuroElement$1 {
7800
7856
  this.updateMenuShapeSize();
7801
7857
  this.setMenuValue(this.value);
7802
7858
 
7803
- // Set accessible name on the menu for screen readers based on the label slot content
7804
- const labelElement = this.querySelector('[slot="label"]');
7805
- if (labelElement) {
7806
- this.menu.setAttribute('aria-label', labelElement.textContent.trim());
7807
- }
7859
+ this._syncLabelText();
7808
7860
 
7809
7861
  if (this.multiSelect) {
7810
7862
  this.menu.multiSelect = this.multiSelect;
@@ -7816,8 +7868,21 @@ class AuroSelect extends AuroElement$1 {
7816
7868
  if (typeof this.menu.initItems === 'function') {
7817
7869
  this.menu.initItems();
7818
7870
  }
7819
- this.options = this.menu.options;
7820
7871
  this.updateOptionPositions();
7872
+ // renderNativeSelect reads this.menu.options, which the parent doesn't
7873
+ // observe — request an update so the hidden native <option> list reflects
7874
+ // the menu's options after initItems populates them.
7875
+ this.requestUpdate();
7876
+
7877
+ // Keep aria-setsize/aria-posinset (and the native <option> list) in sync
7878
+ // when the menu re-initializes its items — e.g., slotchange, async/lazy
7879
+ // loads, value-triggered re-init. Without this, stale set-size is
7880
+ // announced and the native select goes stale after dynamic mutations.
7881
+ this.menu.addEventListener('auroMenu-optionsChange', () => {
7882
+ this.updateOptionPositions();
7883
+ this.requestUpdate();
7884
+ });
7885
+
7821
7886
  this.menu.addEventListener("auroMenu-loadingChange", (event) => this.handleMenuLoadingChange(event));
7822
7887
 
7823
7888
  this.menu.addEventListener("auroMenu-selectValueFailure", () => {
@@ -7836,11 +7901,26 @@ class AuroSelect extends AuroElement$1 {
7836
7901
  this.dropdown.setActiveDescendant(this.optionActive);
7837
7902
  }
7838
7903
 
7839
- // Announce the active option for screen readers
7840
- if (this.optionActive) {
7904
+ // Live-region announce only for [not selected] options. For activations
7905
+ // on an already-selected option — auto-activation on bib open, arrow
7906
+ // navigation back to the selection, or click in multiSelect — rely on
7907
+ // aria-activedescendant + aria-selected="true" to convey state per the
7908
+ // WAI-ARIA listbox pattern. This is intentional, not limited to the
7909
+ // initial activation on open: it also prevents a duplicate "X, selected"
7910
+ // when Enter on the active+selected option re-fires
7911
+ // auroMenu-selectedOption (see 03b289e39).
7912
+ if (this.optionActive && !this.optionActive.hasAttribute('selected')) {
7841
7913
  const optionText = this.optionActive.textContent.trim();
7842
- const selectedState = this.optionActive.hasAttribute('selected') ? ', selected' : ', not selected';
7843
- announceToScreenReader(this._getAnnouncementRoot(), `${optionText}${selectedState}`);
7914
+ const message = `${optionText}, not selected`;
7915
+ if (this.dropdown.isPopoverVisible) {
7916
+ announceToScreenReader(this._getAnnouncementRoot(), message);
7917
+ } else {
7918
+ // Typeahead-on-closed fires this event before `show()` flips
7919
+ // isPopoverVisible. Defer so the announcement targets the bib's
7920
+ // live region once the fullscreen <dialog> opens — otherwise it
7921
+ // lands in the host root, which is inert under the active modal.
7922
+ queueMicrotask(() => announceToScreenReader(this._getAnnouncementRoot(), message));
7923
+ }
7844
7924
  }
7845
7925
 
7846
7926
  if (this.dropdown.isPopoverVisible) {
@@ -7849,6 +7929,7 @@ class AuroSelect extends AuroElement$1 {
7849
7929
  });
7850
7930
 
7851
7931
  this.menu.addEventListener('auroMenu-selectedOption', () => {
7932
+ const previousSelected = this.optionSelected;
7852
7933
 
7853
7934
  // Update the displayed value
7854
7935
  this.updateDisplayedValue();
@@ -7868,13 +7949,32 @@ class AuroSelect extends AuroElement$1 {
7868
7949
  this.dropdown.trigger.focus();
7869
7950
  }
7870
7951
 
7871
- // Announce the selection after the dropdown closes so it isn't
7872
- // overridden by VoiceOver's "collapsed" announcement from aria-expanded.
7873
- const selectedValue = this.menu.currentLabel;
7874
- const announcementDelay = 300;
7875
- setTimeout(() => {
7876
- announceToScreenReader(this._getAnnouncementRoot(), `${selectedValue}, selected`);
7877
- }, announcementDelay);
7952
+ // Describe the actual change. In multiSelect, currentLabel is the
7953
+ // concatenated remaining list — announcing "{list}, selected" after a
7954
+ // deselect would falsely claim every remaining label was just added.
7955
+ // Diff previous vs next to recover the toggled option.
7956
+ let announcement = '';
7957
+ if (this.multiSelect) {
7958
+ const prev = Array.isArray(previousSelected) ? previousSelected : [];
7959
+ const removed = prev.find((opt) => !nextSelected.includes(opt));
7960
+ const added = nextSelected.find((opt) => !prev.includes(opt));
7961
+ if (removed) {
7962
+ announcement = `${removed.textContent.trim()}, not selected`;
7963
+ } else if (added) {
7964
+ announcement = `${added.textContent.trim()}, selected`;
7965
+ }
7966
+ } else {
7967
+ announcement = `${this.menu.currentLabel}, selected`;
7968
+ }
7969
+
7970
+ // Delay so the utterance isn't overridden by VoiceOver's "collapsed"
7971
+ // announcement from aria-expanded when the dropdown closes.
7972
+ if (announcement) {
7973
+ const announcementDelay = 300;
7974
+ setTimeout(() => {
7975
+ announceToScreenReader(this._getAnnouncementRoot(), announcement);
7976
+ }, announcementDelay);
7977
+ }
7878
7978
  });
7879
7979
  }
7880
7980
 
@@ -7972,24 +8072,32 @@ class AuroSelect extends AuroElement$1 {
7972
8072
 
7973
8073
  this.typeaheadBuffer += key;
7974
8074
 
7975
- const isRepeatedChar = this.typeaheadBuffer.length > 1 && new Set(this.typeaheadBuffer).size === 1;
8075
+ // Prefer the literal buffer as a prefix per WAI-ARIA APG ("focus moves to the
8076
+ // next item with a name that starts with the string of characters typed").
8077
+ // Only fall back to single-char cycling when the repeated buffer has no
8078
+ // longer prefix match — e.g. "aa" cycles through ["Apple", "Apricot"] only
8079
+ // because no option starts with "aa".
8080
+ let match = options.find((option) => this._getOptionDisplayText(option).startsWith(this.typeaheadBuffer));
7976
8081
 
7977
- let match = null;
8082
+ const isRepeatedChar = !match && this.typeaheadBuffer.length > 1 && new Set(this.typeaheadBuffer).size === 1;
7978
8083
  if (isRepeatedChar) {
7979
8084
  const matches = options.filter((option) => this._getOptionDisplayText(option).startsWith(key));
7980
8085
  if (matches.length) {
7981
8086
  const cycleIndex = (this.typeaheadBuffer.length - 1) % matches.length;
7982
8087
  match = matches[cycleIndex];
7983
8088
  }
7984
- } else {
7985
- match = options.find((option) => this._getOptionDisplayText(option).startsWith(this.typeaheadBuffer));
7986
8089
  }
7987
8090
 
8091
+ // Intentional: no-match leaves the bib closed (deviates from APG / some native <select>).
7988
8092
  if (match) {
8093
+ // Pre-stash the match so the auroDropdown-toggled handler's `!optionActive`
8094
+ // guard short-circuits and skips the firstActive/selected fallback —
8095
+ // otherwise show() synchronously fires the handler, which writes
8096
+ // aria-activedescendant once before we overwrite it.
8097
+ this.menu.updateActiveOption(match);
7989
8098
  if (!this.dropdown.isPopoverVisible) {
7990
8099
  this.dropdown.show();
7991
8100
  }
7992
- this.menu.updateActiveOption(match);
7993
8101
  }
7994
8102
  }
7995
8103
 
@@ -8106,6 +8214,28 @@ class AuroSelect extends AuroElement$1 {
8106
8214
  disconnectedCallback() {
8107
8215
  super.disconnectedCallback();
8108
8216
  this._clearTypeaheadBuffer();
8217
+ if (this._labelObserver) {
8218
+ this._labelObserver.disconnect();
8219
+ this._labelObserver = null;
8220
+ }
8221
+ if (this._retargetLabelObserver && this.shadowRoot) {
8222
+ this.shadowRoot.querySelectorAll('slot[name="label"]').forEach((slot) => {
8223
+ slot.removeEventListener('slotchange', this._retargetLabelObserver);
8224
+ });
8225
+ this._retargetLabelObserver = null;
8226
+ }
8227
+ }
8228
+
8229
+ connectedCallback() {
8230
+ super.connectedCallback();
8231
+ // Regression guard: firstUpdated() fires once per instance, so the label
8232
+ // observer setup it triggers does NOT re-run on reconnect. After a
8233
+ // disconnect+reconnect (reparent, SPA route swap), runtime label mutations
8234
+ // would silently stop syncing menu aria-label / dropdown.bibDialogLabel
8235
+ // unless we re-wire the observer here.
8236
+ if (this.hasUpdated) {
8237
+ this._observeLabelChanges();
8238
+ }
8109
8239
  }
8110
8240
 
8111
8241
  // lifecycle runs only after the element's DOM has been updated the first time
@@ -8116,6 +8246,7 @@ class AuroSelect extends AuroElement$1 {
8116
8246
  this.configureDropdown();
8117
8247
  this.configureMenu();
8118
8248
  this.configureSelect();
8249
+ this._observeLabelChanges();
8119
8250
  }
8120
8251
 
8121
8252
  setMenuValue(value) {
@@ -8248,25 +8379,18 @@ class AuroSelect extends AuroElement$1 {
8248
8379
  * @private
8249
8380
  */
8250
8381
  _handleNativeSelectChange(event) {
8382
+ // Hidden native <select> has no `multiple` attribute, so any change it fires
8383
+ // is a single raw value — applying it in multiSelect mode would collapse the
8384
+ // JSON-array `value` shape. Bfcache/autofill can reach this on a name-bearing
8385
+ // form control even with aria-hidden/tabindex=-1.
8386
+ if (this.multiSelect) return;
8387
+
8251
8388
  const selectedOption = event.target.options[event.target.selectedIndex];
8252
8389
  if (!selectedOption) return;
8253
8390
  const selectedValue = selectedOption.value;
8254
8391
 
8255
- if (this.multiSelect) {
8256
- const currentArray = this.menu.value || [];
8257
-
8258
- if (!currentArray.includes(selectedValue)) {
8259
- this.value = JSON.stringify([
8260
- ...currentArray,
8261
- selectedValue
8262
- ]);
8263
- }
8264
- } else {
8265
- const currentValue = this.value;
8266
-
8267
- if (currentValue !== selectedValue) {
8268
- this.value = selectedValue;
8269
- }
8392
+ if (this.value !== selectedValue) {
8393
+ this.value = selectedValue;
8270
8394
  }
8271
8395
  }
8272
8396