@aurodesignsystem/auro-formkit 5.8.0 → 5.9.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 (75) hide show
  1. package/CHANGELOG.md +3 -12
  2. package/components/checkbox/demo/api.min.js +2 -2
  3. package/components/checkbox/demo/index.min.js +2 -2
  4. package/components/checkbox/dist/index.js +2 -2
  5. package/components/checkbox/dist/registered.js +2 -2
  6. package/components/combobox/demo/api.md +7 -6
  7. package/components/combobox/demo/api.min.js +1674 -1004
  8. package/components/combobox/demo/index.md +47 -2
  9. package/components/combobox/demo/index.min.js +1674 -1004
  10. package/components/combobox/dist/auro-combobox.d.ts +9 -8
  11. package/components/combobox/dist/index.js +129 -127
  12. package/components/combobox/dist/registered.js +129 -127
  13. package/components/counter/demo/api.min.js +12 -18
  14. package/components/counter/demo/index.min.js +12 -18
  15. package/components/counter/dist/buttonVersion.d.ts +2 -0
  16. package/components/counter/dist/index.js +12 -18
  17. package/components/counter/dist/registered.js +12 -18
  18. package/components/datepicker/demo/api.min.js +46 -45
  19. package/components/datepicker/demo/index.min.js +46 -45
  20. package/components/datepicker/dist/buttonVersion.d.ts +1 -1
  21. package/components/datepicker/dist/iconVersion.d.ts +1 -1
  22. package/components/datepicker/dist/index.js +46 -45
  23. package/components/datepicker/dist/registered.js +46 -45
  24. package/components/dropdown/demo/api.min.js +6 -8
  25. package/components/dropdown/demo/index.min.js +6 -8
  26. package/components/dropdown/dist/iconVersion.d.ts +1 -1
  27. package/components/dropdown/dist/index.js +6 -8
  28. package/components/dropdown/dist/registered.js +6 -8
  29. package/components/input/demo/api.min.js +33 -24
  30. package/components/input/demo/index.min.js +33 -24
  31. package/components/input/dist/base-input.d.ts +19 -2
  32. package/components/input/dist/buttonVersion.d.ts +1 -1
  33. package/components/input/dist/index.js +33 -24
  34. package/components/input/dist/registered.js +33 -24
  35. package/components/menu/demo/api.js +4 -0
  36. package/components/menu/demo/api.md +271 -26
  37. package/components/menu/demo/api.min.js +1591 -858
  38. package/components/menu/demo/index.html +1 -0
  39. package/components/menu/demo/index.js +2 -0
  40. package/components/menu/demo/index.md +95 -1
  41. package/components/menu/demo/index.min.js +1529 -810
  42. package/components/menu/dist/auro-menu.context.d.ts +222 -0
  43. package/components/menu/dist/auro-menu.d.ts +93 -53
  44. package/components/menu/dist/auro-menuoption.d.ts +115 -13
  45. package/components/menu/dist/index.js +1441 -793
  46. package/components/menu/dist/registered.js +1439 -803
  47. package/components/radio/demo/api.min.js +3 -3
  48. package/components/radio/demo/index.min.js +3 -3
  49. package/components/radio/dist/index.js +3 -3
  50. package/components/radio/dist/registered.js +3 -3
  51. package/components/select/demo/api.md +8 -7
  52. package/components/select/demo/api.min.js +1587 -1020
  53. package/components/select/demo/index.min.js +1587 -1020
  54. package/components/select/dist/auro-select.d.ts +11 -35
  55. package/components/select/dist/index.js +72 -173
  56. package/components/select/dist/registered.js +72 -173
  57. package/package.json +6 -2
  58. package/components/checkbox/dist/helptextVersion.d.ts +0 -2
  59. package/components/combobox/dist/bibtemplateVersion.d.ts +0 -2
  60. package/components/combobox/dist/dropdownVersion.d.ts +0 -2
  61. package/components/combobox/dist/inputVersion.d.ts +0 -2
  62. package/components/counter/dist/bibtemplateVersion.d.ts +0 -2
  63. package/components/counter/dist/dropdownVersion.d.ts +0 -2
  64. package/components/counter/dist/helptextVersion.d.ts +0 -2
  65. package/components/datepicker/dist/bibtemplateVersion.d.ts +0 -2
  66. package/components/datepicker/dist/dropdownVersion.d.ts +0 -2
  67. package/components/datepicker/dist/inputVersion.d.ts +0 -2
  68. package/components/dropdown/dist/dropdownVersion.d.ts +0 -2
  69. package/components/dropdown/dist/helptextVersion.d.ts +0 -2
  70. package/components/input/dist/helptextVersion.d.ts +0 -2
  71. package/components/menu/dist/dropdownVersion.d.ts +0 -2
  72. package/components/radio/dist/helptextVersion.d.ts +0 -2
  73. package/components/select/dist/bibtemplateVersion.d.ts +0 -2
  74. package/components/select/dist/dropdownVersion.d.ts +0 -2
  75. package/components/select/dist/helptextVersion.d.ts +0 -2
@@ -1,6 +1,7 @@
1
1
  import { css, LitElement, html } from 'lit';
2
- import { classMap } from 'lit/directives/class-map.js';
2
+ import { ContextConsumer, createContext, ContextProvider } from '@lit/context';
3
3
  import { unsafeStatic, literal, html as html$1 } from 'lit/static-html.js';
4
+ import { classMap } from 'lit/directives/class-map.js';
4
5
  import { ifDefined } from 'lit/directives/if-defined.js';
5
6
 
6
7
  var styleCss$1 = css`:focus:not(:focus-visible){outline:3px solid transparent}.body-default{font-family:var(--wcss-body-family, "AS Circular"),system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;font-weight:var(--wcss-body-weight, 450);letter-spacing:var(--wcss-body-letter-spacing, 0);font-size:var(--wcss-body-default-font-size, 1rem);line-height:var(--wcss-body-default-line-height, 1.5rem)}.body-lg{font-family:var(--wcss-body-family, "AS Circular"),system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;font-weight:var(--wcss-body-weight, 450);letter-spacing:var(--wcss-body-letter-spacing, 0);font-size:var(--wcss-body-lg-font-size, 1.125rem);line-height:var(--wcss-body-lg-line-height, 1.625rem)}.body-sm{font-family:var(--wcss-body-family, "AS Circular"),system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;font-weight:var(--wcss-body-weight, 450);letter-spacing:var(--wcss-body-letter-spacing, 0);font-size:var(--wcss-body-sm-font-size, 0.875rem);line-height:var(--wcss-body-sm-line-height, 1.25rem)}.body-xs{font-family:var(--wcss-body-family, "AS Circular"),system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;font-weight:var(--wcss-body-weight, 450);letter-spacing:var(--wcss-body-letter-spacing, 0);font-size:var(--wcss-body-xs-font-size, 0.75rem);line-height:var(--wcss-body-xs-line-height, 1rem)}.body-2xs{font-family:var(--wcss-body-family, "AS Circular"),system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;font-weight:var(--wcss-body-weight, 450);letter-spacing:var(--wcss-body-letter-spacing, 0);font-size:var(--wcss-body-2xs-font-size, 0.625rem);line-height:var(--wcss-body-2xs-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);letter-spacing:var(--wcss-display-2xl-letter-spacing, 0);font-weight:var(--wcss-display-2xl-weight, 300);line-height:var(--wcss-display-2xl-line-height, 1.3);font-size:var(--wcss-display-2xl-font-size, clamp(3.5rem, 6vw, 5.375rem))}.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);letter-spacing:var(--wcss-display-xl-letter-spacing, 0);font-weight:var(--wcss-display-xl-weight, 300);line-height:var(--wcss-display-xl-line-height, 1.3);font-size:var(--wcss-display-xl-font-size, clamp(3rem, 5.3333333333vw, 4.5rem))}.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);letter-spacing:var(--wcss-display-lg-letter-spacing, 0);font-weight:var(--wcss-display-lg-weight, 300);line-height:var(--wcss-display-lg-line-height, 1.3);font-size:var(--wcss-display-lg-font-size, clamp(2.75rem, 4.6666666667vw, 4rem))}.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);letter-spacing:var(--wcss-display-md-letter-spacing, 0);font-weight:var(--wcss-display-md-weight, 300);line-height:var(--wcss-display-md-line-height, 1.3);font-size:var(--wcss-display-md-font-size, clamp(2.5rem, 4vw, 3.5rem))}.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);letter-spacing:var(--wcss-display-sm-letter-spacing, 0);font-weight:var(--wcss-display-sm-weight, 300);line-height:var(--wcss-display-sm-line-height, 1.3);font-size:var(--wcss-display-sm-font-size, clamp(2rem, 3.6666666667vw, 3rem))}.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);letter-spacing:var(--wcss-display-xs-letter-spacing, 0);font-weight:var(--wcss-display-xs-weight, 300);line-height:var(--wcss-display-xs-line-height, 1.3);font-size:var(--wcss-display-xs-font-size, clamp(1.75rem, 3vw, 2.375rem))}.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);letter-spacing:var(--wcss-heading-xl-letter-spacing, 0);font-weight:var(--wcss-heading-xl-weight, 300);line-height:var(--wcss-heading-xl-line-height, 1.3);font-size:var(--wcss-heading-xl-font-size, clamp(2rem, 3vw, 2.5rem))}.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);letter-spacing:var(--wcss-heading-lg-letter-spacing, 0);font-weight:var(--wcss-heading-lg-weight, 300);line-height:var(--wcss-heading-lg-line-height, 1.3);font-size:var(--wcss-heading-lg-font-size, clamp(1.75rem, 2.6666666667vw, 2.25rem))}.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);letter-spacing:var(--wcss-heading-md-letter-spacing, 0);font-weight:var(--wcss-heading-md-weight, 300);line-height:var(--wcss-heading-md-line-height, 1.3);font-size:var(--wcss-heading-md-font-size, clamp(1.625rem, 2.3333333333vw, 1.75rem))}.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);letter-spacing:var(--wcss-heading-sm-letter-spacing, 0);font-weight:var(--wcss-heading-sm-weight, 300);line-height:var(--wcss-heading-sm-line-height, 1.3);font-size:var(--wcss-heading-sm-font-size, clamp(1.375rem, 2vw, 1.5rem))}.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);letter-spacing:var(--wcss-heading-xs-letter-spacing, 0);font-weight:var(--wcss-heading-xs-weight, 450);line-height:var(--wcss-heading-xs-line-height, 1.3);font-size:var(--wcss-heading-xs-font-size, clamp(1.25rem, 1.6666666667vw, 1.25rem))}.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);letter-spacing:var(--wcss-heading-2xs-letter-spacing, 0);font-weight:var(--wcss-heading-2xs-weight, 450);line-height:var(--wcss-heading-2xs-line-height, 1.3);font-size:var(--wcss-heading-2xs-font-size, clamp(1.125rem, 1.5vw, 1.125rem))}.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);letter-spacing:var(--wcss-accent-2xl-letter-spacing, 0.05em);font-weight:var(--wcss-accent-2xl-weight, 450);line-height:var(--wcss-accent-2xl-line-height, 1);font-size:var(--wcss-accent-2xl-font-size, clamp(2rem, 3.1666666667vw, 2.375rem));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);letter-spacing:var(--wcss-accent-xl-letter-spacing, 0.05em);font-weight:var(--wcss-accent-xl-weight, 450);line-height:var(--wcss-accent-xl-line-height, 1.3);font-size:var(--wcss-accent-xl-font-size, clamp(1.625rem, 2.3333333333vw, 2rem));text-transform:uppercase}.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);letter-spacing:var(--wcss-accent-lg-letter-spacing, 0.05em);font-weight:var(--wcss-accent-lg-weight, 450);line-height:var(--wcss-accent-lg-line-height, 1.3);font-size:var(--wcss-accent-lg-font-size, clamp(1.5rem, 2.1666666667vw, 1.75rem));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);letter-spacing:var(--wcss-accent-md-letter-spacing, 0.05em);font-weight:var(--wcss-accent-md-weight, 500);line-height:var(--wcss-accent-md-line-height, 1.3);font-size:var(--wcss-accent-md-font-size, clamp(1.375rem, 1.8333333333vw, 1.5rem));text-transform:uppercase}.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);letter-spacing:var(--wcss-accent-sm-letter-spacing, 0.05em);font-weight:var(--wcss-accent-sm-weight, 500);line-height:var(--wcss-accent-sm-line-height, 1.3);font-size:var(--wcss-accent-sm-font-size, clamp(1.125rem, 1.5vw, 1.25rem));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);letter-spacing:var(--wcss-accent-xs-letter-spacing, 0.1em);font-weight:var(--wcss-accent-xs-weight, 500);line-height:var(--wcss-accent-xs-line-height, 1.3);font-size:var(--wcss-accent-xs-font-size, clamp(1rem, 1.3333333333vw, 1rem));text-transform:uppercase}.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);letter-spacing:var(--wcss-accent-2xs-letter-spacing, 0.1em);font-weight:var(--wcss-accent-2xs-weight, 450);line-height:var(--wcss-accent-2xs-line-height, 1.3);font-size:var(--wcss-accent-2xs-font-size, clamp(0.875rem, 1.1666666667vw, 0.875rem));text-transform:uppercase}:host{display:block;vertical-align:middle;line-height:0}:host .menuWrapper{box-sizing:border-box;display:flex;flex-direction:column;width:100%;margin:0;padding:0}:host ::slotted(hr){box-sizing:content-box !important;height:0 !important;overflow:visible !important;margin:var(--ds-size-100, 0.5rem) 0 !important;border-width:0 !important;border-top-width:1px !important;border-top-style:solid !important}:host [loadingplaceholder].empty{opacity:0;position:absolute}:host [loadingplaceholder] slot[name=loadingIcon]{vertical-align:middle;display:inline-block;margin-bottom:var(--ds-size-25, 0.125rem)}:host [loadingplaceholder] slot[name=loadingIcon]::slotted(*){margin-right:var(--ds-size-150, 0.75rem)}:host([root]){overflow-y:auto}:host([root]) .menuWrapper.lg{padding:var(--ds-size-150, 0.75rem);gap:var(--ds-size-50, 0.25rem)}:host([root]) .menuWrapper.xl{padding:var(--ds-size-200, 1rem);gap:var(--ds-size-100, 0.5rem)}`;
@@ -113,6 +114,10 @@ class AuroElement extends LitElement {
113
114
  }
114
115
  }
115
116
 
117
+ var styleCss = css`.body-default{font-family:var(--wcss-body-family, "AS Circular"),system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;font-weight:var(--wcss-body-weight, 450);letter-spacing:var(--wcss-body-letter-spacing, 0);font-size:var(--wcss-body-default-font-size, 1rem);line-height:var(--wcss-body-default-line-height, 1.5rem)}.body-lg{font-family:var(--wcss-body-family, "AS Circular"),system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;font-weight:var(--wcss-body-weight, 450);letter-spacing:var(--wcss-body-letter-spacing, 0);font-size:var(--wcss-body-lg-font-size, 1.125rem);line-height:var(--wcss-body-lg-line-height, 1.625rem)}.body-sm{font-family:var(--wcss-body-family, "AS Circular"),system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;font-weight:var(--wcss-body-weight, 450);letter-spacing:var(--wcss-body-letter-spacing, 0);font-size:var(--wcss-body-sm-font-size, 0.875rem);line-height:var(--wcss-body-sm-line-height, 1.25rem)}.body-xs{font-family:var(--wcss-body-family, "AS Circular"),system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;font-weight:var(--wcss-body-weight, 450);letter-spacing:var(--wcss-body-letter-spacing, 0);font-size:var(--wcss-body-xs-font-size, 0.75rem);line-height:var(--wcss-body-xs-line-height, 1rem)}.body-2xs{font-family:var(--wcss-body-family, "AS Circular"),system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;font-weight:var(--wcss-body-weight, 450);letter-spacing:var(--wcss-body-letter-spacing, 0);font-size:var(--wcss-body-2xs-font-size, 0.625rem);line-height:var(--wcss-body-2xs-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);letter-spacing:var(--wcss-display-2xl-letter-spacing, 0);font-weight:var(--wcss-display-2xl-weight, 300);line-height:var(--wcss-display-2xl-line-height, 1.3);font-size:var(--wcss-display-2xl-font-size, clamp(3.5rem, 6vw, 5.375rem))}.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);letter-spacing:var(--wcss-display-xl-letter-spacing, 0);font-weight:var(--wcss-display-xl-weight, 300);line-height:var(--wcss-display-xl-line-height, 1.3);font-size:var(--wcss-display-xl-font-size, clamp(3rem, 5.3333333333vw, 4.5rem))}.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);letter-spacing:var(--wcss-display-lg-letter-spacing, 0);font-weight:var(--wcss-display-lg-weight, 300);line-height:var(--wcss-display-lg-line-height, 1.3);font-size:var(--wcss-display-lg-font-size, clamp(2.75rem, 4.6666666667vw, 4rem))}.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);letter-spacing:var(--wcss-display-md-letter-spacing, 0);font-weight:var(--wcss-display-md-weight, 300);line-height:var(--wcss-display-md-line-height, 1.3);font-size:var(--wcss-display-md-font-size, clamp(2.5rem, 4vw, 3.5rem))}.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);letter-spacing:var(--wcss-display-sm-letter-spacing, 0);font-weight:var(--wcss-display-sm-weight, 300);line-height:var(--wcss-display-sm-line-height, 1.3);font-size:var(--wcss-display-sm-font-size, clamp(2rem, 3.6666666667vw, 3rem))}.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);letter-spacing:var(--wcss-display-xs-letter-spacing, 0);font-weight:var(--wcss-display-xs-weight, 300);line-height:var(--wcss-display-xs-line-height, 1.3);font-size:var(--wcss-display-xs-font-size, clamp(1.75rem, 3vw, 2.375rem))}.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);letter-spacing:var(--wcss-heading-xl-letter-spacing, 0);font-weight:var(--wcss-heading-xl-weight, 300);line-height:var(--wcss-heading-xl-line-height, 1.3);font-size:var(--wcss-heading-xl-font-size, clamp(2rem, 3vw, 2.5rem))}.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);letter-spacing:var(--wcss-heading-lg-letter-spacing, 0);font-weight:var(--wcss-heading-lg-weight, 300);line-height:var(--wcss-heading-lg-line-height, 1.3);font-size:var(--wcss-heading-lg-font-size, clamp(1.75rem, 2.6666666667vw, 2.25rem))}.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);letter-spacing:var(--wcss-heading-md-letter-spacing, 0);font-weight:var(--wcss-heading-md-weight, 300);line-height:var(--wcss-heading-md-line-height, 1.3);font-size:var(--wcss-heading-md-font-size, clamp(1.625rem, 2.3333333333vw, 1.75rem))}.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);letter-spacing:var(--wcss-heading-sm-letter-spacing, 0);font-weight:var(--wcss-heading-sm-weight, 300);line-height:var(--wcss-heading-sm-line-height, 1.3);font-size:var(--wcss-heading-sm-font-size, clamp(1.375rem, 2vw, 1.5rem))}.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);letter-spacing:var(--wcss-heading-xs-letter-spacing, 0);font-weight:var(--wcss-heading-xs-weight, 450);line-height:var(--wcss-heading-xs-line-height, 1.3);font-size:var(--wcss-heading-xs-font-size, clamp(1.25rem, 1.6666666667vw, 1.25rem))}.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);letter-spacing:var(--wcss-heading-2xs-letter-spacing, 0);font-weight:var(--wcss-heading-2xs-weight, 450);line-height:var(--wcss-heading-2xs-line-height, 1.3);font-size:var(--wcss-heading-2xs-font-size, clamp(1.125rem, 1.5vw, 1.125rem))}.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);letter-spacing:var(--wcss-accent-2xl-letter-spacing, 0.05em);font-weight:var(--wcss-accent-2xl-weight, 450);line-height:var(--wcss-accent-2xl-line-height, 1);font-size:var(--wcss-accent-2xl-font-size, clamp(2rem, 3.1666666667vw, 2.375rem));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);letter-spacing:var(--wcss-accent-xl-letter-spacing, 0.05em);font-weight:var(--wcss-accent-xl-weight, 450);line-height:var(--wcss-accent-xl-line-height, 1.3);font-size:var(--wcss-accent-xl-font-size, clamp(1.625rem, 2.3333333333vw, 2rem));text-transform:uppercase}.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);letter-spacing:var(--wcss-accent-lg-letter-spacing, 0.05em);font-weight:var(--wcss-accent-lg-weight, 450);line-height:var(--wcss-accent-lg-line-height, 1.3);font-size:var(--wcss-accent-lg-font-size, clamp(1.5rem, 2.1666666667vw, 1.75rem));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);letter-spacing:var(--wcss-accent-md-letter-spacing, 0.05em);font-weight:var(--wcss-accent-md-weight, 500);line-height:var(--wcss-accent-md-line-height, 1.3);font-size:var(--wcss-accent-md-font-size, clamp(1.375rem, 1.8333333333vw, 1.5rem));text-transform:uppercase}.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);letter-spacing:var(--wcss-accent-sm-letter-spacing, 0.05em);font-weight:var(--wcss-accent-sm-weight, 500);line-height:var(--wcss-accent-sm-line-height, 1.3);font-size:var(--wcss-accent-sm-font-size, clamp(1.125rem, 1.5vw, 1.25rem));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);letter-spacing:var(--wcss-accent-xs-letter-spacing, 0.1em);font-weight:var(--wcss-accent-xs-weight, 500);line-height:var(--wcss-accent-xs-line-height, 1.3);font-size:var(--wcss-accent-xs-font-size, clamp(1rem, 1.3333333333vw, 1rem));text-transform:uppercase}.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);letter-spacing:var(--wcss-accent-2xs-letter-spacing, 0.1em);font-weight:var(--wcss-accent-2xs-weight, 450);line-height:var(--wcss-accent-2xs-line-height, 1.3);font-size:var(--wcss-accent-2xs-font-size, clamp(0.875rem, 1.1666666667vw, 0.875rem));text-transform:uppercase}:host{cursor:pointer;user-select:none;text-overflow:ellipsis;max-width:100dvw}:host .wrapper{display:flex;align-items:center;padding-right:var(--ds-size-200, 1rem);padding-left:calc(var(--ds-size-150, 0.75rem) + var(--ds-size-300, 1.5rem) + var(--ds-size-100, 0.5rem));padding-top:var(--ds-size-50, 0.25rem);padding-bottom:var(--ds-size-50, 0.25rem);border-radius:var(--ds-size-100, 0.5rem);-webkit-tap-highlight-color:transparent}:host .wrapper[class*=shape-box]{border-radius:unset}:host .wrapper[class*=shape-snowflake]{border-radius:unset;line-height:24px}:host .wrapper[class*=shape-pill]{border-radius:30px}:host .wrapper[class*=-lg]{padding-top:var(--ds-size-75, 0.375rem);padding-bottom:var(--ds-size-75, 0.375rem);padding-right:var(--ds-size-150, 0.75rem);line-height:26px}:host .wrapper[class*=-xl]{padding-top:var(--ds-size-100, 0.5rem);padding-bottom:var(--ds-size-100, 0.5rem);padding-right:var(--ds-size-200, 1rem);line-height:26px}:host slot{display:block;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}:host [auro-icon]{--ds-auro-icon-size: var(--ds-size-300, 1.5rem);margin-right:var(--ds-size-150, 0.75rem);margin-left:var(--ds-size-100, 0.5rem)}:host ::slotted(.nestingSpacer){display:inline-block;width:var(--ds-size-300, 1.5rem)}[slot=displayValue]{display:none}:host([loadingplaceholder]) .wrapper{padding-left:calc(var(--ds-size-150, 0.75rem) + var(--ds-size-300, 1.5rem) + var(--ds-size-100, 0.5rem))}:host([selected]) .wrapper{padding-left:0}:host([nocheckmark]) .wrapper{padding-left:var(--ds-size-150, 0.75rem)}:host([nocheckmark]) .wrapper[class*=-lg]{padding-left:var(--ds-size-150, 0.75rem)}:host([nocheckmark]) .wrapper[class*=-xl]{padding-left:var(--ds-size-200, 1rem)}:host([hidden]){display:none}:host([static]){pointer-events:none}:host([disabled]:hover){cursor:auto}:host([disabled]){user-select:none;pointer-events:none}`;
118
+
119
+ var colorCss = css`:host .wrapper{background-color:var(--ds-auro-menuoption-container-color, transparent);box-shadow:inset 0 0 0 1px var(--ds-auro-menuoption-container-border-color, transparent);color:var(--ds-auro-menuoption-text-color)}:host svg{fill:var(--ds-auro-menuoption-icon-color)}:host([disabled]){--ds-auro-menuoption-container-color: var(--ds-basic-color-surface-default, #ffffff);--ds-auro-menuoption-text-color: var(--ds-basic-color-texticon-disabled, #d0d0d0);--ds-auro-menuoption-icon-color: var(--ds-basic-color-texticon-disabled, #d0d0d0)}:host(:hover),:host(.active){--ds-auro-menuoption-container-color: var(--ds-basic-color-surface-accent1-muted, #ebfafd)}:host(:focus){--ds-auro-menuoption-container-color: var(--ds-basic-color-surface-default, #ffffff);--ds-auro-menuoption-container-border-color: var(--ds-basic-color-border-brand, #00274a)}:host([selected]){--ds-auro-menuoption-container-color: var(--ds-basic-color-surface-accent1-subtle, #b4eff9);--ds-auro-menuoption-text-color: var(--ds-basic-color-texticon-default, #2a2a2a);--ds-auro-menuoption-icon-color: var(--ds-basic-color-texticon-default, #2a2a2a)}:host([selected]:hover),:host([selected].active){--ds-auro-menuoption-container-color: var(--ds-basic-color-surface-accent1-muted, #ebfafd)}:host([selected]:focus){--ds-auro-menuoption-container-color: var(--ds-basic-color-surface-accent1-subtle, #b4eff9);--ds-auro-menuoption-container-border-color: var(--ds-basic-color-border-brand, #00274a)}:host(:focus:hover),:host(:focus.active){--ds-auro-menuoption-container-color: var(--ds-basic-color-surface-accent1-muted, #ebfafd);--ds-auro-menuoption-container-border-color: var(--ds-basic-color-border-brand, #00274a)}:host([selected]:focus:hover),:host([selected]:focus.active){--ds-auro-menuoption-container-color: var(--ds-basic-color-surface-accent1-muted, #ebfafd);--ds-auro-menuoption-container-border-color: var(--ds-basic-color-border-brand, #00274a)}`;
120
+
116
121
  // Copyright (c) Alaska Air. All right reserved. Licensed under the Apache-2.0 license
117
122
  // See LICENSE in the project root for license information.
118
123
 
@@ -196,6 +201,74 @@ class AuroLibraryRuntimeUtils {
196
201
  }
197
202
  }
198
203
 
204
+ // Copyright (c) Alaska Air. All right reserved. Licensed under the Apache-2.0 license
205
+ // See LICENSE in the project root for license information.
206
+
207
+
208
+ class AuroDependencyVersioning {
209
+
210
+ /**
211
+ * Generates a unique string to be used for child auro element naming.
212
+ * @private
213
+ * @param {string} baseName - Defines the first part of the unique element name.
214
+ * @param {string} version - Version of the component that will be appended to the baseName.
215
+ * @returns {string} - Unique string to be used for naming.
216
+ */
217
+ generateElementName(baseName, version) {
218
+ let result = baseName;
219
+
220
+ result += '-';
221
+ result += version.replace(/[.]/g, '_');
222
+
223
+ return result;
224
+ }
225
+
226
+ /**
227
+ * Generates a unique string to be used for child auro element naming.
228
+ * @param {string} baseName - Defines the first part of the unique element name.
229
+ * @param {string} version - Version of the component that will be appended to the baseName.
230
+ * @returns {string} - Unique string to be used for naming.
231
+ */
232
+ generateTag(baseName, version, tagClass) {
233
+ const elementName = this.generateElementName(baseName, version);
234
+ const tag = literal`${unsafeStatic(elementName)}`;
235
+
236
+ if (!customElements.get(elementName)) {
237
+ customElements.define(elementName, class extends tagClass {});
238
+ }
239
+
240
+ return tag;
241
+ }
242
+ }
243
+
244
+ class p{registerComponent(t,a){customElements.get(t)||customElements.define(t,class extends a{});}closestElement(t,a=this,e=(a,s=a&&a.closest(t))=>a&&a!==document&&a!==window?s||e(a.getRootNode().host):null){return e(a)}handleComponentTagRename(t,a){const e=a.toLowerCase();t.tagName.toLowerCase()!==e&&t.setAttribute(e,true);}elementMatch(t,a){const e=a.toLowerCase();return t.tagName.toLowerCase()===e||t.hasAttribute(e)}}var u='<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-labelledby="error__desc" class="ico_squareLarge" data-deprecated="true" role="img" style="min-width:var(--auro-size-lg, var(--ds-size-300, 1.5rem));height:var(--auro-size-lg, var(--ds-size-300, 1.5rem));fill:currentColor" viewBox="0 0 24 24" part="svg"><title/><desc id="error__desc">Error alert indicator.</desc><path d="m13.047 5.599 6.786 11.586A1.207 1.207 0 0 1 18.786 19H5.214a1.207 1.207 0 0 1-1.047-1.815l6.786-11.586a1.214 1.214 0 0 1 2.094 0m-1.165.87a.23.23 0 0 0-.085.085L5.419 17.442a.232.232 0 0 0 .203.35h12.756a.234.234 0 0 0 .203-.35L12.203 6.554a.236.236 0 0 0-.321-.084M12 15.5a.75.75 0 1 1 0 1.5.75.75 0 0 1 0-1.5m-.024-6.22c.325 0 .589.261.589.583v4.434a.586.586 0 0 1-.589.583.586.586 0 0 1-.588-.583V9.863c0-.322.264-.583.588-.583"/></svg>';class m extends LitElement{static get properties(){return {hidden:{type:Boolean,reflect:true},hiddenVisually:{type:Boolean,reflect:true},hiddenAudible:{type:Boolean,reflect:true}}}hideAudible(t){return t?"true":"false"}}const g=new Map,f=(t,a={})=>{const e=a.responseParser||(t=>t.text());return g.has(t)||g.set(t,fetch(t).then(e)),g.get(t)};var w=css`:focus:not(:focus-visible){outline:3px solid transparent}.util_displayInline{display:inline}.util_displayInlineBlock{display:inline-block}.util_displayBlock,:host{display:block}.util_displayFlex{display:flex}.util_displayHidden,:host([hidden]:not(:focus):not(:active)){display:none}.util_displayHiddenVisually,:host([hiddenVisually]:not(:focus):not(:active)){position:absolute;overflow:hidden;clip:rect(1px,1px,1px,1px);width:1px;height:1px;padding:0;border:0}.ico_squareLarge{fill:currentColor;height:var(--auro-size-lg, var(--ds-size-300, 1.5rem))}.ico_squareSmall{fill:currentColor;height:.6rem}.ico_squareMed{fill:currentColor;height:var(--auro-size-md, var(--ds-size-200, 1rem))}.ico_squareSml{fill:currentColor;height:var(--auro-size-sm, var(--ds-size-150, .75rem))}:host{color:currentColor;vertical-align:middle;line-height:1;display:inline-block}svg{min-width:var(--ds-auro-icon-size, 1.5rem)!important;width:var(--ds-auro-icon-size, 1.5rem)!important;height:var(--ds-auro-icon-size, 1.5rem)!important}.componentWrapper{display:flex}.svgWrapper{height:var(--ds-auro-icon-size);width:var(--ds-auro-icon-size)}.labelWrapper{margin-left:var(--ds-size-50, .25rem);line-height:1.8}
245
+ `;class z extends m{constructor(){super(),this.onDark=false,this.appearance="default";}static get properties(){return {...m.properties,onDark:{type:Boolean,reflect:true},appearance:{type:String,reflect:true},svg:{attribute:false,reflect:true}}}static get styles(){return w}async fetchIcon(t,a){let e="";e="logos"===t?await f(`${this.uri}/${t}/${a}.svg`):await f(`${this.uri}/icons/${t}/${a}.svg`);return (new DOMParser).parseFromString(e,"text/html").body.querySelector("svg")}async firstUpdated(){try{if(!this.customSvg){const t=await this.fetchIcon(this.category,this.name);if(t)this.svg=t;else if(!t){const t=(new DOMParser).parseFromString(u,"text/html");this.svg=t.body.firstChild;}}}catch(t){this.svg=void 0;}}}css`.util_displayInline{display:inline}.util_displayInlineBlock{display:inline-block}.util_displayBlock,:host{display:block}.util_displayFlex{display:flex}.util_displayHidden,:host([hidden]:not(:focus):not(:active)){display:none}.util_displayHiddenVisually,:host([hiddenVisually]:not(:focus):not(:active)){position:absolute;overflow:hidden;clip:rect(1px,1px,1px,1px);width:1px;height:1px;padding:0;border:0}:host{display:inline-block;--ds-auro-icon-size: 100%;width:100%;height:100%}:host .logo{color:var(--ds-auro-alaska-color)}:host([onDark]),:host([appearance=inverse]){--ds-auro-alaska-color: #FFF}
246
+ `;var y=css`:host{--ds-auro-icon-color: var(--ds-basic-color-texticon-default, #2a2a2a);--ds-auro-alaska-color: #02426D;--ds-auro-icon-size: var(--ds-size-300, 1.5rem)}
247
+ `;var k=css`:host{color:var(--ds-auro-icon-color)}:host([customColor]){color:inherit}:host(:not([onDark])[variant=accent1]),:host(:not([appearance=inverse])[variant=accent1]){--ds-auro-icon-color: var(--ds-basic-color-texticon-accent1, #265688)}:host(:not([onDark])[variant=disabled]),:host(:not([appearance=inverse])[variant=disabled]){--ds-auro-icon-color: var(--ds-basic-color-texticon-disabled, #d0d0d0)}:host(:not([onDark])[variant=muted]),:host(:not([appearance=inverse])[variant=muted]){--ds-auro-icon-color: var(--ds-basic-color-texticon-muted, #676767)}:host(:not([onDark])[variant=statusDefault]),:host(:not([appearance=inverse])[variant=statusDefault]){--ds-auro-icon-color: var(--ds-basic-color-status-default, #afb9c6)}:host(:not([onDark])[variant=statusInfo]),:host(:not([appearance=inverse])[variant=statusInfo]){--ds-auro-icon-color: var(--ds-basic-color-status-info, #01426a)}:host(:not([onDark])[variant=statusSuccess]),:host(:not([appearance=inverse])[variant=statusSuccess]){--ds-auro-icon-color: var(--ds-basic-color-status-success, #447a1f)}:host(:not([onDark])[variant=statusWarning]),:host(:not([appearance=inverse])[variant=statusWarning]){--ds-auro-icon-color: var(--ds-basic-color-status-warning, #fac200)}:host(:not([onDark])[variant=statusError]),:host(:not([appearance=inverse])[variant=statusError]){--ds-auro-icon-color: var(--ds-basic-color-status-error, #e31f26)}:host(:not([onDark])[variant=statusInfoSubtle]),:host(:not([appearance=inverse])[variant=statusInfoSubtle]){--ds-auro-icon-color: var(--ds-basic-color-status-info-subtle, #ebf3f9)}:host(:not([onDark])[variant=statusSuccessSubtle]),:host(:not([appearance=inverse])[variant=statusSuccessSubtle]){--ds-auro-icon-color: var(--ds-basic-color-status-success-subtle, #d6eac7)}:host(:not([onDark])[variant=statusWarningSubtle]),:host(:not([appearance=inverse])[variant=statusWarningSubtle]){--ds-auro-icon-color: var(--ds-basic-color-status-warning-subtle, #fff0b2)}:host(:not([onDark])[variant=statusErrorSubtle]),:host(:not([appearance=inverse])[variant=statusErrorSubtle]){--ds-auro-icon-color: var(--ds-basic-color-status-error-subtle, #fbc6c6)}:host(:not([onDark])[variant=fareBasicEconomy]),:host(:not([appearance=inverse])[variant=fareBasicEconomy]){--ds-auro-icon-color: var(--ds-basic-color-fare-basiceconomy, #97eaf8)}:host(:not([onDark])[variant=fareBusiness]),:host(:not([appearance=inverse])[variant=fareBusiness]){--ds-auro-icon-color: var(--ds-basic-color-fare-business, #01426a)}:host(:not([onDark])[variant=fareEconomy]),:host(:not([appearance=inverse])[variant=fareEconomy]){--ds-auro-icon-color: var(--ds-basic-color-fare-economy, #0074ca)}:host(:not([onDark])[variant=fareFirst]),:host(:not([appearance=inverse])[variant=fareFirst]){--ds-auro-icon-color: var(--ds-basic-color-fare-first, #00274a)}:host(:not([onDark])[variant=farePremiumEconomy]),:host(:not([appearance=inverse])[variant=farePremiumEconomy]){--ds-auro-icon-color: var(--ds-basic-color-fare-premiumeconomy, #005154)}:host(:not([onDark])[variant=tierOneWorldEmerald]),:host(:not([appearance=inverse])[variant=tierOneWorldEmerald]){--ds-auro-icon-color: var(--ds-basic-color-tier-program-oneworld-emerald, #139142)}:host(:not([onDark])[variant=tierOneWorldSapphire]),:host(:not([appearance=inverse])[variant=tierOneWorldSapphire]){--ds-auro-icon-color: var(--ds-basic-color-tier-program-oneworld-sapphire, #015daa)}:host(:not([onDark])[variant=tierOneWorldRuby]),:host(:not([appearance=inverse])[variant=tierOneWorldRuby]){--ds-auro-icon-color: var(--ds-basic-color-tier-program-oneworld-ruby, #a41d4a)}:host([onDark]),:host([appearance=inverse]){--ds-auro-icon-color: var(--ds-basic-color-texticon-inverse, #ffffff)}:host([onDark][variant=disabled]),:host([appearance=inverse][variant=disabled]){--ds-auro-icon-color: var(--ds-basic-color-texticon-inverse-disabled, #7e8894)}:host([onDark][variant=muted]),:host([appearance=inverse][variant=muted]){--ds-auro-icon-color: var(--ds-basic-color-texticon-inverse-muted, #ccd2db)}:host([onDark][variant=statusError]),:host([appearance=inverse][variant=statusError]){--ds-auro-icon-color: var(--ds-advanced-color-state-error-inverse, #f9a4a8)}
248
+ `;class x extends z{constructor(){super(),this.variant=void 0,this.privateDefaults();}privateDefaults(){this.uri="https://cdn.jsdelivr.net/npm/@alaskaairux/icons@latest/dist",this.runtimeUtils=new p;}static get properties(){return {...z.properties,ariaHidden:{type:String,reflect:true},category:{type:String,reflect:true},customColor:{type:Boolean,reflect:true},customSvg:{type:Boolean},label:{type:Boolean,reflect:true},name:{type:String,reflect:true},variant:{type:String,reflect:true}}}static get styles(){return [z.styles,y,w,k]}static register(t="auro-icon"){p.prototype.registerComponent(t,x);}connectedCallback(){super.connectedCallback(),this.runtimeUtils.handleComponentTagRename(this,"auro-icon");}exposeCssParts(){this.setAttribute("exportparts","svg:iconSvg");}async firstUpdated(){if(await super.firstUpdated(),this.hasAttribute("ariaHidden")&&this.svg){const t=this.svg.querySelector("desc");t&&(t.remove(),this.svg.removeAttribute("aria-labelledby"));}}render(){const t={labelWrapper:true,util_displayHiddenVisually:!this.label};return html`
249
+ <div class="componentWrapper">
250
+ <div
251
+ class="${classMap({svgWrapper:true})}"
252
+ title="${ifDefined(this.title||void 0)}">
253
+ <span aria-hidden="${ifDefined(this.ariaHidden||true)}" part="svg">
254
+ ${this.customSvg?html`
255
+ <slot name="svg"></slot>
256
+ `:html`
257
+ ${this.svg}
258
+ `}
259
+ </span>
260
+ </div>
261
+
262
+ <div class="${classMap(t)}" part="label">
263
+ <slot></slot>
264
+ </div>
265
+ </div>
266
+ `}}
267
+
268
+ var iconVersion = '9.1.0';
269
+
270
+ var checkmarkIcon = {"svg":"<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" aria-labelledby=\"checkmark-sm__desc\" class=\"ico_squareLarge\" role=\"img\" style=\"min-width:var(--auro-size-lg, var(--ds-size-300, 1.5rem));height:var(--auro-size-lg, var(--ds-size-300, 1.5rem));fill:currentColor\" viewBox=\"0 0 24 24\" part=\"svg\"><title/><desc id=\"checkmark-sm__desc\">a small check mark.</desc><path d=\"M8.461 11.84a.625.625 0 1 0-.922.844l2.504 2.738c.247.27.674.27.922 0l5.496-6a.625.625 0 1 0-.922-.844l-5.035 5.496z\"/></svg>"};
271
+
199
272
  // Copyright (c) 2021 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
200
273
  // See LICENSE in the project root for license information.
201
274
 
@@ -273,755 +346,1572 @@ function dispatchMenuEvent(element, eventName, detail = null) {
273
346
  element.dispatchEvent(new CustomEvent(eventName, eventConfig));
274
347
  }
275
348
 
276
- // Copyright (c) 2025 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
349
+ // Copyright (c) 2021 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
277
350
  // See LICENSE in the project root for license information.
278
351
 
279
352
 
280
-
281
- // See https://git.io/JJ6SJ for "How to document your components using JSDoc"
282
353
  /**
283
- * The auro-menu element provides users a way to select from a list of options.
284
- * @attr {HTMLElement|Array<HTMLElement>} optionSelected - An array of currently selected menu options, type `HTMLElement` by default. In multi-select mode, `optionSelected` is an array of HTML elements.
285
- * @attr {object} optionactive - Specifies the current active menuOption.
286
- * @attr {string} matchword - Specifies a string used to highlight matched string parts in options.
287
- * @attr {boolean} disabled - When true, the entire menu and all options are disabled;
288
- * @attr {boolean} nocheckmark - When true, selected option will not show the checkmark.
289
- * @attr {boolean} loading - When true, displays a loading state using the loadingIcon and loadingText slots if provided.
290
- * @attr {boolean} multiselect - When true, the selected option can be multiple options.
291
- * @prop {boolean} hasLoadingPlaceholder - Indicates whether the menu has a loadingIcon or loadingText to render when in a loading state.
292
- * @event {CustomEvent<Element>} auroMenu-activatedOption - Notifies that a menuoption has been made `active`.
293
- * @event {CustomEvent<any>} auroMenu-customEventFired - Notifies that a custom event has been fired.
294
- * @event {CustomEvent<{ loading: boolean; hasLoadingPlaceholder: boolean; }>} auroMenu-loadingChange - Notifies when the loading attribute is changed.
295
- * @event {CustomEvent<any>} auroMenu-selectValueFailure - Notifies that an attempt to select a menuoption by matching a value has failed.
296
- * @event {CustomEvent<any>} auroMenu-selectValueReset - Notifies that the component value has been reset.
297
- * @event {CustomEvent<any>} auroMenu-selectedOption - Notifies that a new menuoption selection has been made.
298
- * @slot loadingText - Text to show while loading attribute is set
299
- * @slot loadingIcon - Icon to show while loading attribute is set
300
- * @slot - Slot for insertion of menu options.
354
+ * The auro-menu element provides users a way to define a menu option.
355
+ *
356
+ * @attr {String} value - Specifies the value to be sent to a server.
357
+ * @attr {String} noCheckmark - When true, selected option will not show the checkmark.
358
+ * @attr {Boolean} disabled - When true specifies that the menuoption is disabled.
359
+ * @attr {Boolean} selected - Specifies that an option is selected.
360
+ * @event auroMenuOption-mouseover - Notifies that this option has been hovered over.
361
+ * @slot - Specifies text for an option, but is not the value.
301
362
  */
363
+ class AuroMenuOption extends AuroElement {
302
364
 
303
- /* eslint-disable no-magic-numbers, max-lines, no-extra-parens */
365
+ /**
366
+ * This will register this element with the browser.
367
+ * @param {string} [name="auro-menuoption"] - The name of element that you want to register to.
368
+ *
369
+ * @example
370
+ * AuroMenuOption.register("custom-menuoption") // this will register this element to <custom-menuoption/>
371
+ *
372
+ */
373
+ static register(name = "auro-menuoption") {
374
+ AuroLibraryRuntimeUtils.prototype.registerComponent(name, AuroMenuOption);
375
+ }
376
+
377
+ /**
378
+ * Returns whether the menu option is currently active and selectable.
379
+ * An option is considered active if it is not hidden, not disabled, and not static.
380
+ * @returns {boolean} True if the option is active, false otherwise.
381
+ */
382
+ get isActive() {
383
+ return !this.hasAttribute('hidden') &&
384
+ !this.disabled &&
385
+ !this.hasAttribute('static');
386
+ }
304
387
 
305
- class AuroMenu extends AuroElement {
306
388
  constructor() {
307
389
  super();
308
390
 
309
- // State properties (reactive)
310
-
311
- /**
312
- * @private
313
- */
314
- this.shape = "box";
391
+ this.bindEvents();
315
392
 
316
393
  /**
317
394
  * @private
318
395
  */
319
- this.size = "sm";
320
-
321
- // Value of the selected options
322
- this.value = undefined;
323
- // Currently selected option
324
- this.optionSelected = undefined;
325
- // String used for highlighting/filtering
326
- this.matchWord = undefined;
327
- // Hide the checkmark icon on selected options
328
- this.noCheckmark = false;
329
- // Currently active option
330
- this.optionActive = undefined;
331
- // Loading state
332
- this.loading = false;
333
- // Multi-select mode
334
- this.multiSelect = false;
335
-
336
- // Event Bindings
396
+ this.shape = undefined;
337
397
 
338
398
  /**
339
399
  * @private
340
400
  */
341
- this.handleKeyDown = this.handleKeyDown.bind(this);
401
+ this.size = undefined;
342
402
 
343
403
  /**
344
- * @private
404
+ * Generate unique names for dependency components.
345
405
  */
346
- this.handleMouseSelect = this.handleMouseSelect.bind(this);
406
+ const versioning = new AuroDependencyVersioning();
407
+ this.iconTag = versioning.generateTag('auro-formkit-menuoption-icon', iconVersion, x);
347
408
 
348
- /**
349
- * @private
350
- */
351
- this.handleOptionHover = this.handleOptionHover.bind(this);
409
+ this.selected = false;
410
+ this.nocheckmark = false;
411
+ this.disabled = false;
352
412
 
353
413
  /**
354
414
  * @private
355
415
  */
356
- this.handleSlotChange = this.handleSlotChange.bind(this);
416
+ this.runtimeUtils = new AuroLibraryRuntimeUtils();
357
417
 
358
- // Instance properties (non-reactive)
418
+ // Initialize context-related properties
419
+ this.menuService = null;
420
+ this.unsubscribe = null;
359
421
 
360
422
  /**
361
423
  * @private
362
424
  */
363
- Object.assign(this, {
364
- // Root-level menu (true) or a nested submenu (false)
365
- rootMenu: true,
366
- // Currently focused/active menu item index
367
- index: -1,
368
- // Nested menu spacer
369
- nestingSpacer: '<span class="nestingSpacer"></span>',
370
- // Loading indicator for slot elements
371
- loadingSlots: null,
372
- // Store for menu items
373
- items: [],
374
- });
425
+ this.handleMenuChange = this.handleMenuChange.bind(this);
375
426
  }
376
427
 
377
428
  static get properties() {
378
429
  return {
379
430
  ...super.properties,
380
- noCheckmark: {
381
- type: Boolean,
382
- reflect: true,
383
- attribute: 'nocheckmark'
384
- },
385
431
  disabled: {
386
432
  type: Boolean,
387
433
  reflect: true
388
434
  },
389
- loading: {
390
- type: Boolean,
435
+ event: {
436
+ type: String,
391
437
  reflect: true
392
438
  },
393
- optionSelected: {
394
- // Allow HTMLElement, HTMLElement[] arrays and undefined
395
- type: Object
439
+ key: {
440
+ type: String,
441
+ reflect: true
396
442
  },
397
- optionActive: {
443
+ menuService: {
398
444
  type: Object,
399
- attribute: 'optionactive'
445
+ state: true
400
446
  },
401
447
  matchWord: {
402
448
  type: String,
403
- attribute: 'matchword'
449
+ state: true
404
450
  },
405
- multiSelect: {
451
+ nocheckmark: {
406
452
  type: Boolean,
407
- reflect: true,
408
- attribute: 'multiselect'
453
+ reflect: true
454
+ },
455
+ selected: {
456
+ type: Boolean,
457
+ reflect: true
458
+ },
459
+ tabIndex: {
460
+ type: Number,
461
+ reflect: true
409
462
  },
410
-
411
- /**
412
- * Value selected for the component.
413
- */
414
463
  value: {
415
464
  type: String,
416
- reflect: true,
417
- attribute: 'value'
465
+ reflect: true
418
466
  },
419
-
420
- /**
421
- * Indent level for submenus.
422
- * @private
423
- */
424
- level: {
425
- type: Number,
426
- reflect: false,
427
- attribute: false
428
- }
429
467
  };
430
468
  }
431
469
 
432
470
  static get styles() {
433
471
  return [
434
- styleCss$1,
435
- colorCss$1,
472
+ styleCss,
473
+ colorCss,
436
474
  tokensCss
437
475
  ];
438
476
  }
439
477
 
440
- /**
441
- * This will register this element with the browser.
442
- * @param {string} [name="auro-menu"] - The name of element that you want to register to.
443
- *
444
- * @example
445
- * AuroMenu.register("custom-menu") // this will register this element to <custom-menu/>
446
- *
447
- */
448
- static register(name = "auro-menu") {
449
- AuroLibraryRuntimeUtils.prototype.registerComponent(name, AuroMenu);
450
- }
451
-
452
- /**
453
- * Formatted value based on `multiSelect` state.
454
- * Default type is `String`, changing to `Array<String>` when `multiSelect` is true.
455
- * @private
456
- * @returns {String|Array<String>}
457
- */
458
- get formattedValue() {
459
- if (this.multiSelect) {
460
- if (!this.value) {
461
- return undefined;
462
- }
463
- if (this.value.startsWith("[")) {
464
- return JSON.parse(this.value);
465
- }
466
- return [this.value];
467
- }
468
- return this.value;
469
- }
470
-
471
- // Lifecycle Methods
472
-
473
478
  connectedCallback() {
474
479
  super.connectedCallback();
475
480
 
476
- this.addEventListener('keydown', this.handleKeyDown);
477
- this.addEventListener('mousedown', this.handleMouseSelect);
478
- this.addEventListener('auroMenuOption-mouseover', this.handleOptionHover);
479
- this.addEventListener('slotchange', this.handleSlotChange);
480
- this.setTagAttribute("auro-menu");
481
+ // Add the tag name as an attribute if it is different than the component name
482
+ // Add this step soon as this node gets attached to the DOM to avoid racing condition with menu's value setting logic.
483
+ this.runtimeUtils.handleComponentTagRename(this, 'auro-menuoption');
484
+
485
+ // Set up context consumption in connectedCallback
486
+ this._contextConsumer = new ContextConsumer(this, {
487
+ context: MenuContext,
488
+ callback: this.attachTo.bind(this),
489
+ subscribe: true
490
+ });
491
+
492
+ // Establish the key property as early as possible
493
+ const valueAttr = this.getAttribute('value');
494
+ const keyAttr = this.getAttribute('key');
495
+ this.key = keyAttr !== null ? keyAttr : valueAttr;
481
496
  }
482
497
 
483
- disconnectedCallback() {
484
- this.removeEventListener('keydown', this.handleKeyDown);
485
- this.removeEventListener('mousedown', this.handleMouseSelect);
486
- this.removeEventListener('auroMenuOption-mouseover', this.handleOptionHover);
487
- this.removeEventListener('slotchange', this.handleSlotChange);
498
+ firstUpdated() {
499
+ // Add the tag name as an attribute if it is different than the component name
500
+ this.runtimeUtils.handleComponentTagRename(this, 'auro-menuoption');
488
501
 
489
- super.disconnectedCallback();
502
+ this.setAttribute('role', 'option');
503
+ this.setAttribute('aria-selected', 'false');
504
+
505
+ this.addEventListener('mouseover', () => {
506
+ this.dispatchEvent(new CustomEvent('auroMenuOption-mouseover', {
507
+ bubbles: true,
508
+ cancelable: false,
509
+ composed: true,
510
+ detail: this
511
+ }));
512
+ });
490
513
  }
491
514
 
492
- firstUpdated() {
493
- AuroLibraryRuntimeUtils.prototype.handleComponentTagRename(this, 'auro-menu');
515
+ updated(changedProperties) {
516
+ super.updated(changedProperties);
494
517
 
495
- this.loadingSlots = this.querySelectorAll("[slot='loadingText'], [slot='loadingIcon']");
496
- this.initializeMenu();
518
+ // Update aria-selected attribute if selected changed
519
+ if (changedProperties.has('selected')) {
520
+
521
+ // Update aria-selected attribute
522
+ this.setAttribute('aria-selected', this.selected.toString());
523
+
524
+ // Update menu service selection state if this isn't an internal update
525
+ if (this.internalUpdateInProgress !== true) {
526
+ this.menuService[this.selected ? 'selectOption' : 'deselectOption'](this);
527
+ }
528
+ }
529
+
530
+ if (changedProperties.has('active')) {
531
+ this.updateActiveClasses();
532
+ }
533
+
534
+ // Update text highlight if matchWord changed
535
+ if (changedProperties.has('matchWord')) {
536
+ this.updateTextHighlight();
537
+ }
538
+
539
+ // Set the key to be the passed value if no key is provided
540
+ if (changedProperties.has('value') && this.key === undefined) {
541
+ this.key = this.value;
542
+ }
543
+ }
544
+
545
+ disconnectedCallback() {
546
+ if (this.menuService) {
547
+ this.menuService.unsubscribe(this.handleMenuChange);
548
+ this.menuService.removeMenuOption(this);
549
+ }
497
550
  }
498
551
 
499
552
  /**
500
- * Sets an attribute that matches the default tag name if the tag name is not the default.
501
- * @param {string} tagName - The tag name to set as an attribute.
502
- * @private
553
+ * Sets up event listeners for user interaction with the menu option.
554
+ * This function enables click and mouse enter events to trigger selection and highlighting logic.
503
555
  */
504
- setTagAttribute(tagName) {
505
- if (this.tagName.toLowerCase() !== tagName) {
506
- this.setAttribute(tagName, true);
556
+ bindEvents() {
557
+ this.addEventListener('click', this.handleClick.bind(this));
558
+ this.addEventListener('mouseenter', this.handleMouseEnter.bind(this));
559
+ }
560
+
561
+ /**
562
+ * Attaches this menu option to a menu service and subscribes to its events.
563
+ * This method enables the option to participate in menu selection and highlighting logic.
564
+ * @param {Object} service - The menu service instance to attach to.
565
+ */
566
+ attachTo(service) {
567
+ if (!service) {
568
+ return;
507
569
  }
570
+ this.menuService = service;
571
+ this.menuService.addMenuOption(this);
572
+ this.menuService.subscribe(this.handleMenuChange);
508
573
  }
509
574
 
510
- // eslint-disable-next-line complexity
511
- updated(changedProperties) {
512
- super.updated(changedProperties);
575
+ /**
576
+ * Handles changes from the menu service and updates the option's state.
577
+ * This function synchronizes the option's properties and selection/highlight state with menu events.
578
+ * @param {Object} event - The event object from the menu service.
579
+ */
580
+ handleMenuChange(event) {
513
581
 
514
- if (changedProperties.has('optionSelected')) {
515
- const old = changedProperties.get('optionSelected');
516
- if ((old && this.optionSelected && old.value !== this.optionSelected.value) ||
517
- (!old && this.optionSelected) ||
518
- (old && !this.optionSelected)) {
519
- this.notifySelectionChange();
520
- }
582
+ // Ignore events without a type or property
583
+ if (!event || (!event.type && !event.property)) {
584
+ return;
521
585
  }
522
586
 
523
- if (changedProperties.has('multiSelect') && !changedProperties.has("value")) {
524
- // Reset selection if multiSelect mode changes
525
- this.clearSelection();
587
+ // Update reactive properties based on event type
588
+ if (event.property && Object.keys(AuroMenuOption.properties).includes(event.property)) {
589
+ this[event.property] = event.value;
526
590
  }
527
591
 
592
+ // Handle highlight changes
593
+ if (event.type === 'highlightChange') {
594
+ const isActive = event.option === this;
595
+ this.active = isActive;
596
+ this.updateActiveClasses();
597
+ }
528
598
 
529
- if (changedProperties.has("value")) {
530
- // Handle null/undefined case
531
- if (this.value === undefined || this.value === null) {
532
- this.clearSelection();
533
- } else {
534
- if (this.multiSelect) {
535
- // In multiselect mode, this.value should be an array of strings
536
- const valueArray = this.formattedValue;
537
- const matchingOptions = this.items.filter((item) => valueArray.includes(item.value));
538
-
539
- this.optionSelected = matchingOptions.length > 0 ? matchingOptions : undefined;
540
- } else {
541
- // In single-select mode, this.value should be a string
542
- const matchingOptions = this.items.find((item) => item.value === this.value);
543
-
544
- if (matchingOptions) {
545
- this.optionSelected = matchingOptions;
546
- this.index = this.items.indexOf(matchingOptions);
547
- } else {
548
- // If no matching option found, reset selection
549
- this.optionSelected = undefined;
550
- this.index = -1;
551
- }
552
- }
599
+ if (event.type === 'stateChange') {
600
+ const isSelected = event.selectedOptions.includes(this);
601
+ this.setInternalSelected(isSelected);
602
+ }
603
+ }
553
604
 
554
- // If no matching options were found in either mode
555
- if (!this.optionSelected || (Array.isArray(this.optionSelected) && this.optionSelected.length === 0)) {
556
- dispatchMenuEvent(this, 'auroMenu-selectValueFailure');
557
- this.optionSelected = undefined;
558
- this.index = -1;
559
- }
560
- }
605
+ /**
606
+ * Updates the internal selected state of the menu option bypassing 'updated' and triggers custom events if selected.
607
+ * This function ensures the option's selection state is synchronized with menu logic and notifies listeners.
608
+ * @param {boolean} isSelected - Whether the option should be marked as selected.
609
+ */
610
+ setInternalSelected(isSelected) {
611
+ this.internalUpdateInProgress = true;
612
+ this.selected = isSelected;
561
613
 
562
- // Update UI state
563
- this.updateItemsState(new Map([
564
- [
565
- 'optionSelected',
566
- true
567
- ]
568
- ]));
569
-
570
- // Notify of changes
571
- if (this.optionSelected !== undefined) {
572
- this.notifySelectionChange();
573
- }
614
+ // Fire custom event if selected
615
+ if (isSelected) {
616
+ this.handleCustomEvent();
574
617
  }
575
618
 
576
- // Process all other UI updates
577
- this.updateItemsState(changedProperties);
619
+ setTimeout(() => {
620
+ this.internalUpdateInProgress = false;
621
+ }, 0);
622
+ }
623
+
624
+ /**
625
+ * Sets the selected state of the menu option.
626
+ * This function updates whether the option is currently selected.
627
+ * @param {boolean} isSelected - Whether the option should be marked as selected.
628
+ * @deprecated Simply modify the `selected` property directly instead.
629
+ */
630
+ setSelected(isSelected) {
631
+ this.selected = isSelected;
632
+ }
633
+
634
+ /**
635
+ * Updates the active state and visual highlighting of the menu option.
636
+ * This function toggles the option's active status and applies or removes the active CSS class.
637
+ * @param {boolean} isActive - Whether the option should be marked as active.
638
+ * @deprecated Simply modify the `active` property directly instead.
639
+ */
640
+ updateActive(isActive) {
641
+
642
+ // Set active state
643
+ this.active = isActive;
644
+ this.updateActiveClasses();
578
645
  }
579
646
 
580
647
  /**
581
- * Updates the UI state and appearance of menu items based on changed properties.
648
+ * Updates the CSS class for the menu option based on its active state.
649
+ * This function adds or removes the 'active' class to visually indicate the option's active status.
582
650
  * @private
583
- * @param {Map<string, boolean>} changedProperties - LitElement's changed properties map.
584
651
  */
585
- updateItemsState(changedProperties) {
586
- if (!this.items) {
587
- return;
588
- }
652
+ updateActiveClasses() {
653
+ // Update class based on active state
654
+ if (this.active) this.classList.add('active');
655
+ else this.classList.remove('active');
656
+ }
589
657
 
590
- // Handle noCheckmark propagation to all menus and options
591
- if (changedProperties.has('noCheckmark') && this.noCheckmark) {
592
- // Update both menus and options
593
- this.querySelectorAll('auro-menu, [auro-menu], auro-menuoption, [auro-menuoption]').forEach((element) => element.setAttribute('noCheckmark', ''));
594
- }
595
658
 
596
- // Handle layout propagation to all menus and options
597
- const propagationTargets = this.querySelectorAll('auro-menu, [auro-menu], auro-menuoption, [auro-menuoption]');
598
- [
599
- 'size',
600
- 'shape'
601
- ].forEach((prop) => {
602
- if (changedProperties.has(prop)) {
603
- propagationTargets.forEach((el) => {
604
- el.setAttribute(prop, this[prop]);
605
- });
606
- }
607
- });
659
+ /**
660
+ * Updates the visual highlighting of text within the menu option based on the current match word.
661
+ * This function highlights matching text segments and manages nested spacers for display formatting.
662
+ * @private
663
+ */
664
+ updateTextHighlight() {
608
665
 
609
666
  // Regex for matchWord if needed
610
667
  let regexWord = null;
611
668
 
612
- if (changedProperties.has('matchWord') && this.matchWord && this.matchWord.length) {
669
+ if (this.matchWord && this.matchWord.length) {
613
670
  const escapedWord = this.matchWord.replace(/[.*+?^${}()|[\]\\]/gu, '\\$&');
614
671
  regexWord = new RegExp(escapedWord, 'giu');
615
672
  }
616
673
 
617
- // Handle direct item updates
618
- this.items.forEach((option) => {
619
- // Update selection if option or value changed
620
- if (changedProperties.has('optionSelected') || changedProperties.has('value')) {
621
- const isSelected = this.isOptionSelected(option);
622
- option.setAttribute('aria-selected', isSelected ? 'true' : 'false');
623
-
624
- // Add/remove selected attribute based on state
625
- if (isSelected) {
626
- option.setAttribute('selected', '');
627
- } else {
628
- option.removeAttribute('selected');
629
- }
630
- }
631
-
632
- // Update text highlighting if matchWord changed
633
- if (changedProperties.has('matchWord') && regexWord &&
634
- isOptionInteractive(option) && !option.hasAttribute('persistent')) {
635
- const nested = option.querySelectorAll('.nestingSpacer');
636
-
637
- const displayValueEl = option.querySelector('[slot="displayValue"]');
638
- if (displayValueEl) {
639
- option.removeChild(displayValueEl);
640
- }
674
+ // Update text highlighting if matchWord changed
675
+ if (regexWord &&
676
+ this.isActive && !this.hasAttribute('persistent')) {
677
+ const nested = this.querySelectorAll('.nestingSpacer');
641
678
 
642
- // Create nested spacers
643
- const nestingSpacerBundle = [...nested].map(() => this.nestingSpacer).join('');
644
-
645
- // Update with spacers and matchWord
646
- option.innerHTML = nestingSpacerBundle +
647
- option.textContent.replace(
648
- regexWord,
649
- (match) => `<strong>${match}</strong>`
650
- );
651
- if (displayValueEl) {
652
- option.append(displayValueEl);
653
- }
679
+ const displayValueEl = this.querySelector('[slot="displayValue"]');
680
+ if (displayValueEl) {
681
+ this.removeChild(displayValueEl);
654
682
  }
655
683
 
656
- // Update disabled state
657
- if (changedProperties.has('disabled')) {
658
- option.disabled = this.disabled;
684
+ // Create nested spacers
685
+ const nestingSpacerBundle = [...nested].map(() => this.nestingSpacer).join('');
686
+
687
+ // Update with spacers and matchWord
688
+ this.innerHTML = nestingSpacerBundle +
689
+ this.textContent.replace(
690
+ regexWord,
691
+ (match) => `<strong>${match}</strong>`
692
+ );
693
+ if (displayValueEl) {
694
+ this.append(displayValueEl);
659
695
  }
660
- });
661
-
662
- // Handle loading state changes
663
- if (changedProperties.has('loading')) {
664
- this.setAttribute("aria-busy", this.loading);
665
- dispatchMenuEvent(this, "auroMenu-loadingChange", {
666
- loading: this.loading,
667
- hasLoadingPlaceholder: this.hasLoadingPlaceholder
668
- });
669
696
  }
670
697
  }
671
698
 
672
- // Init Methods
673
-
674
699
  /**
675
- * Initializes the menu's state and structure.
700
+ * Handles click events on the menu option, toggling its selected state.
701
+ * This function dispatches a click event and updates selection if the option is not disabled.
676
702
  * @private
677
703
  */
678
- initializeMenu() {
679
- this.initItems();
680
- if (this.rootMenu) {
681
- this.setAttribute('role', 'listbox');
682
- this.setAttribute('root', '');
683
- this.handleNestedMenus(this);
704
+ handleClick() {
705
+ if (!this.disabled) {
706
+ this.dispatchClickEvent();
707
+ this.selected = !this.selected;
684
708
  }
685
709
  }
686
710
 
687
711
  /**
688
- * Initializes menu items and their attributes.
712
+ * Handles mouse enter events to highlight the menu option.
713
+ * This function updates the menu service to set this option as the currently highlighted item if not disabled.
689
714
  * @private
690
715
  */
691
- initItems() {
692
- this.items = Array.from(this.querySelectorAll('auro-menuoption, [auro-menuoption]'));
693
- if (this.noCheckmark) {
694
- this.updateItemsState(new Map([
695
- [
696
- 'noCheckmark',
697
- true
698
- ]
699
- ]));
716
+ handleMouseEnter() {
717
+ if (!this.disabled) {
718
+ this.menuService.setHighlightedOption(this);
700
719
  }
701
720
  }
702
721
 
703
- // Logic Methods
704
-
705
722
  /**
706
- * Updates menu state when an option is selected.
723
+ * Dispatches custom events defined for this menu option.
724
+ * This function notifies listeners when a custom event is triggered by the option.
707
725
  * @private
708
- * @param {HTMLElement} option - The option element to select.
709
726
  */
710
- handleSelectState(option) {
711
- if (this.multiSelect) {
712
- const currentValue = this.formattedValue || [];
713
- const currentSelected = this.optionSelected || [];
714
-
715
- if (!currentValue.includes(option.value)) {
716
- this.value = JSON.stringify([
717
- ...currentValue,
718
- option.value
719
- ]);
720
- }
721
- if (!currentSelected.includes(option)) {
722
- this.optionSelected = [
723
- ...currentSelected,
724
- option
725
- ];
726
- }
727
- } else {
728
- // Single select - use arrays with single values
729
- this.value = option.value;
730
- this.optionSelected = option;
727
+ handleCustomEvent() {
728
+ if (this.event) {
729
+ dispatchMenuEvent(this, this.event, { option: this });
730
+ dispatchMenuEvent(this, 'auroMenu-customEventFired', { option: this });
731
731
  }
732
+ }
732
733
 
733
- this.index = this.items.indexOf(option);
734
+ /**
735
+ * Dispatches a click event for this menu option.
736
+ * This function notifies listeners that the option has been clicked.
737
+ * @private
738
+ */
739
+ dispatchClickEvent() {
740
+ this.dispatchEvent(new CustomEvent('auroMenuOption-click', {
741
+ bubbles: true,
742
+ cancelable: false,
743
+ composed: true,
744
+ detail: this
745
+ }));
734
746
  }
735
747
 
736
748
  /**
737
- * Deselects a menu option and updates related state.
749
+ * Generates an HTML element containing an SVG icon based on the provided `svgContent`.
750
+ *
738
751
  * @private
739
- * @param {HTMLElement} option - The menuoption to be deselected.
752
+ * @param {string} svgContent - The SVG content to be embedded.
753
+ * @returns {Element} The HTML element containing the SVG icon.
740
754
  */
741
- handleDeselectState(option) {
742
- if (this.multiSelect) {
743
- // Remove this option from array
744
- const newFormattedValue = (this.formattedValue || []).filter((val) => val !== option.value);
755
+ generateIconHtml(svgContent) {
756
+ const dom = new DOMParser().parseFromString(svgContent, 'text/html');
757
+ const svg = dom.body.firstChild;
745
758
 
746
- // If array is empty after removal, set back to undefined
747
- if (newFormattedValue && newFormattedValue.length === 0) {
748
- this.value = undefined;
749
- } else {
750
- this.value = JSON.stringify(newFormattedValue);
751
- }
759
+ svg.setAttribute('slot', 'svg');
752
760
 
753
- this.optionSelected = this.optionSelected.filter((val) => val !== option);
754
- if (this.optionSelected.length === 0) {
755
- this.optionSelected = undefined;
756
- }
757
- } else {
758
- // For single-select: Back to undefined when deselected
759
- this.value = undefined;
760
- this.optionSelected = undefined;
761
- }
761
+ return html$1`<${this.iconTag} customColor customSvg>${svg}</${this.iconTag}>`;
762
+ }
763
+
764
+ /**
765
+ * Logic to determine the layout of the component.
766
+ * @protected
767
+ * @returns {void}
768
+ */
769
+ renderLayout() {
762
770
 
763
- // Update the index tracking
764
- this.index = this.items.indexOf(option);
771
+ const fontClassMap = {
772
+ xs: 'body-sm',
773
+ sm: 'body-default',
774
+ md: 'body-default',
775
+ lg: 'body-lg',
776
+ xl: 'body-lg'
777
+ };
765
778
 
766
- // Update UI to reflect changes
767
- this.updateItemsState(new Map([
768
- [
769
- 'optionSelected',
770
- true
771
- ]
772
- ]));
779
+ const classes = classMap({
780
+ 'wrapper': true,
781
+ [this.size ? fontClassMap[this.size] : 'body-sm']: true,
782
+ });
773
783
 
774
- // Notify of selection change
775
- this.notifySelectionChange();
784
+ return html$1`
785
+ <div class="${classes}">
786
+ ${this.selected && !this.nocheckmark
787
+ ? this.generateIconHtml(checkmarkIcon.svg)
788
+ : undefined}
789
+ <slot></slot>
790
+ </div>
791
+ `;
776
792
  }
793
+ }
794
+
795
+ /* eslint-disable */
796
+
797
+ class MenuService {
777
798
 
778
799
  /**
779
- * Resets all options to their default state.
780
- * @private
800
+ * PROPERTIES AND GETTERS
781
801
  */
782
- clearSelection() {
783
- this.optionSelected = undefined;
784
- this.value = undefined;
785
- this.index = -1;
786
- }
787
802
 
788
803
  /**
789
- * Resets the menu to its initial state.
790
- * This is the only way to return value to undefined.
791
- * @public
804
+ * Gets the list of registered menu options.
805
+ * @returns {AuroMenuOption[]}
792
806
  */
793
- reset() {
794
- // Reset to undefined - initial state
795
- this.value = undefined;
796
- this.optionSelected = undefined;
797
- this.index = -1;
807
+ get menuOptions() {
808
+ return this._menuOptions;
809
+ }
798
810
 
799
- // Reset UI state
800
- this.updateItemsState(new Map([
801
- [
802
- 'optionSelected',
803
- true
804
- ]
805
- ]));
811
+ /**
812
+ * Gets the currently highlighted option.
813
+ * @returns {AuroMenuOption|null}
814
+ */
815
+ get highlightedOption() {
816
+ return this._menuOptions[this.highlightedIndex] || null;
817
+ }
806
818
 
807
- // Dispatch reset event
808
- dispatchMenuEvent(this, 'auroMenu-selectValueReset');
819
+ /**
820
+ * Gets the current value(s) of the selected option(s).
821
+ * @returns {string|string[]|undefined}
822
+ */
823
+ get currentValue() {
824
+ const values = (this.selectedOptions || []).map(option => option.value);
825
+ return this.multiSelect ? values : values[0];
809
826
  }
810
827
 
811
828
  /**
812
- * Handles nested menu structure.
813
- * @private
814
- * @param {HTMLElement} menu - Root menu element.
829
+ * Gets the string representation of the current value(s).
830
+ * For multi-select, this is a JSON stringified array.
831
+ * @returns {string|undefined}
815
832
  */
816
- handleNestedMenus(menu) {
817
- menu.level = menu.parentElement.level >= 0 ? menu.parentElement.level + 1 : 0;
833
+ get stringValue() {
834
+ const { currentValue } = this;
818
835
 
819
- if (menu.level > 0) {
820
- menu.setAttribute('role', 'group');
821
- menu.removeAttribute("root");
822
- if (!menu.hasAttribute('aria-label')) {
823
- menu.setAttribute('aria-label', 'submenu');
836
+ if (Array.isArray(currentValue)) {
837
+ if (currentValue.length > 0) {
838
+ return JSON.stringify(currentValue);
824
839
  }
840
+ return undefined;
825
841
  }
826
842
 
827
- const options = menu.querySelectorAll(':scope > auro-menuoption, :scope > [auro-menuoption]');
828
- options.forEach((option) => {
829
- const regex = new RegExp(this.nestingSpacer, "gu");
830
- option.innerHTML = this.nestingSpacer.repeat(menu.level) + option.innerHTML.replace(regex, '');
831
- });
832
- }
843
+ if (typeof currentValue === 'string') {
844
+ if (currentValue.length > 0) {
845
+ return currentValue;
846
+ }
847
+ return undefined;
848
+ }
833
849
 
834
- // Event Handlers
850
+ // Future: handle other types here (e.g., number, object, etc.)
851
+ return undefined;
852
+ }
835
853
 
836
854
  /**
837
- * Handles keyboard navigation.
838
- * @private
839
- * @param {KeyboardEvent} event - Event object from the browser.
855
+ * Gets the key(s) of the currently selected option(s).
856
+ * @returns {string|string[]|undefined}
840
857
  */
841
- handleKeyDown(event) {
842
- event.preventDefault();
843
- switch (event.key) {
844
- case "ArrowDown":
845
- this.navigateOptions('down');
846
- break;
847
- case "ArrowUp":
848
- this.navigateOptions('up');
849
- break;
850
- case "Tab":
851
- this.makeSelection();
852
- break;
853
- case "Enter":
854
- this.makeSelection();
855
- break;
856
- }
858
+ get currentKeys() {
859
+ const keys = (this.selectedOptions || []).map(option => option.key);
860
+ return this.multiSelect ? keys : keys[0];
857
861
  }
858
862
 
859
863
  /**
860
- * Makes a selection based on the current index or clicked option.
861
- * @private
864
+ * CONSTRUCTOR
862
865
  */
863
- makeSelection() {
864
- if (!this.items) {
865
- this.initItems();
866
- }
867
866
 
868
- // Get currently selected menu option based on index
869
- const option = this.items[this.index];
867
+ /**
868
+ * Creates a new MenuService instance.
869
+ * @param {Object} options - The options object.
870
+ * @param {AuroMenu} options.host - The host element that this service will control. Required.
871
+ * @throws {Error} If the host is not provided.
872
+ */
873
+ constructor({ host } = {}) {
870
874
 
871
- // Return early if option is not interactive
872
- if (!option || !isOptionInteractive(option)) {
873
- return;
875
+ // Ensure a host was passed
876
+ if (!host) {
877
+ throw new Error("MenuService requires a host element.");
874
878
  }
875
879
 
876
- // Handle custom events first
877
- if (option.hasAttribute('event')) {
878
- this.handleCustomEvent(option);
879
- return;
880
- }
880
+ // Attach the service to the host
881
+ this.host = host;
882
+ this.host.addController(this);
881
883
 
882
- if (this.multiSelect) {
883
- // In multiselect, toggle individual selections
884
- this.toggleOption(option);
885
- // In single select, only handle selection of new options
886
- } else if (this.option !== this.optionSelected || !this.isOptionSelected(option)) {
887
- this.clearSelection();
888
- this.handleSelectState(option);
889
- }
884
+ // Set default properties
885
+ this.size = undefined;
886
+ this.shape = undefined;
887
+ this.noCheckmark = undefined;
888
+ this.disabled = undefined;
889
+ this.matchWord = undefined;
890
+ this.multiSelect = undefined;
891
+ this.allowDeselect = undefined;
892
+ this.selectAllMatchingOptions = undefined;
893
+
894
+ this.highlightedIndex = -1;
890
895
 
891
- this.notifySelectionChange();
896
+ this._menuOptions = [];
897
+ this._subscribers = [];
898
+ this.internalUpdateInProgress = false;
899
+ this.selectedOptions = [];
892
900
  }
893
901
 
894
902
  /**
895
- * Toggle the selection state of the menuoption.
896
- * @private
897
- * @param {HTMLElement} option - The menuoption to toggle.
903
+ * PROPERTY SYNCING
898
904
  */
899
- toggleOption(option) {
900
- const isCurrentlySelected = this.isOptionSelected(option);
901
-
902
- if (isCurrentlySelected) {
903
- this.handleDeselectState(option);
904
- } else if (option.value === undefined || option.value === '') {
905
- dispatchMenuEvent(this, 'auroMenu-selectValueFailure');
906
- } else {
907
- this.handleSelectState(option);
908
- }
909
- }
910
905
 
911
906
  /**
912
- * Handles option selection via mouse.
913
- * @private
914
- * @param {MouseEvent} event - Event object from the browser.
907
+ * Handles host updates.
908
+ * This is a lit reactive lifecycle method.
909
+ * This comes from the Lit controller interface provided by adding this service as a controller to the host.
910
+ * See constructor for `this.host.addController(this)`
911
+ * You can read more about Lit reactive controllers here: https://lit.dev/docs/composition/controllers/
915
912
  */
916
- handleMouseSelect(event) {
917
- if (!this.rootMenu || event.target === this) {
918
- return;
919
- }
913
+ hostUpdated() {
920
914
 
921
- const option = event.target.closest('auro-menuoption, [auro-menuoption]');
922
- if (option) {
923
- this.index = this.items.indexOf(option);
924
- this.makeSelection();
915
+ // Reset selection if multiSelect mode changes
916
+ if (this.host.multiSelect !== this.multiSelect) {
917
+ this.selectedOptions = [];
925
918
  }
919
+
920
+ // Update properties on host update
921
+ this.setProperties({
922
+ size: this.host.size,
923
+ shape: this.host.shape,
924
+ noCheckmark: this.host.noCheckmark,
925
+ disabled: this.host.disabled,
926
+ matchWord: this.host.matchWord,
927
+ multiSelect: this.host.multiSelect,
928
+ allowDeselect: this.host.allowDeselect,
929
+ selectAllMatchingOptions: this.host.selectAllMatchingOptions
930
+ });
926
931
  }
927
932
 
928
933
  /**
929
- * Handles option hover events.
930
- * @private
931
- * @param {CustomEvent} event - Event object from the browser.
934
+ * Handles host disconnection and memory cleanup.
932
935
  */
933
- handleOptionHover(event) {
934
- const option = event.target;
935
- this.index = this.items.indexOf(option);
936
- this.updateActiveOption(this.index);
936
+ hostDisconnected() {
937
+ this._subscribers = [];
938
+ this._menuOptions = [];
937
939
  }
938
940
 
939
941
  /**
940
- * Handles slot change events.
941
- * @private
942
+ * Sets a property value if it exists on the instance and the value has changed.
943
+ * @param {string} property
944
+ * @param {any} value
942
945
  */
943
- handleSlotChange() {
944
- if (this.parentElement && this.parentElement.closest('auro-menu, [auro-menu]')) {
945
- this.rootMenu = false;
946
- }
946
+ setProperty(property, value) {
947
947
 
948
- if (this.rootMenu) {
949
- this.initializeMenu();
950
- } else if (this.noCheckmark) {
951
- this.updateItemsState(new Map([
952
- [
953
- 'noCheckmark',
954
- true
955
- ]
956
- ]));
948
+ // Only update if we are tracking the property in this service
949
+ if (this.hasOwnProperty(property)) {
950
+
951
+ // Check if the value has changed
952
+ const valueChanged = this[property] !== value;
953
+
954
+ // Update and notify if changed
955
+ if (valueChanged) {
956
+ this[property] = value;
957
+ this.notify({ property, value });
958
+ }
957
959
  }
958
960
  }
959
961
 
960
962
  /**
961
- * Navigates through options using keyboard.
962
- * @private
963
- * @param {string} direction - 'up' or 'down'.
963
+ * Sets multiple properties on the instance.
964
+ * @param {Object} properties - Key-value pairs of properties to set.
964
965
  */
965
- navigateOptions(direction) {
966
- // Return early if no items exist
967
- if (!this.items || !this.items.length) {
968
- return;
966
+ setProperties(properties) {
967
+ for (const [key, value] of Object.entries(properties)) {
968
+ this.setProperty(key, value);
969
969
  }
970
+ }
970
971
 
971
- let newIndex = this.index;
972
- const increment = direction === 'down' ? 1 : -1;
973
- const maxIterations = this.items.length;
974
- let iterations = 0;
975
- let foundInteractiveOption = false;
976
-
977
- do {
978
- newIndex = (newIndex + increment + this.items.length) % this.items.length;
979
- iterations += 1;
972
+ /**
973
+ * MENU OPTION HIGHLIGHTING
974
+ */
975
+
976
+ /**
977
+ * Highlights the next active option in the menu.
978
+ */
979
+ highlightNext() {
980
+ this.moveHighlightedOption("next");
981
+ }
982
+
983
+ /**
984
+ * Highlights the previous active option in the menu.
985
+ */
986
+ highlightPrevious() {
987
+ this.moveHighlightedOption("previous");
988
+ }
989
+
990
+ /**
991
+ * Moves the highlighted option in the specified direction.
992
+ * @param {string} direction - The direction to move the highlight ("next" or "previous").
993
+ */
994
+ moveHighlightedOption(direction) {
995
+
996
+ // Get the active options
997
+ const activeOptions = this._menuOptions.filter(option => option.isActive);
998
+
999
+ // Get the currently active option
1000
+ const currentActiveOption = activeOptions[activeOptions.indexOf(this.highlightedOption)];
1001
+
1002
+ // Determine the new index based on the currently active option and direction
1003
+ let newIndex = currentActiveOption
1004
+ ? direction === "previous"
1005
+ ? activeOptions.indexOf(currentActiveOption) - 1
1006
+ : activeOptions.indexOf(currentActiveOption) + 1
1007
+ : direction === "previous"
1008
+ ? activeOptions.length - 1
1009
+ : 0;
1010
+
1011
+ // Wrap around the index if needed
1012
+ newIndex = newIndex < 0 ? activeOptions.length - 1 : newIndex >= activeOptions.length ? 0 : newIndex;
1013
+
1014
+ // Get the new active option and set it as highlighted
1015
+ const newActiveOption = activeOptions[newIndex];
1016
+ this.setHighlightedOption(newActiveOption);
1017
+ }
1018
+
1019
+ /**
1020
+ * Sets the highlighted index to the specified option.
1021
+ * @param {AuroMenuOption} option - The option to highlight.
1022
+ */
1023
+ setHighlightedOption(option) {
1024
+
1025
+ if (!option) return;
1026
+
1027
+ // Get the index of the option to highlight
1028
+ const index = this._menuOptions.indexOf(option);
1029
+
1030
+ // Update highlighted index
1031
+ this.highlightedIndex = index;
1032
+
1033
+ // Notify subscribers of highlight change
1034
+ this.notify({ type: 'highlightChange', option, index: this.highlightedIndex });
1035
+
1036
+ // Dispatch the change event
1037
+ this.dispatchChangeEvent('auroMenu-activatedOption', option);
1038
+ }
1039
+
1040
+ /**
1041
+ * Sets the highlighted option to the option at the specified index if it exists.
1042
+ * @param {number} index
1043
+ */
1044
+ setHighlightedIndex(index) {
1045
+ const option = this._menuOptions[index] || null;
1046
+ this.setHighlightedOption(option);
1047
+ }
1048
+
1049
+ /**
1050
+ * Selects the currently highlighted option.
1051
+ */
1052
+ selectHighlightedOption() {
1053
+ if (this.highlightedOption) {
1054
+ this.toggleOption(this.highlightedOption);
1055
+ }
1056
+ }
1057
+
1058
+ /**
1059
+ * SELECTION AND DESELECTION METHODS
1060
+ */
1061
+
1062
+ /**
1063
+ * Selects one or more options in a batch operation
1064
+ * @param {AuroMenuOption|AuroMenuOption[]} options - Single option or array of options to select
1065
+ */
1066
+ selectOptions(options) {
1067
+ let optionsToSelect = Array.isArray(options) ? options : [options];
1068
+
1069
+ // Filter out options that are inactive
1070
+ optionsToSelect = optionsToSelect.filter(option => option.isActive);
1071
+
1072
+ if (!optionsToSelect.length) return;
1073
+
1074
+ if (this.multiSelect) {
1075
+ this.selectedOptions = [...(this.selectedOptions || []), ...optionsToSelect];
1076
+ } else {
1077
+ // In single select mode, only take the last option
1078
+ this.selectedOptions = [optionsToSelect[optionsToSelect.length - 1]];
1079
+ }
1080
+
1081
+ this.stageUpdate();
1082
+ }
1083
+
1084
+ /**
1085
+ * Deselects one or more options in a batch operation
1086
+ * @param {AuroMenuOption|AuroMenuOption[]} options - Single option or array of options to deselect
1087
+ */
1088
+ deselectOptions(options) {
1089
+ const optionsToDeselect = Array.isArray(options) ? options : [options];
1090
+
1091
+ if (!optionsToDeselect.length) return;
1092
+
1093
+ // Check if deselection should be prevented
1094
+ const shouldPreventDeselect = !this.allowDeselect && !this.multiSelect;
1095
+ const isOnlySelectedOption = this.selectedOptions.length === 1 && optionsToDeselect.includes(this.selectedOptions[0]);
1096
+
1097
+ // Prevent deselecting the only selected option if not allowed
1098
+ if (shouldPreventDeselect && isOnlySelectedOption) return;
1099
+
1100
+ const optionsSet = new Set(optionsToDeselect);
1101
+ this.selectedOptions = (this.selectedOptions || [])
1102
+ .filter(opt => !optionsSet.has(opt));
1103
+
1104
+ this.stageUpdate();
1105
+ }
1106
+
1107
+ /**
1108
+ * Selects a single option.
1109
+ * @param {AuroMenuOption} option
1110
+ */
1111
+ selectOption(option) {
1112
+ this.selectOptions(option);
1113
+ }
1114
+
1115
+ /**
1116
+ * Deselects a single option.
1117
+ * @param {AuroMenuOption} option
1118
+ */
1119
+ deselectOption(option) {
1120
+ this.deselectOptions(option);
1121
+ }
1122
+
1123
+ /**
1124
+ * Toggles the selection state of a single option.
1125
+ * @param {AuroMenuOption} option
1126
+ */
1127
+ toggleOption(option) {
1128
+ if (option.selected) {
1129
+ this.deselectOption(option);
1130
+ } else {
1131
+ this.selectOption(option);
1132
+ }
1133
+ }
1134
+
1135
+ /**
1136
+ * Selects options based on their value(s) when compared to a passed value or values.
1137
+ * Value or values are normalized to an array of strings that can be matched to option keys.
1138
+ * @param {string|number|Array<string|number>} value - The value(s) to select.
1139
+ */
1140
+ selectByValue(value) {
1141
+ // Early exit for invalid/empty values or internal updates
1142
+ if (this.internalUpdateInProgress ||
1143
+ this.host.internalUpdateInProgress ||
1144
+ value === undefined ||
1145
+ value === null ||
1146
+ (Array.isArray(value) && value.length === 0) ||
1147
+ (typeof value === 'string' && value.trim() === '')) {
1148
+ return;
1149
+ }
1150
+
1151
+ this.reset();
1152
+
1153
+ // Normalize values to array of strings
1154
+ const normalizedValues = this._getNormalizedValues(value);
1155
+
1156
+ // Validate for single-select mode
1157
+ let validatedValues = normalizedValues;
1158
+ if (normalizedValues.length > 1 && !this.multiSelect) {
1159
+ console.warn("MenuService - Multiple values provided for single-select menu. Only the first value will be selected.");
1160
+ validatedValues = [normalizedValues[0]];
1161
+ }
1162
+
1163
+ // Find matching options by comparing available options to validated values
1164
+ const trackedKeys = new Set();
1165
+ const optionsToSelect = this._menuOptions.filter(option => {
1166
+ const passesFilter = validatedValues.includes(option.key);
1167
+ const alreadyTracked = trackedKeys.has(option.key);
1168
+
1169
+ trackedKeys.add(option.key);
1170
+
1171
+ // Include the option in the options to be selected if it passes the filter check and
1172
+ // either hasn't been tracked yet or selectAllMatchingOptions is true
1173
+ return passesFilter && (!alreadyTracked || (alreadyTracked && this.selectAllMatchingOptions));
1174
+ });
1175
+
1176
+ // Handle selection result
1177
+ if (optionsToSelect.length && !this.optionsArraysMatch(optionsToSelect, this.selectedOptions)) {
1178
+ this.selectOptions(optionsToSelect);
1179
+ } else {
1180
+ this.stageUpdate();
1181
+ }
1182
+
1183
+ // Dispatch failure event if no matches found
1184
+ if (!optionsToSelect.length && validatedValues.length) {
1185
+ this.dispatchChangeEvent('auroMenu-selectValueFailure', {
1186
+ message: 'No matching options found for the provided value(s).',
1187
+ values: validatedValues
1188
+ });
1189
+ }
1190
+ }
1191
+
1192
+ /**
1193
+ * Resets the selected options to an empty array.
1194
+ */
1195
+ reset() {
1196
+ const previousOptions = [...this.selectedOptions];
1197
+ this.selectedOptions = [];
1198
+
1199
+ // Single update after clearing all
1200
+ if (previousOptions.length) {
1201
+ this.stageUpdate();
1202
+ }
1203
+ }
1204
+
1205
+ /**
1206
+ * SUBSCRIPTION, NOTIFICATION AND EVENT DISPATCH METHODS
1207
+ */
1208
+
1209
+ /**
1210
+ * Subscribes a callback to menu service events.
1211
+ * @param {Function} callback - The callback to invoke on events.
1212
+ */
1213
+ subscribe(callback) {
1214
+ this._subscribers.push(callback);
1215
+ }
1216
+
1217
+ /**
1218
+ * Remove a previously subscribed callback from menu service events.
1219
+ * @param {Function} callback
1220
+ */
1221
+ unsubscribe(callback) {
1222
+ this._subscribers = this._subscribers.filter(cb => cb !== callback);
1223
+ }
1224
+
1225
+ /**
1226
+ * Stages an update to notify subscribers of state and value changes.
1227
+ */
1228
+ stageUpdate() {
1229
+ this.notifyStateChange();
1230
+ this.notifyValueChange();
1231
+ }
1232
+
1233
+ /**
1234
+ * Notifies subscribers of a menu service event.
1235
+ * All notifications are sent to all subscribers.
1236
+ * @param {string} event - The event to send to subscribers.
1237
+ */
1238
+ notify(event) {
1239
+ this._subscribers.forEach(callback => callback(event));
1240
+ }
1241
+
1242
+ /**
1243
+ * Notifies subscribers of a state change (selected options has changed).
1244
+ */
1245
+ notifyStateChange() {
1246
+ this.notify({ type: 'stateChange', selectedOptions: this.selectedOptions });
1247
+ }
1248
+
1249
+ /**
1250
+ * Notifies subscribers of a value change (current value has changed).
1251
+ */
1252
+ notifyValueChange() {
1253
+
1254
+ // Prepare details for the event
1255
+ const details = {
1256
+ value: this.currentValue,
1257
+ stringValue: this.stringValue,
1258
+ keys: this.currentKeys,
1259
+ options: this.selectedOptions
1260
+ };
1261
+
1262
+ // If only one option is selected, include its index
1263
+ if (this.selectedOptions.length === 1) details.index = this._menuOptions.indexOf(this.selectedOptions[0]);
1264
+
1265
+ this.notify({
1266
+ type: 'valueChange',
1267
+ ...details
1268
+ });
1269
+
1270
+ this.dispatchChangeEvent('auroMenu-selectedOption', details);
1271
+ }
1272
+
1273
+ /**
1274
+ * Dispatches a custom event from the host element.
1275
+ * @param {string} eventName
1276
+ * @param {any} detail
1277
+ */
1278
+ dispatchChangeEvent(eventName, detail) {
1279
+ this.host.dispatchEvent(new CustomEvent(eventName, {
1280
+ bubbles: true,
1281
+ cancelable: false,
1282
+ composed: true,
1283
+ detail
1284
+ }));
1285
+ }
1286
+
1287
+ /**
1288
+ * MENU OPTION MANAGEMENT METHODS
1289
+ */
1290
+
1291
+ /**
1292
+ * Adds a menu option to the service's list.
1293
+ * @param {AuroMenuOption} option - the option to track
1294
+ */
1295
+ addMenuOption(option) {
1296
+ this._menuOptions.push(option);
1297
+ this.notify({ type: 'optionsChange', options: this._menuOptions });
1298
+ }
1299
+
1300
+ /**
1301
+ * Removes a menu option from the service's list.
1302
+ * @param {AuroMenuOption} option - the option to remove
1303
+ */
1304
+ removeMenuOption(option) {
1305
+ this._menuOptions = this._menuOptions.filter(opt => opt !== option);
1306
+ this.notify({ type: 'optionsChange', options: this._menuOptions });
1307
+ }
1308
+
1309
+ /**
1310
+ * UTILITIES
1311
+ */
1312
+
1313
+ /**
1314
+ * Normalizes a value or array of values into an array of strings for option selection.
1315
+ * This function ensures that input values are consistently formatted for matching menu options.
1316
+ *
1317
+ * @param {string|number|Array<string|number>} value - The value(s) to normalize.
1318
+ * @returns {Array<string>} An array of string values suitable for option matching.
1319
+ * @throws {Error} If any value is not a string or number.
1320
+ */
1321
+ _getNormalizedValues(value) {
1322
+ let values = value;
1323
+
1324
+ // Handle JSON string and single value string input
1325
+ if (!Array.isArray(values) && typeof values === 'string') {
1326
+
1327
+ // Attempt to parse as JSON array
1328
+ try {
1329
+
1330
+ // Normalize single quotes to double quotes for JSON parsing
1331
+ // This will not handle complex cases but will cover basic usage
1332
+ const parseValue = values.replace(/'([^']*?)'/g, '"$1"');
1333
+
1334
+ // Attempt parse
1335
+ const parsed = JSON.parse(parseValue);
1336
+
1337
+ // Ensure parsed value is an array
1338
+ if (!Array.isArray(parsed)) throw new Error('Not an array');
1339
+
1340
+ // Set values to parsed array
1341
+ values = parsed;
1342
+ } catch (err) {
1343
+
1344
+ // If parsing fails, treat as single value
1345
+ values = [value];
1346
+ }
1347
+ }
1348
+
1349
+ // Handle a single number being passed
1350
+ if (typeof values === 'number') {
1351
+ values = [String(values)];
1352
+ }
1353
+
1354
+ // Coerce each value to string and validate types
1355
+ values.forEach((val, index) => {
1356
+
1357
+ // Throw an error for invalid value types
1358
+ if (typeof val !== 'string' && typeof val !== 'number') {
1359
+ throw new Error('Value contains invalid value type. Supported types are string and number.');
1360
+ }
1361
+
1362
+ // Convert numbers to strings for consistency
1363
+ if (typeof val === 'number') {
1364
+ values[index] = String(val);
1365
+ }
1366
+ });
1367
+
1368
+ // Return the resulting array of string values
1369
+ return values;
1370
+ }
1371
+
1372
+ /**
1373
+ * Returns whether two arrays of options contain the same elements.
1374
+ * @param {AuroMenuOption[]} arr1 - First array of options.
1375
+ * @param {AuroMenuOption[]} arr2 - Second array of options.
1376
+ * @returns {boolean} True if arrays match, false otherwise.
1377
+ */
1378
+ optionsArraysMatch(arr1, arr2) {
1379
+ if (arr1.length !== arr2.length) return false;
1380
+
1381
+ const set1 = new Set(arr1);
1382
+ const set2 = new Set(arr2);
1383
+
1384
+ for (let item of set1) {
1385
+ if (!set2.has(item)) {
1386
+ return false;
1387
+ }
1388
+ }
1389
+
1390
+ return true;
1391
+ }
1392
+ }
1393
+
1394
+ const MenuContext = createContext('menu-context');
1395
+
1396
+ /* eslint-disable no-underscore-dangle, curly */
1397
+ // Copyright (c) 2025 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
1398
+ // See LICENSE in the project root for license information.
1399
+
1400
+
1401
+
1402
+ /**
1403
+ * The auro-menu element provides users a way to select from a list of options.
1404
+ * @attr {HTMLElement|Array<HTMLElement>} optionSelected - An array of currently selected menu options, type `HTMLElement` by default. In multi-select mode, `optionSelected` is an array of HTML elements.
1405
+ * @attr {object} optionactive - Specifies the current active menuOption.
1406
+ * @attr {string} matchword - Specifies a string used to highlight matched string parts in options.
1407
+ * @attr {boolean} disabled - When true, the entire menu and all options are disabled;
1408
+ * @attr {boolean} nocheckmark - When true, selected option will not show the checkmark.
1409
+ * @attr {boolean} loading - When true, displays a loading state using the loadingIcon and loadingText slots if provided.
1410
+ * @attr {boolean} multiselect - When true, the selected option can be multiple options.
1411
+ * @attr {boolean} selectAllMatchingOptions - When true, selects all options that match the provided value/key when setting value and multiselect is enabled.
1412
+ * @attr {string} value - The value of the selected option. In multi-select mode, this is a JSON stringified array of selected option values.
1413
+ * @prop {string} size - Sets the size of the menu. Accepted values are 'sm' and 'md'. Default is 'sm'.
1414
+ * @prop {string} shape - Sets the shape of the menu options. Accepted values are 'box' and 'round'. Default is 'box'.
1415
+ * @prop {boolean} hasLoadingPlaceholder - Indicates whether the menu has a loadingIcon or loadingText to render when in a loading state.
1416
+ * @event {CustomEvent<Element>} auroMenu-activatedOption - Notifies that a menuoption has been made `active`.
1417
+ * @event {CustomEvent<any>} auroMenu-customEventFired - Notifies that a custom event has been fired.
1418
+ * @event {CustomEvent<{ loading: boolean; hasLoadingPlaceholder: boolean; }>} auroMenu-loadingChange - Notifies when the loading attribute is changed.
1419
+ * @event {CustomEvent<any>} auroMenu-selectValueFailure - Notifies that an attempt to select a menuoption by matching a value has failed.
1420
+ * @event {CustomEvent<any>} auroMenu-selectValueReset - Notifies that the component value has been reset.
1421
+ * @event {CustomEvent<any>} auroMenu-selectedOption - Notifies that a new menuoption selection has been made.
1422
+ * @slot loadingText - Text to show while loading attribute is set
1423
+ * @slot loadingIcon - Icon to show while loading attribute is set
1424
+ * @slot - Slot for insertion of menu options.
1425
+ */
1426
+
1427
+ /* eslint-disable no-magic-numbers, max-lines, no-extra-parens */
1428
+
1429
+ class AuroMenu extends AuroElement {
1430
+
1431
+ constructor() {
1432
+ super();
1433
+
1434
+ // State properties (reactive)
1435
+
1436
+ /**
1437
+ * @private
1438
+ */
1439
+ this.shape = "box";
1440
+
1441
+ /**
1442
+ * @private
1443
+ */
1444
+ this.size = "sm";
1445
+
1446
+ // Value of the selected options
1447
+ this.value = undefined;
1448
+ // Currently selected option
1449
+ this.optionSelected = undefined;
1450
+ // String used for highlighting/filtering
1451
+ this.matchWord = undefined;
1452
+ // Hide the checkmark icon on selected options
1453
+ this.noCheckmark = false;
1454
+ // Currently active option
1455
+ this.optionActive = undefined;
1456
+ // Loading state
1457
+ this.loading = false;
1458
+ // Multi-select mode
1459
+ this.multiSelect = false;
1460
+ // Allow deselecting of menu options
1461
+ this.allowDeselect = false;
1462
+ // Select all matching options when setting value in multi-select mode
1463
+ this.selectAllMatchingOptions = false;
1464
+
1465
+ // Event Bindings
1466
+
1467
+ /**
1468
+ * @private
1469
+ */
1470
+ this.handleKeyDown = this.handleKeyDown.bind(this);
1471
+
1472
+
1473
+ /**
1474
+ * @private
1475
+ */
1476
+ this.handleSlotChange = this.handleSlotChange.bind(this);
1477
+
1478
+ // Instance properties (non-reactive)
1479
+
1480
+ /**
1481
+ * @private
1482
+ */
1483
+ Object.assign(this, {
1484
+ // Root-level menu (true) or a nested submenu (false)
1485
+ rootMenu: true,
1486
+ // Currently focused/active menu item index
1487
+ _index: -1,
1488
+ // Nested menu spacer
1489
+ nestingSpacer: '<span class="nestingSpacer"></span>',
1490
+ // Loading indicator for slot elements
1491
+ loadingSlots: null,
1492
+ });
1493
+ }
1494
+
1495
+ static get properties() {
1496
+ return {
1497
+ ...super.properties,
1498
+
1499
+ /**
1500
+ * Allows deselecting an already selected option when clicked again in single-select mode.
1501
+ */
1502
+ allowDeselect: {
1503
+ type: Boolean,
1504
+ reflect: true,
1505
+ },
1506
+ noCheckmark: {
1507
+ type: Boolean,
1508
+ reflect: true,
1509
+ attribute: 'nocheckmark'
1510
+ },
1511
+ disabled: {
1512
+ type: Boolean,
1513
+ reflect: true
1514
+ },
1515
+ loading: {
1516
+ type: Boolean,
1517
+ reflect: true
1518
+ },
1519
+ optionSelected: {
1520
+ // Allow HTMLElement, HTMLElement[] arrays and undefined
1521
+ type: Object
1522
+ },
1523
+ optionActive: {
1524
+ type: Object,
1525
+ attribute: 'optionactive'
1526
+ },
1527
+ matchWord: {
1528
+ type: String,
1529
+ attribute: 'matchword'
1530
+ },
1531
+ multiSelect: {
1532
+ type: Boolean,
1533
+ reflect: true,
1534
+ attribute: 'multiselect'
1535
+ },
1536
+ selectAllMatchingOptions: {
1537
+ type: Boolean,
1538
+ reflect: true,
1539
+ },
980
1540
 
981
- // Check if current option is interactive
982
- const currentOption = this.items[newIndex];
983
- if (isOptionInteractive(currentOption)) {
984
- foundInteractiveOption = true;
985
- break;
986
- }
1541
+ /**
1542
+ * Value selected for the component.
1543
+ */
1544
+ value: {
1545
+ type: String,
1546
+ reflect: true,
1547
+ attribute: 'value'
1548
+ },
987
1549
 
988
- // Break if all options were checked
989
- if (iterations >= maxIterations) {
990
- break;
1550
+ /**
1551
+ * Indent level for submenus.
1552
+ * @private
1553
+ */
1554
+ level: {
1555
+ type: Number,
1556
+ reflect: false,
1557
+ attribute: false
1558
+ },
1559
+
1560
+ /**
1561
+ * Available menu options
1562
+ * @readonly
1563
+ */
1564
+ options: {
1565
+ type: Array,
1566
+ reflect: false,
1567
+ attribute: false
991
1568
  }
992
- } while (iterations < maxIterations);
1569
+ };
1570
+ }
993
1571
 
994
- // Handle the results of the search
995
- if (foundInteractiveOption) {
996
- // Update only if an interactive option was found
997
- this.index = newIndex;
998
- this.updateActiveOption(this.index);
999
- } else {
1000
- // All options are disabled or non-interactive
1001
- // Keep the current index unchanged
1002
- dispatchMenuEvent(this, 'auroMenu-navigateFailure', {
1003
- reason: 'No interactive options available',
1004
- direction,
1005
- currentIndex: this.index
1572
+ static get styles() {
1573
+ return [
1574
+ styleCss$1,
1575
+ colorCss$1,
1576
+ tokensCss
1577
+ ];
1578
+ }
1579
+
1580
+ /**
1581
+ * @readonly
1582
+ * @returns {Array<HTMLElement>} - Returns the array of available menu options.
1583
+ * @deprecated use `options` property instead.
1584
+ */
1585
+ get items() {
1586
+ return this.options;
1587
+ }
1588
+
1589
+ /**
1590
+ * @returns {number} - Returns the index of the currently active option.
1591
+ */
1592
+ get index() {
1593
+ return this._index;
1594
+ }
1595
+
1596
+ /**
1597
+ * @param {number} value - Sets the index of the currently active option.
1598
+ */
1599
+ set index(value) {
1600
+ this.menuService.setHighlightedIndex(value);
1601
+ }
1602
+
1603
+ /**
1604
+ * This will register this element with the browser.
1605
+ * @param {string} [name="auro-menu"] - The name of element that you want to register to.
1606
+ *
1607
+ * @example
1608
+ * AuroMenu.register("custom-menu") // this will register this element to <custom-menu/>
1609
+ *
1610
+ */
1611
+ static register(name = "auro-menu") {
1612
+ AuroLibraryRuntimeUtils.prototype.registerComponent(name, AuroMenu);
1613
+ }
1614
+
1615
+ /**
1616
+ * Formatted value based on `multiSelect` state.
1617
+ * Default type is `String`, changing to `Array<String>` when `multiSelect` is true.
1618
+ * @private
1619
+ * @returns {String|Array<String>}
1620
+ */
1621
+ get formattedValue() {
1622
+ return this.menuService.currentValue;
1623
+ }
1624
+
1625
+ /**
1626
+ * Gets the current property values for the menu service.
1627
+ * @private
1628
+ * @returns {Object}
1629
+ */
1630
+ get propertyValues() {
1631
+ return {
1632
+ size: this.size,
1633
+ shape: this.shape,
1634
+ noCheckmark: this.nocheckmark,
1635
+ disabled: this.disabled
1636
+ };
1637
+ }
1638
+
1639
+ /**
1640
+ * Provides the menu context to child components.
1641
+ * Initializes the MenuService and subscribes to menu changes.
1642
+ * @protected
1643
+ */
1644
+ provideContext() {
1645
+ this.menuService = new MenuService({host: this});
1646
+ this.menuService.setProperties(this.propertyValues);
1647
+ this.menuService.subscribe(this.handleMenuChange.bind(this));
1648
+ this._contextProvider = new ContextProvider(this, {
1649
+ context: MenuContext,
1650
+ initialValue: this.menuService
1651
+ });
1652
+ }
1653
+
1654
+ /**
1655
+ * Updates the currently active option in the menu.
1656
+ * @param {HTMLElement} option - The option to set as active.
1657
+ */
1658
+ updateActiveOption(option) {
1659
+ this.menuService.setHighlightedOption(option);
1660
+ }
1661
+
1662
+ /**
1663
+ * Sets the internal value and manages update state.
1664
+ * @param {String|Array<String>} value - The value to set.
1665
+ * @protected
1666
+ */
1667
+ setInternalValue(value) {
1668
+ if (this.value !== value) {
1669
+ this.internalUpdateInProgress = true;
1670
+ this.value = value;
1671
+
1672
+ setTimeout(() => {
1673
+ this.internalUpdateInProgress = false;
1006
1674
  });
1007
1675
  }
1008
1676
  }
1009
1677
 
1010
1678
  /**
1011
- * Updates the active option state and dispatches events.
1012
- * @param {number} index - Index of the option to make active.
1679
+ * Handles changes from the menu service and updates component state.
1680
+ * @param {Object} event - The event object from the menu service.
1681
+ * @protected
1682
+ */
1683
+ handleMenuChange(event) {
1684
+ if (event.type === 'valueChange') {
1685
+
1686
+ // New option is array value or first option with fallback to undefined for empty array in all cases
1687
+ const newOption = this.multiSelect && event.options.length ? event.options : event.options[0] || undefined;
1688
+ const newValue = event.stringValue;
1689
+
1690
+ // Check if the option or value has actually changed
1691
+ if (newValue === undefined || (this.optionSelected !== newOption || this.stringValue !== newValue)) {
1692
+ this.optionSelected = newOption;
1693
+ this.setInternalValue(newValue);
1694
+ }
1695
+
1696
+ // Notify components of selection change
1697
+ this.notifySelectionChange(event);
1698
+ }
1699
+
1700
+ if (event.type === 'highlightChange') {
1701
+ this.optionActive = event.option;
1702
+ this._index = event.index;
1703
+ }
1704
+
1705
+ if (event.type === 'optionsChange') {
1706
+ this.options = event.options;
1707
+ this.dispatchEvent(new CustomEvent('auroMenu-optionsChange', {
1708
+ detail: {
1709
+ options: event.options
1710
+ }
1711
+ }));
1712
+ }
1713
+ }
1714
+
1715
+ /**
1716
+ * Gets the currently selected options.
1717
+ * @returns {Array<HTMLElement>}
1718
+ */
1719
+ get selectedOptions() {
1720
+ return this.menuService ? this.menuService.selectedOptions : [];
1721
+ }
1722
+
1723
+ /**
1724
+ * Gets the first selected option, or null if none.
1725
+ * @returns {HTMLElement|null}
1726
+ */
1727
+ get selectedOption() {
1728
+ return this.menuService ? this.menuService.selectedOptions[0] : null;
1729
+ }
1730
+
1731
+ // Lifecycle Methods
1732
+
1733
+ connectedCallback() {
1734
+ super.connectedCallback();
1735
+
1736
+ this.provideContext();
1737
+
1738
+ this.addEventListener('keydown', this.handleKeyDown);
1739
+ this.addEventListener('auroMenuOption-click', this.handleMouseSelect);
1740
+ this.addEventListener('auroMenuOption-mouseover', this.handleOptionHover);
1741
+ this.addEventListener('slotchange', this.handleSlotChange);
1742
+ this.setTagAttribute("auro-menu");
1743
+ }
1744
+
1745
+ disconnectedCallback() {
1746
+ this.removeEventListener('keydown', this.handleKeyDown);
1747
+ this.removeEventListener('auroMenuOption-click', this.handleMouseSelect);
1748
+ this.removeEventListener('auroMenuOption-mouseover', this.handleOptionHover);
1749
+ this.removeEventListener('slotchange', this.handleSlotChange);
1750
+
1751
+ super.disconnectedCallback();
1752
+ }
1753
+
1754
+ firstUpdated() {
1755
+ AuroLibraryRuntimeUtils.prototype.handleComponentTagRename(this, 'auro-menu');
1756
+
1757
+ this.loadingSlots = this.querySelectorAll("[slot='loadingText'], [slot='loadingIcon']");
1758
+ this.initializeMenu();
1759
+ }
1760
+
1761
+
1762
+ updated(changedProperties) {
1763
+ super.updated(changedProperties);
1764
+
1765
+ // Update menu service properties on host update
1766
+ if (changedProperties.has('value')) {
1767
+ this.menuService.selectByValue(this.value);
1768
+ }
1769
+
1770
+ // Handle loading state changes
1771
+ if (changedProperties.has('loading')) {
1772
+ this.setLoadingState(this.loading);
1773
+ }
1774
+ }
1775
+
1776
+ /**
1777
+ * Sets an attribute that matches the default tag name if the tag name is not the default.
1778
+ * @param {string} tagName - The tag name to set as an attribute.
1779
+ * @private
1780
+ */
1781
+ setTagAttribute(tagName) {
1782
+ if (this.tagName.toLowerCase() !== tagName) {
1783
+ this.setAttribute(tagName, true);
1784
+ }
1785
+ }
1786
+
1787
+ /**
1788
+ * Sets the loading state and dispatches a loading change event.
1789
+ * @param {boolean} isLoading - Whether the menu is loading.
1790
+ * @protected
1791
+ */
1792
+ setLoadingState(isLoading) {
1793
+ this.setAttribute("aria-busy", isLoading);
1794
+ dispatchMenuEvent(this, "auroMenu-loadingChange", {
1795
+ loading: isLoading,
1796
+ hasLoadingPlaceholder: this.hasLoadingPlaceholder
1797
+ });
1798
+ }
1799
+
1800
+ // Init Methods
1801
+
1802
+ /**
1803
+ * Initializes the menu's state and structure.
1804
+ * @private
1805
+ */
1806
+ initializeMenu() {
1807
+ if (this.rootMenu) {
1808
+ this.setAttribute('role', 'listbox');
1809
+ this.setAttribute('root', '');
1810
+ this.handleNestedMenus(this);
1811
+ }
1812
+ }
1813
+
1814
+ /**
1815
+ * Selects the currently highlighted option.
1816
+ * @protected
1817
+ */
1818
+ makeSelection() {
1819
+ this.menuService.selectHighlightedOption();
1820
+ }
1821
+
1822
+ /**
1823
+ * Resets all options to their default state.
1824
+ * @private
1825
+ */
1826
+ clearSelection() {
1827
+ this.optionSelected = undefined;
1828
+ this.value = undefined;
1829
+ this._index = -1;
1830
+ }
1831
+
1832
+ /**
1833
+ * Resets the menu to its initial state.
1834
+ * This is the only way to return value to undefined.
1835
+ * @public
1836
+ */
1837
+ reset() {
1838
+ this.menuService.reset();
1839
+
1840
+ // Dispatch reset event
1841
+ dispatchMenuEvent(this, 'auroMenu-selectValueReset');
1842
+ }
1843
+
1844
+ /**
1845
+ * Handles nested menu structure.
1846
+ * @private
1847
+ * @param {HTMLElement} menu - Root menu element.
1848
+ */
1849
+ handleNestedMenus(menu) {
1850
+ menu.level = menu.parentElement.level >= 0 ? menu.parentElement.level + 1 : 0;
1851
+
1852
+ if (menu.level > 0) {
1853
+ menu.setAttribute('role', 'group');
1854
+ menu.removeAttribute("root");
1855
+ if (!menu.hasAttribute('aria-label')) {
1856
+ menu.setAttribute('aria-label', 'submenu');
1857
+ }
1858
+ }
1859
+
1860
+ const options = menu.querySelectorAll(':scope > auro-menuoption, :scope > [auro-menuoption]');
1861
+ options.forEach((option) => {
1862
+ const regex = new RegExp(this.nestingSpacer, "gu");
1863
+ option.innerHTML = this.nestingSpacer.repeat(menu.level) + option.innerHTML.replace(regex, '');
1864
+ });
1865
+ }
1866
+
1867
+ // Event Handlers
1868
+
1869
+ /**
1870
+ * Handles keyboard navigation.
1871
+ * @private
1872
+ * @param {KeyboardEvent} event - Event object from the browser.
1873
+ */
1874
+ handleKeyDown(event) {
1875
+ event.preventDefault();
1876
+ switch (event.key) {
1877
+ case "ArrowDown":
1878
+ this.menuService.highlightNext();
1879
+ break;
1880
+ case "ArrowUp":
1881
+ this.menuService.highlightPrevious();
1882
+ break;
1883
+ case "Tab":
1884
+ case "Enter":
1885
+ this.menuService.selectHighlightedOption();
1886
+ break;
1887
+ }
1888
+ }
1889
+
1890
+ /**
1891
+ * Navigates the menu options in the specified direction.
1892
+ * @param {'up'|'down'} direction - The direction to navigate.
1893
+ * @protected
1013
1894
  */
1014
- updateActiveOption(index) {
1015
- if (!this.items || !this.items[index]) {
1016
- return;
1895
+ navigateOptions(direction) {
1896
+ if (direction === 'up') {
1897
+ this.menuService.highlightPrevious();
1898
+ } else if (direction === 'down') {
1899
+ this.menuService.highlightNext();
1017
1900
  }
1901
+ }
1018
1902
 
1019
- this.items.forEach((item) => item.classList.remove('active'));
1020
- this.items[index].classList.add('active');
1021
- this.optionActive = this.items[index];
1022
- this.index = index;
1903
+ /**
1904
+ * Handles slot change events.
1905
+ * @private
1906
+ */
1907
+ handleSlotChange() {
1908
+ if (this.parentElement && this.parentElement.closest('auro-menu, [auro-menu]')) {
1909
+ this.rootMenu = false;
1910
+ }
1023
1911
 
1024
- dispatchMenuEvent(this, 'auroMenu-activatedOption', this.items[index]);
1912
+ if (this.rootMenu) {
1913
+ this.initializeMenu();
1914
+ }
1025
1915
  }
1026
1916
 
1027
1917
  /**
@@ -1040,8 +1930,13 @@ class AuroMenu extends AuroElement {
1040
1930
  * @param {any} source - The source that triggers this event.
1041
1931
  * @private
1042
1932
  */
1043
- notifySelectionChange(source = undefined) {
1044
- dispatchMenuEvent(this, 'auroMenu-selectedOption', { source });
1933
+ notifySelectionChange({value, stringValue, keys, options} = {}) {
1934
+ dispatchMenuEvent(this, 'auroMenu-selectedOption', {
1935
+ value,
1936
+ stringValue,
1937
+ keys,
1938
+ options
1939
+ });
1045
1940
  }
1046
1941
 
1047
1942
  /**
@@ -1114,251 +2009,4 @@ class AuroMenu extends AuroElement {
1114
2009
  }
1115
2010
  }
1116
2011
 
1117
- var styleCss = css`.body-default{font-family:var(--wcss-body-family, "AS Circular"),system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;font-weight:var(--wcss-body-weight, 450);letter-spacing:var(--wcss-body-letter-spacing, 0);font-size:var(--wcss-body-default-font-size, 1rem);line-height:var(--wcss-body-default-line-height, 1.5rem)}.body-lg{font-family:var(--wcss-body-family, "AS Circular"),system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;font-weight:var(--wcss-body-weight, 450);letter-spacing:var(--wcss-body-letter-spacing, 0);font-size:var(--wcss-body-lg-font-size, 1.125rem);line-height:var(--wcss-body-lg-line-height, 1.625rem)}.body-sm{font-family:var(--wcss-body-family, "AS Circular"),system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;font-weight:var(--wcss-body-weight, 450);letter-spacing:var(--wcss-body-letter-spacing, 0);font-size:var(--wcss-body-sm-font-size, 0.875rem);line-height:var(--wcss-body-sm-line-height, 1.25rem)}.body-xs{font-family:var(--wcss-body-family, "AS Circular"),system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;font-weight:var(--wcss-body-weight, 450);letter-spacing:var(--wcss-body-letter-spacing, 0);font-size:var(--wcss-body-xs-font-size, 0.75rem);line-height:var(--wcss-body-xs-line-height, 1rem)}.body-2xs{font-family:var(--wcss-body-family, "AS Circular"),system-ui,-apple-system,BlinkMacSystemFont,"Segoe UI",Roboto,"Helvetica Neue",Arial,sans-serif;font-weight:var(--wcss-body-weight, 450);letter-spacing:var(--wcss-body-letter-spacing, 0);font-size:var(--wcss-body-2xs-font-size, 0.625rem);line-height:var(--wcss-body-2xs-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);letter-spacing:var(--wcss-display-2xl-letter-spacing, 0);font-weight:var(--wcss-display-2xl-weight, 300);line-height:var(--wcss-display-2xl-line-height, 1.3);font-size:var(--wcss-display-2xl-font-size, clamp(3.5rem, 6vw, 5.375rem))}.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);letter-spacing:var(--wcss-display-xl-letter-spacing, 0);font-weight:var(--wcss-display-xl-weight, 300);line-height:var(--wcss-display-xl-line-height, 1.3);font-size:var(--wcss-display-xl-font-size, clamp(3rem, 5.3333333333vw, 4.5rem))}.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);letter-spacing:var(--wcss-display-lg-letter-spacing, 0);font-weight:var(--wcss-display-lg-weight, 300);line-height:var(--wcss-display-lg-line-height, 1.3);font-size:var(--wcss-display-lg-font-size, clamp(2.75rem, 4.6666666667vw, 4rem))}.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);letter-spacing:var(--wcss-display-md-letter-spacing, 0);font-weight:var(--wcss-display-md-weight, 300);line-height:var(--wcss-display-md-line-height, 1.3);font-size:var(--wcss-display-md-font-size, clamp(2.5rem, 4vw, 3.5rem))}.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);letter-spacing:var(--wcss-display-sm-letter-spacing, 0);font-weight:var(--wcss-display-sm-weight, 300);line-height:var(--wcss-display-sm-line-height, 1.3);font-size:var(--wcss-display-sm-font-size, clamp(2rem, 3.6666666667vw, 3rem))}.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);letter-spacing:var(--wcss-display-xs-letter-spacing, 0);font-weight:var(--wcss-display-xs-weight, 300);line-height:var(--wcss-display-xs-line-height, 1.3);font-size:var(--wcss-display-xs-font-size, clamp(1.75rem, 3vw, 2.375rem))}.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);letter-spacing:var(--wcss-heading-xl-letter-spacing, 0);font-weight:var(--wcss-heading-xl-weight, 300);line-height:var(--wcss-heading-xl-line-height, 1.3);font-size:var(--wcss-heading-xl-font-size, clamp(2rem, 3vw, 2.5rem))}.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);letter-spacing:var(--wcss-heading-lg-letter-spacing, 0);font-weight:var(--wcss-heading-lg-weight, 300);line-height:var(--wcss-heading-lg-line-height, 1.3);font-size:var(--wcss-heading-lg-font-size, clamp(1.75rem, 2.6666666667vw, 2.25rem))}.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);letter-spacing:var(--wcss-heading-md-letter-spacing, 0);font-weight:var(--wcss-heading-md-weight, 300);line-height:var(--wcss-heading-md-line-height, 1.3);font-size:var(--wcss-heading-md-font-size, clamp(1.625rem, 2.3333333333vw, 1.75rem))}.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);letter-spacing:var(--wcss-heading-sm-letter-spacing, 0);font-weight:var(--wcss-heading-sm-weight, 300);line-height:var(--wcss-heading-sm-line-height, 1.3);font-size:var(--wcss-heading-sm-font-size, clamp(1.375rem, 2vw, 1.5rem))}.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);letter-spacing:var(--wcss-heading-xs-letter-spacing, 0);font-weight:var(--wcss-heading-xs-weight, 450);line-height:var(--wcss-heading-xs-line-height, 1.3);font-size:var(--wcss-heading-xs-font-size, clamp(1.25rem, 1.6666666667vw, 1.25rem))}.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);letter-spacing:var(--wcss-heading-2xs-letter-spacing, 0);font-weight:var(--wcss-heading-2xs-weight, 450);line-height:var(--wcss-heading-2xs-line-height, 1.3);font-size:var(--wcss-heading-2xs-font-size, clamp(1.125rem, 1.5vw, 1.125rem))}.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);letter-spacing:var(--wcss-accent-2xl-letter-spacing, 0.05em);font-weight:var(--wcss-accent-2xl-weight, 450);line-height:var(--wcss-accent-2xl-line-height, 1);font-size:var(--wcss-accent-2xl-font-size, clamp(2rem, 3.1666666667vw, 2.375rem));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);letter-spacing:var(--wcss-accent-xl-letter-spacing, 0.05em);font-weight:var(--wcss-accent-xl-weight, 450);line-height:var(--wcss-accent-xl-line-height, 1.3);font-size:var(--wcss-accent-xl-font-size, clamp(1.625rem, 2.3333333333vw, 2rem));text-transform:uppercase}.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);letter-spacing:var(--wcss-accent-lg-letter-spacing, 0.05em);font-weight:var(--wcss-accent-lg-weight, 450);line-height:var(--wcss-accent-lg-line-height, 1.3);font-size:var(--wcss-accent-lg-font-size, clamp(1.5rem, 2.1666666667vw, 1.75rem));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);letter-spacing:var(--wcss-accent-md-letter-spacing, 0.05em);font-weight:var(--wcss-accent-md-weight, 500);line-height:var(--wcss-accent-md-line-height, 1.3);font-size:var(--wcss-accent-md-font-size, clamp(1.375rem, 1.8333333333vw, 1.5rem));text-transform:uppercase}.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);letter-spacing:var(--wcss-accent-sm-letter-spacing, 0.05em);font-weight:var(--wcss-accent-sm-weight, 500);line-height:var(--wcss-accent-sm-line-height, 1.3);font-size:var(--wcss-accent-sm-font-size, clamp(1.125rem, 1.5vw, 1.25rem));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);letter-spacing:var(--wcss-accent-xs-letter-spacing, 0.1em);font-weight:var(--wcss-accent-xs-weight, 500);line-height:var(--wcss-accent-xs-line-height, 1.3);font-size:var(--wcss-accent-xs-font-size, clamp(1rem, 1.3333333333vw, 1rem));text-transform:uppercase}.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);letter-spacing:var(--wcss-accent-2xs-letter-spacing, 0.1em);font-weight:var(--wcss-accent-2xs-weight, 450);line-height:var(--wcss-accent-2xs-line-height, 1.3);font-size:var(--wcss-accent-2xs-font-size, clamp(0.875rem, 1.1666666667vw, 0.875rem));text-transform:uppercase}:host{cursor:pointer;user-select:none;text-overflow:ellipsis;max-width:100dvw}:host .wrapper{display:flex;align-items:center;padding-right:var(--ds-size-200, 1rem);padding-left:calc(var(--ds-size-150, 0.75rem) + var(--ds-size-300, 1.5rem) + var(--ds-size-100, 0.5rem));padding-top:var(--ds-size-50, 0.25rem);padding-bottom:var(--ds-size-50, 0.25rem);border-radius:var(--ds-size-100, 0.5rem);-webkit-tap-highlight-color:transparent}:host .wrapper[class*=shape-box]{border-radius:unset}:host .wrapper[class*=shape-snowflake]{border-radius:unset;line-height:24px}:host .wrapper[class*=shape-pill]{border-radius:30px}:host .wrapper[class*=-lg]{padding-top:var(--ds-size-75, 0.375rem);padding-bottom:var(--ds-size-75, 0.375rem);padding-right:var(--ds-size-150, 0.75rem);line-height:26px}:host .wrapper[class*=-xl]{padding-top:var(--ds-size-100, 0.5rem);padding-bottom:var(--ds-size-100, 0.5rem);padding-right:var(--ds-size-200, 1rem);line-height:26px}:host slot{display:block;overflow:hidden;white-space:nowrap;text-overflow:ellipsis}:host [auro-icon]{--ds-auro-icon-size: var(--ds-size-300, 1.5rem);margin-right:var(--ds-size-150, 0.75rem);margin-left:var(--ds-size-100, 0.5rem)}:host ::slotted(.nestingSpacer){display:inline-block;width:var(--ds-size-300, 1.5rem)}[slot=displayValue]{display:none}:host([loadingplaceholder]) .wrapper{padding-left:calc(var(--ds-size-150, 0.75rem) + var(--ds-size-300, 1.5rem) + var(--ds-size-100, 0.5rem))}:host([selected]) .wrapper{padding-left:0}:host([nocheckmark]) .wrapper{padding-left:var(--ds-size-150, 0.75rem)}:host([nocheckmark]) .wrapper[class*=-lg]{padding-left:var(--ds-size-150, 0.75rem)}:host([nocheckmark]) .wrapper[class*=-xl]{padding-left:var(--ds-size-200, 1rem)}:host([hidden]){display:none}:host([static]){pointer-events:none}:host([disabled]:hover){cursor:auto}:host([disabled]){user-select:none;pointer-events:none}`;
1118
-
1119
- var colorCss = css`:host .wrapper{background-color:var(--ds-auro-menuoption-container-color, transparent);box-shadow:inset 0 0 0 1px var(--ds-auro-menuoption-container-border-color, transparent);color:var(--ds-auro-menuoption-text-color)}:host svg{fill:var(--ds-auro-menuoption-icon-color)}:host([disabled]){--ds-auro-menuoption-container-color: var(--ds-basic-color-surface-default, #ffffff);--ds-auro-menuoption-text-color: var(--ds-basic-color-texticon-disabled, #d0d0d0);--ds-auro-menuoption-icon-color: var(--ds-basic-color-texticon-disabled, #d0d0d0)}:host(:hover),:host(.active){--ds-auro-menuoption-container-color: var(--ds-basic-color-surface-accent1-muted, #ebfafd)}:host(:focus){--ds-auro-menuoption-container-color: var(--ds-basic-color-surface-default, #ffffff);--ds-auro-menuoption-container-border-color: var(--ds-basic-color-border-brand, #00274a)}:host([selected]){--ds-auro-menuoption-container-color: var(--ds-basic-color-surface-accent1-subtle, #b4eff9);--ds-auro-menuoption-text-color: var(--ds-basic-color-texticon-default, #2a2a2a);--ds-auro-menuoption-icon-color: var(--ds-basic-color-texticon-default, #2a2a2a)}:host([selected]:hover),:host([selected].active){--ds-auro-menuoption-container-color: var(--ds-basic-color-surface-accent1-muted, #ebfafd)}:host([selected]:focus){--ds-auro-menuoption-container-color: var(--ds-basic-color-surface-accent1-subtle, #b4eff9);--ds-auro-menuoption-container-border-color: var(--ds-basic-color-border-brand, #00274a)}:host(:focus:hover),:host(:focus.active){--ds-auro-menuoption-container-color: var(--ds-basic-color-surface-accent1-muted, #ebfafd);--ds-auro-menuoption-container-border-color: var(--ds-basic-color-border-brand, #00274a)}:host([selected]:focus:hover),:host([selected]:focus.active){--ds-auro-menuoption-container-color: var(--ds-basic-color-surface-accent1-muted, #ebfafd);--ds-auro-menuoption-container-border-color: var(--ds-basic-color-border-brand, #00274a)}`;
1120
-
1121
- // Copyright (c) Alaska Air. All right reserved. Licensed under the Apache-2.0 license
1122
- // See LICENSE in the project root for license information.
1123
-
1124
-
1125
- class AuroDependencyVersioning {
1126
-
1127
- /**
1128
- * Generates a unique string to be used for child auro element naming.
1129
- * @private
1130
- * @param {string} baseName - Defines the first part of the unique element name.
1131
- * @param {string} version - Version of the component that will be appended to the baseName.
1132
- * @returns {string} - Unique string to be used for naming.
1133
- */
1134
- generateElementName(baseName, version) {
1135
- let result = baseName;
1136
-
1137
- result += '-';
1138
- result += version.replace(/[.]/g, '_');
1139
-
1140
- return result;
1141
- }
1142
-
1143
- /**
1144
- * Generates a unique string to be used for child auro element naming.
1145
- * @param {string} baseName - Defines the first part of the unique element name.
1146
- * @param {string} version - Version of the component that will be appended to the baseName.
1147
- * @returns {string} - Unique string to be used for naming.
1148
- */
1149
- generateTag(baseName, version, tagClass) {
1150
- const elementName = this.generateElementName(baseName, version);
1151
- const tag = literal`${unsafeStatic(elementName)}`;
1152
-
1153
- if (!customElements.get(elementName)) {
1154
- customElements.define(elementName, class extends tagClass {});
1155
- }
1156
-
1157
- return tag;
1158
- }
1159
- }
1160
-
1161
- class p{registerComponent(t,a){customElements.get(t)||customElements.define(t,class extends a{});}closestElement(t,a=this,e=(a,s=a&&a.closest(t))=>a&&a!==document&&a!==window?s||e(a.getRootNode().host):null){return e(a)}handleComponentTagRename(t,a){const e=a.toLowerCase();t.tagName.toLowerCase()!==e&&t.setAttribute(e,true);}elementMatch(t,a){const e=a.toLowerCase();return t.tagName.toLowerCase()===e||t.hasAttribute(e)}}var u='<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-labelledby="error__desc" class="ico_squareLarge" data-deprecated="true" role="img" style="min-width:var(--auro-size-lg, var(--ds-size-300, 1.5rem));height:var(--auro-size-lg, var(--ds-size-300, 1.5rem));fill:currentColor" viewBox="0 0 24 24" part="svg"><title/><desc id="error__desc">Error alert indicator.</desc><path d="m13.047 5.599 6.786 11.586A1.207 1.207 0 0 1 18.786 19H5.214a1.207 1.207 0 0 1-1.047-1.815l6.786-11.586a1.214 1.214 0 0 1 2.094 0m-1.165.87a.23.23 0 0 0-.085.085L5.419 17.442a.232.232 0 0 0 .203.35h12.756a.234.234 0 0 0 .203-.35L12.203 6.554a.236.236 0 0 0-.321-.084M12 15.5a.75.75 0 1 1 0 1.5.75.75 0 0 1 0-1.5m-.024-6.22c.325 0 .589.261.589.583v4.434a.586.586 0 0 1-.589.583.586.586 0 0 1-.588-.583V9.863c0-.322.264-.583.588-.583"/></svg>';class m extends LitElement{static get properties(){return {hidden:{type:Boolean,reflect:true},hiddenVisually:{type:Boolean,reflect:true},hiddenAudible:{type:Boolean,reflect:true}}}hideAudible(t){return t?"true":"false"}}const g=new Map,f=(t,a={})=>{const e=a.responseParser||(t=>t.text());return g.has(t)||g.set(t,fetch(t).then(e)),g.get(t)};var w=css`:focus:not(:focus-visible){outline:3px solid transparent}.util_displayInline{display:inline}.util_displayInlineBlock{display:inline-block}.util_displayBlock,:host{display:block}.util_displayFlex{display:flex}.util_displayHidden,:host([hidden]:not(:focus):not(:active)){display:none}.util_displayHiddenVisually,:host([hiddenVisually]:not(:focus):not(:active)){position:absolute;overflow:hidden;clip:rect(1px,1px,1px,1px);width:1px;height:1px;padding:0;border:0}.ico_squareLarge{fill:currentColor;height:var(--auro-size-lg, var(--ds-size-300, 1.5rem))}.ico_squareSmall{fill:currentColor;height:.6rem}.ico_squareMed{fill:currentColor;height:var(--auro-size-md, var(--ds-size-200, 1rem))}.ico_squareSml{fill:currentColor;height:var(--auro-size-sm, var(--ds-size-150, .75rem))}:host{color:currentColor;vertical-align:middle;line-height:1;display:inline-block}svg{min-width:var(--ds-auro-icon-size, 1.5rem)!important;width:var(--ds-auro-icon-size, 1.5rem)!important;height:var(--ds-auro-icon-size, 1.5rem)!important}.componentWrapper{display:flex}.svgWrapper{height:var(--ds-auro-icon-size);width:var(--ds-auro-icon-size)}.labelWrapper{margin-left:var(--ds-size-50, .25rem);line-height:1.8}
1162
- `;class z extends m{constructor(){super(),this.onDark=false,this.appearance="default";}static get properties(){return {...m.properties,onDark:{type:Boolean,reflect:true},appearance:{type:String,reflect:true},svg:{attribute:false,reflect:true}}}static get styles(){return w}async fetchIcon(t,a){let e="";e="logos"===t?await f(`${this.uri}/${t}/${a}.svg`):await f(`${this.uri}/icons/${t}/${a}.svg`);return (new DOMParser).parseFromString(e,"text/html").body.querySelector("svg")}async firstUpdated(){try{if(!this.customSvg){const t=await this.fetchIcon(this.category,this.name);if(t)this.svg=t;else if(!t){const t=(new DOMParser).parseFromString(u,"text/html");this.svg=t.body.firstChild;}}}catch(t){this.svg=void 0;}}}css`.util_displayInline{display:inline}.util_displayInlineBlock{display:inline-block}.util_displayBlock,:host{display:block}.util_displayFlex{display:flex}.util_displayHidden,:host([hidden]:not(:focus):not(:active)){display:none}.util_displayHiddenVisually,:host([hiddenVisually]:not(:focus):not(:active)){position:absolute;overflow:hidden;clip:rect(1px,1px,1px,1px);width:1px;height:1px;padding:0;border:0}:host{display:inline-block;--ds-auro-icon-size: 100%;width:100%;height:100%}:host .logo{color:var(--ds-auro-alaska-color)}:host([onDark]),:host([appearance=inverse]){--ds-auro-alaska-color: #FFF}
1163
- `;var y=css`:host{--ds-auro-icon-color: var(--ds-basic-color-texticon-default, #2a2a2a);--ds-auro-alaska-color: #02426D;--ds-auro-icon-size: var(--ds-size-300, 1.5rem)}
1164
- `;var k=css`:host{color:var(--ds-auro-icon-color)}:host([customColor]){color:inherit}:host(:not([onDark])[variant=accent1]),:host(:not([appearance=inverse])[variant=accent1]){--ds-auro-icon-color: var(--ds-basic-color-texticon-accent1, #265688)}:host(:not([onDark])[variant=disabled]),:host(:not([appearance=inverse])[variant=disabled]){--ds-auro-icon-color: var(--ds-basic-color-texticon-disabled, #d0d0d0)}:host(:not([onDark])[variant=muted]),:host(:not([appearance=inverse])[variant=muted]){--ds-auro-icon-color: var(--ds-basic-color-texticon-muted, #676767)}:host(:not([onDark])[variant=statusDefault]),:host(:not([appearance=inverse])[variant=statusDefault]){--ds-auro-icon-color: var(--ds-basic-color-status-default, #afb9c6)}:host(:not([onDark])[variant=statusInfo]),:host(:not([appearance=inverse])[variant=statusInfo]){--ds-auro-icon-color: var(--ds-basic-color-status-info, #01426a)}:host(:not([onDark])[variant=statusSuccess]),:host(:not([appearance=inverse])[variant=statusSuccess]){--ds-auro-icon-color: var(--ds-basic-color-status-success, #447a1f)}:host(:not([onDark])[variant=statusWarning]),:host(:not([appearance=inverse])[variant=statusWarning]){--ds-auro-icon-color: var(--ds-basic-color-status-warning, #fac200)}:host(:not([onDark])[variant=statusError]),:host(:not([appearance=inverse])[variant=statusError]){--ds-auro-icon-color: var(--ds-basic-color-status-error, #e31f26)}:host(:not([onDark])[variant=statusInfoSubtle]),:host(:not([appearance=inverse])[variant=statusInfoSubtle]){--ds-auro-icon-color: var(--ds-basic-color-status-info-subtle, #ebf3f9)}:host(:not([onDark])[variant=statusSuccessSubtle]),:host(:not([appearance=inverse])[variant=statusSuccessSubtle]){--ds-auro-icon-color: var(--ds-basic-color-status-success-subtle, #d6eac7)}:host(:not([onDark])[variant=statusWarningSubtle]),:host(:not([appearance=inverse])[variant=statusWarningSubtle]){--ds-auro-icon-color: var(--ds-basic-color-status-warning-subtle, #fff0b2)}:host(:not([onDark])[variant=statusErrorSubtle]),:host(:not([appearance=inverse])[variant=statusErrorSubtle]){--ds-auro-icon-color: var(--ds-basic-color-status-error-subtle, #fbc6c6)}:host(:not([onDark])[variant=fareBasicEconomy]),:host(:not([appearance=inverse])[variant=fareBasicEconomy]){--ds-auro-icon-color: var(--ds-basic-color-fare-basiceconomy, #97eaf8)}:host(:not([onDark])[variant=fareBusiness]),:host(:not([appearance=inverse])[variant=fareBusiness]){--ds-auro-icon-color: var(--ds-basic-color-fare-business, #01426a)}:host(:not([onDark])[variant=fareEconomy]),:host(:not([appearance=inverse])[variant=fareEconomy]){--ds-auro-icon-color: var(--ds-basic-color-fare-economy, #0074ca)}:host(:not([onDark])[variant=fareFirst]),:host(:not([appearance=inverse])[variant=fareFirst]){--ds-auro-icon-color: var(--ds-basic-color-fare-first, #00274a)}:host(:not([onDark])[variant=farePremiumEconomy]),:host(:not([appearance=inverse])[variant=farePremiumEconomy]){--ds-auro-icon-color: var(--ds-basic-color-fare-premiumeconomy, #005154)}:host(:not([onDark])[variant=tierOneWorldEmerald]),:host(:not([appearance=inverse])[variant=tierOneWorldEmerald]){--ds-auro-icon-color: var(--ds-basic-color-tier-program-oneworld-emerald, #139142)}:host(:not([onDark])[variant=tierOneWorldSapphire]),:host(:not([appearance=inverse])[variant=tierOneWorldSapphire]){--ds-auro-icon-color: var(--ds-basic-color-tier-program-oneworld-sapphire, #015daa)}:host(:not([onDark])[variant=tierOneWorldRuby]),:host(:not([appearance=inverse])[variant=tierOneWorldRuby]){--ds-auro-icon-color: var(--ds-basic-color-tier-program-oneworld-ruby, #a41d4a)}:host([onDark]),:host([appearance=inverse]){--ds-auro-icon-color: var(--ds-basic-color-texticon-inverse, #ffffff)}:host([onDark][variant=disabled]),:host([appearance=inverse][variant=disabled]){--ds-auro-icon-color: var(--ds-basic-color-texticon-inverse-disabled, #7e8894)}:host([onDark][variant=muted]),:host([appearance=inverse][variant=muted]){--ds-auro-icon-color: var(--ds-basic-color-texticon-inverse-muted, #ccd2db)}:host([onDark][variant=statusError]),:host([appearance=inverse][variant=statusError]){--ds-auro-icon-color: var(--ds-advanced-color-state-error-inverse, #f9a4a8)}
1165
- `;class x extends z{constructor(){super(),this.variant=void 0,this.privateDefaults();}privateDefaults(){this.uri="https://cdn.jsdelivr.net/npm/@alaskaairux/icons@latest/dist",this.runtimeUtils=new p;}static get properties(){return {...z.properties,ariaHidden:{type:String,reflect:true},category:{type:String,reflect:true},customColor:{type:Boolean,reflect:true},customSvg:{type:Boolean},label:{type:Boolean,reflect:true},name:{type:String,reflect:true},variant:{type:String,reflect:true}}}static get styles(){return [z.styles,y,w,k]}static register(t="auro-icon"){p.prototype.registerComponent(t,x);}connectedCallback(){super.connectedCallback(),this.runtimeUtils.handleComponentTagRename(this,"auro-icon");}exposeCssParts(){this.setAttribute("exportparts","svg:iconSvg");}async firstUpdated(){if(await super.firstUpdated(),this.hasAttribute("ariaHidden")&&this.svg){const t=this.svg.querySelector("desc");t&&(t.remove(),this.svg.removeAttribute("aria-labelledby"));}}render(){const t={labelWrapper:true,util_displayHiddenVisually:!this.label};return html`
1166
- <div class="componentWrapper">
1167
- <div
1168
- class="${classMap({svgWrapper:true})}"
1169
- title="${ifDefined(this.title||void 0)}">
1170
- <span aria-hidden="${ifDefined(this.ariaHidden||true)}" part="svg">
1171
- ${this.customSvg?html`
1172
- <slot name="svg"></slot>
1173
- `:html`
1174
- ${this.svg}
1175
- `}
1176
- </span>
1177
- </div>
1178
-
1179
- <div class="${classMap(t)}" part="label">
1180
- <slot></slot>
1181
- </div>
1182
- </div>
1183
- `}}
1184
-
1185
- var iconVersion = '9.1.0';
1186
-
1187
- var checkmarkIcon = {"svg":"<svg xmlns=\"http://www.w3.org/2000/svg\" xmlns:xlink=\"http://www.w3.org/1999/xlink\" aria-labelledby=\"checkmark-sm__desc\" class=\"ico_squareLarge\" role=\"img\" style=\"min-width:var(--auro-size-lg, var(--ds-size-300, 1.5rem));height:var(--auro-size-lg, var(--ds-size-300, 1.5rem));fill:currentColor\" viewBox=\"0 0 24 24\" part=\"svg\"><title/><desc id=\"checkmark-sm__desc\">a small check mark.</desc><path d=\"M8.461 11.84a.625.625 0 1 0-.922.844l2.504 2.738c.247.27.674.27.922 0l5.496-6a.625.625 0 1 0-.922-.844l-5.035 5.496z\"/></svg>"};
1188
-
1189
- // Copyright (c) 2021 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
1190
- // See LICENSE in the project root for license information.
1191
-
1192
-
1193
- /**
1194
- * The auro-menu element provides users a way to define a menu option.
1195
- *
1196
- * @attr {String} value - Specifies the value to be sent to a server.
1197
- * @attr {String} noCheckmark - When true, selected option will not show the checkmark.
1198
- * @attr {Boolean} disabled - When true specifies that the menuoption is disabled.
1199
- * @attr {Boolean} selected - Specifies that an option is selected.
1200
- * @event auroMenuOption-mouseover - Notifies that this option has been hovered over.
1201
- * @slot - Specifies text for an option, but is not the value.
1202
- */
1203
- class AuroMenuOption extends AuroElement {
1204
- constructor() {
1205
- super();
1206
-
1207
- /**
1208
- * @private
1209
- */
1210
- this.shape = undefined;
1211
-
1212
- /**
1213
- * @private
1214
- */
1215
- this.size = undefined;
1216
-
1217
- /**
1218
- * Generate unique names for dependency components.
1219
- */
1220
- const versioning = new AuroDependencyVersioning();
1221
- this.iconTag = versioning.generateTag('auro-formkit-menuoption-icon', iconVersion, x);
1222
-
1223
- this.selected = false;
1224
- this.nocheckmark = false;
1225
- this.disabled = false;
1226
-
1227
- /**
1228
- * @private
1229
- */
1230
- this.tabIndex = -1;
1231
-
1232
- /**
1233
- * @private
1234
- */
1235
- this.runtimeUtils = new AuroLibraryRuntimeUtils();
1236
- }
1237
-
1238
- static get properties() {
1239
- return {
1240
- ...super.properties,
1241
- nocheckmark: {
1242
- type: Boolean,
1243
- reflect: true
1244
- },
1245
- selected: {
1246
- type: Boolean,
1247
- reflect: true
1248
- },
1249
- disabled: {
1250
- type: Boolean,
1251
- reflect: true
1252
- },
1253
- value: {
1254
- type: String,
1255
- reflect: true
1256
- },
1257
- tabIndex: {
1258
- type: Number,
1259
- reflect: true
1260
- }
1261
- };
1262
- }
1263
-
1264
- static get styles() {
1265
- return [
1266
- styleCss,
1267
- colorCss,
1268
- tokensCss
1269
- ];
1270
- }
1271
-
1272
- /**
1273
- * This will register this element with the browser.
1274
- * @param {string} [name="auro-menuoption"] - The name of element that you want to register to.
1275
- *
1276
- * @example
1277
- * AuroMenuOption.register("custom-menuoption") // this will register this element to <custom-menuoption/>
1278
- *
1279
- */
1280
- static register(name = "auro-menuoption") {
1281
- AuroLibraryRuntimeUtils.prototype.registerComponent(name, AuroMenuOption);
1282
- }
1283
-
1284
- firstUpdated() {
1285
- // Add the tag name as an attribute if it is different than the component name
1286
- this.runtimeUtils.handleComponentTagRename(this, 'auro-menuoption');
1287
-
1288
- if (!this.hasAttribute('size')) {
1289
- this.size = this.parentElement.getAttribute('size') || 'sm';
1290
- }
1291
- if (!this.hasAttribute('shape')) {
1292
- this.shape = this.parentElement.getAttribute('shape') || 'box';
1293
- }
1294
-
1295
- this.setAttribute('role', 'option');
1296
- this.setAttribute('aria-selected', 'false');
1297
-
1298
- this.addEventListener('mouseover', () => {
1299
- this.dispatchEvent(new CustomEvent('auroMenuOption-mouseover', {
1300
- bubbles: true,
1301
- cancelable: false,
1302
- composed: true,
1303
- detail: this
1304
- }));
1305
- });
1306
- }
1307
-
1308
- // observer for selected property changes
1309
- updated(changedProperties) {
1310
- super.updated(changedProperties);
1311
-
1312
- if (changedProperties.has('selected')) {
1313
- this.setAttribute('aria-selected', this.selected.toString());
1314
- }
1315
- }
1316
-
1317
- /**
1318
- * Generates an HTML element containing an SVG icon based on the provided `svgContent`.
1319
- *
1320
- * @private
1321
- * @param {string} svgContent - The SVG content to be embedded.
1322
- * @returns {Element} The HTML element containing the SVG icon.
1323
- */
1324
- generateIconHtml(svgContent) {
1325
- const dom = new DOMParser().parseFromString(svgContent, 'text/html');
1326
- const svg = dom.body.firstChild;
1327
-
1328
- svg.setAttribute('slot', 'svg');
1329
-
1330
- return html$1`<${this.iconTag} customColor customSvg>${svg}</${this.iconTag}>`;
1331
- }
1332
-
1333
- /**
1334
- * Logic to determine the layout of the component.
1335
- * @protected
1336
- * @returns {void}
1337
- */
1338
- renderLayout() {
1339
-
1340
- const fontClassMap = {
1341
- xs: 'body-sm',
1342
- sm: 'body-default',
1343
- md: 'body-default',
1344
- lg: 'body-lg',
1345
- xl: 'body-lg'
1346
- };
1347
-
1348
- const classes = classMap({
1349
- 'wrapper': true,
1350
- [this.size ? fontClassMap[this.size] : 'body-sm']: true,
1351
- });
1352
-
1353
- return html$1`
1354
- <div class="${classes}">
1355
- ${this.selected && !this.nocheckmark
1356
- ? this.generateIconHtml(checkmarkIcon.svg)
1357
- : undefined}
1358
- <slot></slot>
1359
- </div>
1360
- `;
1361
- }
1362
- }
1363
-
1364
2012
  export { AuroMenu, AuroMenuOption, arrayConverter, dispatchMenuEvent, isOptionInteractive };