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