@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
@@ -959,19 +959,28 @@ const selectKeyboardStrategy = {
959
959
  },
960
960
 
961
961
  End(component, evt, ctx) {
962
- if (!ctx.isExpanded) {
963
- return;
964
- }
965
962
  evt.preventDefault();
966
963
  evt.stopPropagation();
967
964
  // `pop()` is safe here: getEnabledOptions returns a fresh filtered array.
968
965
  const lastOption = getEnabledOptions(component.menu).pop();
969
- if (lastOption) {
970
- component.menu.updateActiveOption(lastOption);
966
+ if (!lastOption) {
967
+ return;
968
+ }
969
+ // Pre-stash before show() so the auroDropdown-toggled handler's
970
+ // `!optionActive` guard short-circuits the firstActive/selected fallback —
971
+ // otherwise show() synchronously fires the handler and writes
972
+ // aria-activedescendant once before we overwrite it.
973
+ component.menu.updateActiveOption(lastOption);
974
+ if (!ctx.isExpanded) {
975
+ component.dropdown.show();
971
976
  }
972
977
  },
973
978
 
974
979
  Enter(component, evt, ctx) {
980
+ // Prevent the keypress from bubbling to parent containers (e.g., forms)
981
+ // which could interpret Enter as a submit. Matches APG select-only combobox
982
+ // and native <select> behavior: Enter opens the listbox when closed, selects
983
+ // the active option when open — it does not submit a parent form.
975
984
  evt.preventDefault();
976
985
  evt.stopPropagation();
977
986
  if (!ctx.isExpanded) {
@@ -982,14 +991,16 @@ const selectKeyboardStrategy = {
982
991
  },
983
992
 
984
993
  Home(component, evt, ctx) {
985
- if (!ctx.isExpanded) {
986
- return;
987
- }
988
994
  evt.preventDefault();
989
995
  evt.stopPropagation();
990
996
  const [firstOption] = getEnabledOptions(component.menu);
991
- if (firstOption) {
992
- component.menu.updateActiveOption(firstOption);
997
+ if (!firstOption) {
998
+ return;
999
+ }
1000
+ // See End() for why this must run before show().
1001
+ component.menu.updateActiveOption(firstOption);
1002
+ if (!ctx.isExpanded) {
1003
+ component.dropdown.show();
993
1004
  }
994
1005
  },
995
1006
 
@@ -4961,7 +4972,7 @@ let AuroHelpText$1 = class AuroHelpText extends i$2 {
4961
4972
  }
4962
4973
  };
4963
4974
 
4964
- var formkitVersion$1 = '202606291652';
4975
+ var formkitVersion$1 = '202606291737';
4965
4976
 
4966
4977
  class AuroElement extends i$2 {
4967
4978
  static get properties() {
@@ -6233,6 +6244,7 @@ class AuroDropdown extends AuroElement {
6233
6244
  role="${o(this.triggerContentFocusable ? undefined : this.a11yRole)}"
6234
6245
  aria-expanded="${o(this.a11yRole === 'button' || this.triggerContentFocusable ? undefined : this.isPopoverVisible)}"
6235
6246
  aria-controls="${o(this.a11yRole === 'button' || this.triggerContentFocusable ? undefined : this.dropdownId)}"
6247
+ aria-haspopup="${o(this.a11yRole === 'combobox' && !this.triggerContentFocusable ? 'listbox' : undefined)}"
6236
6248
  aria-labelledby="${o(this.triggerContentFocusable ? undefined : 'triggerLabel')}"
6237
6249
  aria-disabled="${o(this.disabled ? 'true' : undefined)}"
6238
6250
  @focusin="${this.handleFocusin}"
@@ -6982,7 +6994,7 @@ class AuroHelpText extends i$2 {
6982
6994
  }
6983
6995
  }
6984
6996
 
6985
- var formkitVersion = '202606291652';
6997
+ var formkitVersion = '202606291737';
6986
6998
 
6987
6999
  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}`;
6988
7000
 
@@ -7314,14 +7326,6 @@ class AuroSelect extends AuroElement$1 {
7314
7326
  reflect: true
7315
7327
  },
7316
7328
 
7317
- /**
7318
- * @private
7319
- */
7320
- options: {
7321
- type: Array,
7322
- state: true
7323
- },
7324
-
7325
7329
  /**
7326
7330
  * Specifies the current selected menuOption. Default type is `HTMLElement`, changing to `Array<HTMLElement>` when `multiSelect` is true.
7327
7331
  * @type {HTMLElement|Array<HTMLElement>}
@@ -7609,16 +7613,68 @@ class AuroSelect extends AuroElement$1 {
7609
7613
  this.dropdown.dropdownWidth = this.customBibWidth;
7610
7614
  }
7611
7615
 
7612
- // Pass label text to the dropdown bib for accessible dialog naming
7613
- const labelElement = this.querySelector('span[slot="label"]');
7614
- if (labelElement) {
7615
- this.dropdown.bibDialogLabel = labelElement.textContent.trim() || undefined;
7616
- }
7616
+ this._syncLabelText();
7617
7617
 
7618
7618
  // Exposes the CSS parts from the dropdown for styling
7619
7619
  this.dropdown.exposeCssParts();
7620
7620
  }
7621
7621
 
7622
+ /**
7623
+ * Reads the current label slot text and pushes it to the dropdown bib
7624
+ * (for dialog naming) and the menu (for listbox aria-label). Safe to call
7625
+ * before either child has been wired up — each branch self-guards.
7626
+ * @private
7627
+ */
7628
+ _syncLabelText() {
7629
+ const labelElement = this.querySelector('[slot="label"]');
7630
+ const text = labelElement ? labelElement.textContent.trim() : '';
7631
+ if (this.dropdown) {
7632
+ this.dropdown.bibDialogLabel = text || undefined;
7633
+ }
7634
+ if (this.menu) {
7635
+ if (text) {
7636
+ this.menu.setAttribute('aria-label', text);
7637
+ } else {
7638
+ this.menu.removeAttribute('aria-label');
7639
+ }
7640
+ }
7641
+ }
7642
+
7643
+ /**
7644
+ * Keeps the dialog/menu accessible names in sync when consumers mutate the
7645
+ * label slot at runtime (e.g., i18n locale swap). `slotchange` alone is
7646
+ * insufficient — it doesn't fire when textContent of an already-assigned
7647
+ * slotted node changes, which is the common case. We scope the observer to
7648
+ * the label node itself (not the whole host subtree) so option-content
7649
+ * mutations don't trigger label re-syncs, and re-target on `slotchange`
7650
+ * when consumers add or replace the label element.
7651
+ * @private
7652
+ */
7653
+ _observeLabelChanges() {
7654
+ if (this._labelObserver) return;
7655
+ this._labelObserver = new MutationObserver(() => this._syncLabelText());
7656
+
7657
+ const retarget = () => {
7658
+ this._labelObserver.disconnect();
7659
+ const labelElement = this.querySelector('[slot="label"]');
7660
+ if (labelElement) {
7661
+ this._labelObserver.observe(labelElement, {
7662
+ childList: true,
7663
+ subtree: true,
7664
+ characterData: true
7665
+ });
7666
+ }
7667
+ this._syncLabelText();
7668
+ };
7669
+
7670
+ retarget();
7671
+
7672
+ this._retargetLabelObserver = retarget;
7673
+ this.shadowRoot.querySelectorAll('slot[name="label"]').forEach((slot) => {
7674
+ slot.addEventListener('slotchange', retarget);
7675
+ });
7676
+ }
7677
+
7622
7678
  /**
7623
7679
  * This will register this element with the browser.
7624
7680
  * @param {string} [name="auro-select"] - The name of element that you want to register to.
@@ -7769,11 +7825,7 @@ class AuroSelect extends AuroElement$1 {
7769
7825
  this.updateMenuShapeSize();
7770
7826
  this.setMenuValue(this.value);
7771
7827
 
7772
- // Set accessible name on the menu for screen readers based on the label slot content
7773
- const labelElement = this.querySelector('[slot="label"]');
7774
- if (labelElement) {
7775
- this.menu.setAttribute('aria-label', labelElement.textContent.trim());
7776
- }
7828
+ this._syncLabelText();
7777
7829
 
7778
7830
  if (this.multiSelect) {
7779
7831
  this.menu.multiSelect = this.multiSelect;
@@ -7785,8 +7837,21 @@ class AuroSelect extends AuroElement$1 {
7785
7837
  if (typeof this.menu.initItems === 'function') {
7786
7838
  this.menu.initItems();
7787
7839
  }
7788
- this.options = this.menu.options;
7789
7840
  this.updateOptionPositions();
7841
+ // renderNativeSelect reads this.menu.options, which the parent doesn't
7842
+ // observe — request an update so the hidden native <option> list reflects
7843
+ // the menu's options after initItems populates them.
7844
+ this.requestUpdate();
7845
+
7846
+ // Keep aria-setsize/aria-posinset (and the native <option> list) in sync
7847
+ // when the menu re-initializes its items — e.g., slotchange, async/lazy
7848
+ // loads, value-triggered re-init. Without this, stale set-size is
7849
+ // announced and the native select goes stale after dynamic mutations.
7850
+ this.menu.addEventListener('auroMenu-optionsChange', () => {
7851
+ this.updateOptionPositions();
7852
+ this.requestUpdate();
7853
+ });
7854
+
7790
7855
  this.menu.addEventListener("auroMenu-loadingChange", (event) => this.handleMenuLoadingChange(event));
7791
7856
 
7792
7857
  this.menu.addEventListener("auroMenu-selectValueFailure", () => {
@@ -7805,11 +7870,26 @@ class AuroSelect extends AuroElement$1 {
7805
7870
  this.dropdown.setActiveDescendant(this.optionActive);
7806
7871
  }
7807
7872
 
7808
- // Announce the active option for screen readers
7809
- if (this.optionActive) {
7873
+ // Live-region announce only for [not selected] options. For activations
7874
+ // on an already-selected option — auto-activation on bib open, arrow
7875
+ // navigation back to the selection, or click in multiSelect — rely on
7876
+ // aria-activedescendant + aria-selected="true" to convey state per the
7877
+ // WAI-ARIA listbox pattern. This is intentional, not limited to the
7878
+ // initial activation on open: it also prevents a duplicate "X, selected"
7879
+ // when Enter on the active+selected option re-fires
7880
+ // auroMenu-selectedOption (see 03b289e39).
7881
+ if (this.optionActive && !this.optionActive.hasAttribute('selected')) {
7810
7882
  const optionText = this.optionActive.textContent.trim();
7811
- const selectedState = this.optionActive.hasAttribute('selected') ? ', selected' : ', not selected';
7812
- announceToScreenReader(this._getAnnouncementRoot(), `${optionText}${selectedState}`);
7883
+ const message = `${optionText}, not selected`;
7884
+ if (this.dropdown.isPopoverVisible) {
7885
+ announceToScreenReader(this._getAnnouncementRoot(), message);
7886
+ } else {
7887
+ // Typeahead-on-closed fires this event before `show()` flips
7888
+ // isPopoverVisible. Defer so the announcement targets the bib's
7889
+ // live region once the fullscreen <dialog> opens — otherwise it
7890
+ // lands in the host root, which is inert under the active modal.
7891
+ queueMicrotask(() => announceToScreenReader(this._getAnnouncementRoot(), message));
7892
+ }
7813
7893
  }
7814
7894
 
7815
7895
  if (this.dropdown.isPopoverVisible) {
@@ -7818,6 +7898,7 @@ class AuroSelect extends AuroElement$1 {
7818
7898
  });
7819
7899
 
7820
7900
  this.menu.addEventListener('auroMenu-selectedOption', () => {
7901
+ const previousSelected = this.optionSelected;
7821
7902
 
7822
7903
  // Update the displayed value
7823
7904
  this.updateDisplayedValue();
@@ -7837,13 +7918,32 @@ class AuroSelect extends AuroElement$1 {
7837
7918
  this.dropdown.trigger.focus();
7838
7919
  }
7839
7920
 
7840
- // Announce the selection after the dropdown closes so it isn't
7841
- // overridden by VoiceOver's "collapsed" announcement from aria-expanded.
7842
- const selectedValue = this.menu.currentLabel;
7843
- const announcementDelay = 300;
7844
- setTimeout(() => {
7845
- announceToScreenReader(this._getAnnouncementRoot(), `${selectedValue}, selected`);
7846
- }, announcementDelay);
7921
+ // Describe the actual change. In multiSelect, currentLabel is the
7922
+ // concatenated remaining list — announcing "{list}, selected" after a
7923
+ // deselect would falsely claim every remaining label was just added.
7924
+ // Diff previous vs next to recover the toggled option.
7925
+ let announcement = '';
7926
+ if (this.multiSelect) {
7927
+ const prev = Array.isArray(previousSelected) ? previousSelected : [];
7928
+ const removed = prev.find((opt) => !nextSelected.includes(opt));
7929
+ const added = nextSelected.find((opt) => !prev.includes(opt));
7930
+ if (removed) {
7931
+ announcement = `${removed.textContent.trim()}, not selected`;
7932
+ } else if (added) {
7933
+ announcement = `${added.textContent.trim()}, selected`;
7934
+ }
7935
+ } else {
7936
+ announcement = `${this.menu.currentLabel}, selected`;
7937
+ }
7938
+
7939
+ // Delay so the utterance isn't overridden by VoiceOver's "collapsed"
7940
+ // announcement from aria-expanded when the dropdown closes.
7941
+ if (announcement) {
7942
+ const announcementDelay = 300;
7943
+ setTimeout(() => {
7944
+ announceToScreenReader(this._getAnnouncementRoot(), announcement);
7945
+ }, announcementDelay);
7946
+ }
7847
7947
  });
7848
7948
  }
7849
7949
 
@@ -7941,24 +8041,32 @@ class AuroSelect extends AuroElement$1 {
7941
8041
 
7942
8042
  this.typeaheadBuffer += key;
7943
8043
 
7944
- const isRepeatedChar = this.typeaheadBuffer.length > 1 && new Set(this.typeaheadBuffer).size === 1;
8044
+ // Prefer the literal buffer as a prefix per WAI-ARIA APG ("focus moves to the
8045
+ // next item with a name that starts with the string of characters typed").
8046
+ // Only fall back to single-char cycling when the repeated buffer has no
8047
+ // longer prefix match — e.g. "aa" cycles through ["Apple", "Apricot"] only
8048
+ // because no option starts with "aa".
8049
+ let match = options.find((option) => this._getOptionDisplayText(option).startsWith(this.typeaheadBuffer));
7945
8050
 
7946
- let match = null;
8051
+ const isRepeatedChar = !match && this.typeaheadBuffer.length > 1 && new Set(this.typeaheadBuffer).size === 1;
7947
8052
  if (isRepeatedChar) {
7948
8053
  const matches = options.filter((option) => this._getOptionDisplayText(option).startsWith(key));
7949
8054
  if (matches.length) {
7950
8055
  const cycleIndex = (this.typeaheadBuffer.length - 1) % matches.length;
7951
8056
  match = matches[cycleIndex];
7952
8057
  }
7953
- } else {
7954
- match = options.find((option) => this._getOptionDisplayText(option).startsWith(this.typeaheadBuffer));
7955
8058
  }
7956
8059
 
8060
+ // Intentional: no-match leaves the bib closed (deviates from APG / some native <select>).
7957
8061
  if (match) {
8062
+ // Pre-stash the match so the auroDropdown-toggled handler's `!optionActive`
8063
+ // guard short-circuits and skips the firstActive/selected fallback —
8064
+ // otherwise show() synchronously fires the handler, which writes
8065
+ // aria-activedescendant once before we overwrite it.
8066
+ this.menu.updateActiveOption(match);
7958
8067
  if (!this.dropdown.isPopoverVisible) {
7959
8068
  this.dropdown.show();
7960
8069
  }
7961
- this.menu.updateActiveOption(match);
7962
8070
  }
7963
8071
  }
7964
8072
 
@@ -8075,6 +8183,28 @@ class AuroSelect extends AuroElement$1 {
8075
8183
  disconnectedCallback() {
8076
8184
  super.disconnectedCallback();
8077
8185
  this._clearTypeaheadBuffer();
8186
+ if (this._labelObserver) {
8187
+ this._labelObserver.disconnect();
8188
+ this._labelObserver = null;
8189
+ }
8190
+ if (this._retargetLabelObserver && this.shadowRoot) {
8191
+ this.shadowRoot.querySelectorAll('slot[name="label"]').forEach((slot) => {
8192
+ slot.removeEventListener('slotchange', this._retargetLabelObserver);
8193
+ });
8194
+ this._retargetLabelObserver = null;
8195
+ }
8196
+ }
8197
+
8198
+ connectedCallback() {
8199
+ super.connectedCallback();
8200
+ // Regression guard: firstUpdated() fires once per instance, so the label
8201
+ // observer setup it triggers does NOT re-run on reconnect. After a
8202
+ // disconnect+reconnect (reparent, SPA route swap), runtime label mutations
8203
+ // would silently stop syncing menu aria-label / dropdown.bibDialogLabel
8204
+ // unless we re-wire the observer here.
8205
+ if (this.hasUpdated) {
8206
+ this._observeLabelChanges();
8207
+ }
8078
8208
  }
8079
8209
 
8080
8210
  // lifecycle runs only after the element's DOM has been updated the first time
@@ -8085,6 +8215,7 @@ class AuroSelect extends AuroElement$1 {
8085
8215
  this.configureDropdown();
8086
8216
  this.configureMenu();
8087
8217
  this.configureSelect();
8218
+ this._observeLabelChanges();
8088
8219
  }
8089
8220
 
8090
8221
  setMenuValue(value) {
@@ -8217,25 +8348,18 @@ class AuroSelect extends AuroElement$1 {
8217
8348
  * @private
8218
8349
  */
8219
8350
  _handleNativeSelectChange(event) {
8351
+ // Hidden native <select> has no `multiple` attribute, so any change it fires
8352
+ // is a single raw value — applying it in multiSelect mode would collapse the
8353
+ // JSON-array `value` shape. Bfcache/autofill can reach this on a name-bearing
8354
+ // form control even with aria-hidden/tabindex=-1.
8355
+ if (this.multiSelect) return;
8356
+
8220
8357
  const selectedOption = event.target.options[event.target.selectedIndex];
8221
8358
  if (!selectedOption) return;
8222
8359
  const selectedValue = selectedOption.value;
8223
8360
 
8224
- if (this.multiSelect) {
8225
- const currentArray = this.menu.value || [];
8226
-
8227
- if (!currentArray.includes(selectedValue)) {
8228
- this.value = JSON.stringify([
8229
- ...currentArray,
8230
- selectedValue
8231
- ]);
8232
- }
8233
- } else {
8234
- const currentValue = this.value;
8235
-
8236
- if (currentValue !== selectedValue) {
8237
- this.value = selectedValue;
8238
- }
8361
+ if (this.value !== selectedValue) {
8362
+ this.value = selectedValue;
8239
8363
  }
8240
8364
  }
8241
8365
 
@@ -169,8 +169,15 @@
169
169
  </td>
170
170
  </tr>
171
171
  <tr>
172
- <td>End</td>
173
- <td>-</td>
172
+ <td rowspan="2">End</td>
173
+ <td rowspan="2">-</td>
174
+ <td>Collapsed</td>
175
+ <td>Trigger element</td>
176
+ <td>
177
+ Opens the bib and advances the <code>focused</code> option to the last enabled option in the list.
178
+ </td>
179
+ </tr>
180
+ <tr>
174
181
  <td>Expanded</td>
175
182
  <td>Trigger element</td>
176
183
  <td>
@@ -198,8 +205,15 @@
198
205
  </td>
199
206
  </tr>
200
207
  <tr>
201
- <td>Home</td>
202
- <td>-</td>
208
+ <td rowspan="2">Home</td>
209
+ <td rowspan="2">-</td>
210
+ <td>Collapsed</td>
211
+ <td>Trigger element</td>
212
+ <td>
213
+ Opens the bib and advances the <code>focused</code> option to the first enabled option in the list.
214
+ </td>
215
+ </tr>
216
+ <tr>
203
217
  <td>Expanded</td>
204
218
  <td>Trigger element</td>
205
219
  <td>
@@ -180,13 +180,6 @@ export class AuroSelect extends AuroElement {
180
180
  type: BooleanConstructor;
181
181
  reflect: boolean;
182
182
  };
183
- /**
184
- * @private
185
- */
186
- options: {
187
- type: ArrayConstructor;
188
- state: boolean;
189
- };
190
183
  /**
191
184
  * Specifies the current selected menuOption. Default type is `HTMLElement`, changing to `Array<HTMLElement>` when `multiSelect` is true.
192
185
  * @type {HTMLElement|Array<HTMLElement>}
@@ -389,6 +382,26 @@ export class AuroSelect extends AuroElement {
389
382
  dropdown: any;
390
383
  optionActive: any;
391
384
  bibtemplate: any;
385
+ /**
386
+ * Reads the current label slot text and pushes it to the dropdown bib
387
+ * (for dialog naming) and the menu (for listbox aria-label). Safe to call
388
+ * before either child has been wired up — each branch self-guards.
389
+ * @private
390
+ */
391
+ private _syncLabelText;
392
+ /**
393
+ * Keeps the dialog/menu accessible names in sync when consumers mutate the
394
+ * label slot at runtime (e.g., i18n locale swap). `slotchange` alone is
395
+ * insufficient — it doesn't fire when textContent of an already-assigned
396
+ * slotted node changes, which is the common case. We scope the observer to
397
+ * the label node itself (not the whole host subtree) so option-content
398
+ * mutations don't trigger label re-syncs, and re-target on `slotchange`
399
+ * when consumers add or replace the label element.
400
+ * @private
401
+ */
402
+ private _observeLabelChanges;
403
+ _labelObserver: MutationObserver | null | undefined;
404
+ _retargetLabelObserver: (() => void) | null | undefined;
392
405
  /**
393
406
  * Updates the displayed value in an Auro dropdown component based on optionSelected.
394
407
  * @private
@@ -425,7 +438,6 @@ export class AuroSelect extends AuroElement {
425
438
  menu: Element | null | undefined;
426
439
  defaultMenuSize: string | null | undefined;
427
440
  defaultMenuShape: string | null | undefined;
428
- options: any;
429
441
  optionSelected: any;
430
442
  /**
431
443
  * Binds all behavior needed to the component after rendering.