@aurodesignsystem-dev/auro-formkit 0.0.0-pr1460.2 → 0.0.0-pr1462.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.
- package/components/checkbox/demo/api.html +4 -26
- package/components/checkbox/demo/getting-started.md +5 -6
- package/components/checkbox/demo/index.min.js +1 -1
- package/components/checkbox/dist/index.js +1 -1
- package/components/checkbox/dist/registered.js +1 -1
- package/components/combobox/demo/api.html +4 -25
- package/components/combobox/demo/getting-started.md +76 -27
- package/components/combobox/demo/index.min.js +15 -1
- package/components/combobox/demo/registered.min.js +1506 -1506
- package/components/combobox/dist/index.js +3 -3
- package/components/combobox/dist/registered.js +3 -3
- package/components/counter/demo/api.html +5 -29
- package/components/counter/demo/getting-started.md +4 -3
- package/components/counter/demo/index.min.js +8392 -1
- package/components/counter/dist/index.js +106 -5110
- package/components/counter/dist/registered.js +106 -5110
- package/components/datepicker/demo/accessibility.html +0 -1
- package/components/datepicker/demo/api.html +4 -29
- package/components/datepicker/demo/getting-started.md +25 -2
- package/components/datepicker/demo/index.min.js +24612 -1
- package/components/datepicker/demo/readme.html +2 -10
- package/components/datepicker/dist/index.js +3 -3
- package/components/datepicker/dist/registered.js +3 -3
- package/components/dropdown/demo/api.html +5 -31
- package/components/dropdown/demo/getting-started.md +34 -2
- package/components/dropdown/demo/index.min.js +5097 -1
- package/components/dropdown/dist/index.js +1 -1
- package/components/dropdown/dist/registered.js +1 -1
- package/components/form/demo/api.html +5 -27
- package/components/form/demo/getting-started.md +5 -6
- package/components/form/demo/index.min.js +719 -2
- package/components/form/demo/keyboard-behavior.md +38 -0
- package/components/form/demo/pages.json +1 -1
- package/components/form/demo/registerDemoDeps.min.js +11590 -60657
- package/components/input/demo/accessibility.md +1 -1
- package/components/input/demo/api.html +15 -26
- package/components/input/demo/auro-input.min.js +1 -1
- package/components/input/demo/getting-started.md +1 -1
- package/components/input/demo/readme.html +2 -10
- package/components/input/dist/index.js +1 -1
- package/components/input/dist/registered.js +1 -1
- package/components/menu/demo/api.html +5 -30
- package/components/menu/demo/getting-started.md +1 -1
- package/components/menu/demo/index.min.js +1572 -1572
- package/components/menu/dist/auro-menu.context.d.ts +0 -1
- package/components/menu/dist/index.js +1607 -1607
- package/components/menu/dist/registered.js +1556 -1556
- package/components/radio/demo/api.html +7 -28
- package/components/radio/demo/getting-started.md +27 -2
- package/components/radio/demo/index.min.js +1 -1
- package/components/radio/dist/index.js +1 -1
- package/components/radio/dist/registered.js +1 -1
- package/components/select/demo/api.html +5 -42
- package/components/select/demo/getting-started.md +39 -5
- package/components/select/demo/registered.min.js +1505 -1505
- package/components/select/dist/index.js +2 -2
- package/components/select/dist/registered.js +2 -2
- package/custom-elements.json +1489 -1489
- package/package.json +38 -4
- package/components/combobox/demo/api.js +0 -39
- package/components/combobox/demo/api.min.js +0 -106
- package/components/combobox/demo/install.html +0 -50
- package/components/combobox/demo/styles.css +0 -974
- package/components/combobox/demo/swap-value.min.js +0 -16
- package/components/counter/demo/api.js +0 -24
- package/components/counter/demo/api.min.js +0 -52
- package/components/counter/demo/auro-counter-group.min.js +0 -8394
- package/components/datepicker/demo/api.js +0 -37
- package/components/datepicker/demo/api.min.js +0 -300
- package/components/datepicker/demo/auro-datepicker.min.js +0 -24614
- package/components/dropdown/demo/api.js +0 -26
- package/components/dropdown/demo/api.min.js +0 -109
- package/components/dropdown/demo/auro-dropdown.min.js +0 -5099
- package/components/form/demo/api.js +0 -5
- package/components/form/demo/api.min.js +0 -5
- package/components/form/demo/auro-form.min.js +0 -718
- package/components/form/demo/autocomplete.html +0 -31
- package/components/radio/demo/api.js +0 -19
- package/components/radio/demo/api.min.js +0 -44
- package/components/select/demo/keyboardBehavior.html +0 -48
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { css, LitElement, html } from 'lit';
|
|
2
|
-
import {
|
|
3
|
-
import { unsafeStatic, literal, html as html$1 } from 'lit/static-html.js';
|
|
2
|
+
import { createContext, ContextProvider, ContextConsumer } from '@lit/context';
|
|
4
3
|
import { classMap } from 'lit/directives/class-map.js';
|
|
4
|
+
import { unsafeStatic, literal, html as html$1 } from 'lit/static-html.js';
|
|
5
5
|
import { ifDefined } from 'lit/directives/if-defined.js';
|
|
6
6
|
|
|
7
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-default-weight, );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-default-emphasized{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-default-emphasized-weight, );letter-spacing:var(--wcss-body-letter-spacing, 0);font-size:var(--wcss-body-default-emphasized-font-size, 1rem);line-height:var(--wcss-body-default-emphasized-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-lg-weight, );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-lg-emphasized{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-lg-emphasized-weight, );letter-spacing:var(--wcss-body-letter-spacing, 0);font-size:var(--wcss-body-lg-emphasized-font-size, 1.125rem);line-height:var(--wcss-body-lg-emphasized-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-sm-weight, );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-sm-emphasized{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-sm-emphasized-weight, );letter-spacing:var(--wcss-body-letter-spacing, 0);font-size:var(--wcss-body-sm-emphasized-font-size, 0.875rem);line-height:var(--wcss-body-sm-emphasized-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-xs-weight, );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-xs-emphasized{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-xs-emphasized-weight, );letter-spacing:var(--wcss-body-letter-spacing, 0);font-size:var(--wcss-body-xs-emphasized-font-size, 0.75rem);line-height:var(--wcss-body-xs-emphasized-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-2xs-weight, );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)}.body-2xs-emphasized{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-2xs-emphasized-weight, );letter-spacing:var(--wcss-body-letter-spacing, 0);font-size:var(--wcss-body-2xs-emphasized-font-size, 0.625rem);line-height:var(--wcss-body-2xs-emphasized-line-height, 0.875rem)}.display-2xl{font-family:var(--wcss-display-2xl-family, "AS Circular"),var(--wcss-display-2xl-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-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));letter-spacing:var(--wcss-display-2xl-letter-spacing, 0)}.display-xl{font-family:var(--wcss-display-xl-family, "AS Circular"),var(--wcss-display-xl-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-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));letter-spacing:var(--wcss-display-xl-letter-spacing, 0)}.display-lg{font-family:var(--wcss-display-lg-family, "AS Circular"),var(--wcss-display-lg-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-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));letter-spacing:var(--wcss-display-lg-letter-spacing, 0)}.display-md{font-family:var(--wcss-display-md-family, "AS Circular"),var(--wcss-display-md-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-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));letter-spacing:var(--wcss-display-md-letter-spacing, 0)}.display-sm{font-family:var(--wcss-display-sm-family, "AS Circular"),var(--wcss-display-sm-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-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));letter-spacing:var(--wcss-display-sm-letter-spacing, 0)}.display-xs{font-family:var(--wcss-display-xs-family, "AS Circular"),var(--wcss-display-xs-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-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));letter-spacing:var(--wcss-display-xs-letter-spacing, 0)}.heading-xl{font-family:var(--wcss-heading-xl-family, "AS Circular"),var(--wcss-heading-xl-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-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));letter-spacing:var(--wcss-heading-xl-letter-spacing, 0)}.heading-lg{font-family:var(--wcss-heading-lg-family, "AS Circular"),var(--wcss-heading-lg-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-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));letter-spacing:var(--wcss-heading-lg-letter-spacing, 0)}.heading-md{font-family:var(--wcss-heading-md-family, "AS Circular"),var(--wcss-heading-md-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-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));letter-spacing:var(--wcss-heading-md-letter-spacing, 0)}.heading-sm{font-family:var(--wcss-heading-sm-family, "AS Circular"),var(--wcss-heading-sm-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-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));letter-spacing:var(--wcss-heading-sm-letter-spacing, 0)}.heading-xs{font-family:var(--wcss-heading-xs-family, "AS Circular"),var(--wcss-heading-xs-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-weight:var(--wcss-heading-xs-weight, 300);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));letter-spacing:var(--wcss-heading-xs-letter-spacing, 0)}.heading-2xs{font-family:var(--wcss-heading-2xs-family, "AS Circular"),var(--wcss-heading-2xs-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-weight:var(--wcss-heading-2xs-weight, 300);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));letter-spacing:var(--wcss-heading-2xs-letter-spacing, 0)}.accent-2xl{font-family:var(--wcss-accent-2xl-family, "Good OT"),var(--wcss-accent-2xl-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-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));letter-spacing:var(--wcss-accent-2xl-letter-spacing, 0.05em);text-transform:uppercase}.accent-xl{font-family:var(--wcss-accent-xl-family, "Good OT"),var(--wcss-accent-xl-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-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));letter-spacing:var(--wcss-accent-xl-letter-spacing, 0.05em);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);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));letter-spacing:var(--wcss-accent-lg-letter-spacing, 0.05em);text-transform:uppercase}.accent-md{font-family:var(--wcss-accent-md-family, "Good OT"),var(--wcss-accent-md-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-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));letter-spacing:var(--wcss-accent-md-letter-spacing, 0.05em);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);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));letter-spacing:var(--wcss-accent-sm-letter-spacing, 0.05em);text-transform:uppercase}.accent-xs{font-family:var(--wcss-accent-xs-family, "Good OT"),var(--wcss-accent-xs-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-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));letter-spacing:var(--wcss-accent-xs-letter-spacing, 0.1em);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);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));letter-spacing:var(--wcss-accent-2xs-letter-spacing, 0.1em);text-transform:uppercase}:host{display:block;line-height:0;overflow-y:auto}: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]) .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)}`;
|
|
@@ -114,1507 +114,1648 @@ class AuroElement extends LitElement {
|
|
|
114
114
|
}
|
|
115
115
|
}
|
|
116
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-default-weight, );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-default-emphasized{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-default-emphasized-weight, );letter-spacing:var(--wcss-body-letter-spacing, 0);font-size:var(--wcss-body-default-emphasized-font-size, 1rem);line-height:var(--wcss-body-default-emphasized-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-lg-weight, );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-lg-emphasized{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-lg-emphasized-weight, );letter-spacing:var(--wcss-body-letter-spacing, 0);font-size:var(--wcss-body-lg-emphasized-font-size, 1.125rem);line-height:var(--wcss-body-lg-emphasized-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-sm-weight, );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-sm-emphasized{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-sm-emphasized-weight, );letter-spacing:var(--wcss-body-letter-spacing, 0);font-size:var(--wcss-body-sm-emphasized-font-size, 0.875rem);line-height:var(--wcss-body-sm-emphasized-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-xs-weight, );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-xs-emphasized{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-xs-emphasized-weight, );letter-spacing:var(--wcss-body-letter-spacing, 0);font-size:var(--wcss-body-xs-emphasized-font-size, 0.75rem);line-height:var(--wcss-body-xs-emphasized-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-2xs-weight, );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)}.body-2xs-emphasized{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-2xs-emphasized-weight, );letter-spacing:var(--wcss-body-letter-spacing, 0);font-size:var(--wcss-body-2xs-emphasized-font-size, 0.625rem);line-height:var(--wcss-body-2xs-emphasized-line-height, 0.875rem)}.display-2xl{font-family:var(--wcss-display-2xl-family, "AS Circular"),var(--wcss-display-2xl-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-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));letter-spacing:var(--wcss-display-2xl-letter-spacing, 0)}.display-xl{font-family:var(--wcss-display-xl-family, "AS Circular"),var(--wcss-display-xl-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-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));letter-spacing:var(--wcss-display-xl-letter-spacing, 0)}.display-lg{font-family:var(--wcss-display-lg-family, "AS Circular"),var(--wcss-display-lg-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-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));letter-spacing:var(--wcss-display-lg-letter-spacing, 0)}.display-md{font-family:var(--wcss-display-md-family, "AS Circular"),var(--wcss-display-md-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-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));letter-spacing:var(--wcss-display-md-letter-spacing, 0)}.display-sm{font-family:var(--wcss-display-sm-family, "AS Circular"),var(--wcss-display-sm-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-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));letter-spacing:var(--wcss-display-sm-letter-spacing, 0)}.display-xs{font-family:var(--wcss-display-xs-family, "AS Circular"),var(--wcss-display-xs-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-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));letter-spacing:var(--wcss-display-xs-letter-spacing, 0)}.heading-xl{font-family:var(--wcss-heading-xl-family, "AS Circular"),var(--wcss-heading-xl-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-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));letter-spacing:var(--wcss-heading-xl-letter-spacing, 0)}.heading-lg{font-family:var(--wcss-heading-lg-family, "AS Circular"),var(--wcss-heading-lg-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-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));letter-spacing:var(--wcss-heading-lg-letter-spacing, 0)}.heading-md{font-family:var(--wcss-heading-md-family, "AS Circular"),var(--wcss-heading-md-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-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));letter-spacing:var(--wcss-heading-md-letter-spacing, 0)}.heading-sm{font-family:var(--wcss-heading-sm-family, "AS Circular"),var(--wcss-heading-sm-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-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));letter-spacing:var(--wcss-heading-sm-letter-spacing, 0)}.heading-xs{font-family:var(--wcss-heading-xs-family, "AS Circular"),var(--wcss-heading-xs-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-weight:var(--wcss-heading-xs-weight, 300);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));letter-spacing:var(--wcss-heading-xs-letter-spacing, 0)}.heading-2xs{font-family:var(--wcss-heading-2xs-family, "AS Circular"),var(--wcss-heading-2xs-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-weight:var(--wcss-heading-2xs-weight, 300);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));letter-spacing:var(--wcss-heading-2xs-letter-spacing, 0)}.accent-2xl{font-family:var(--wcss-accent-2xl-family, "Good OT"),var(--wcss-accent-2xl-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-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));letter-spacing:var(--wcss-accent-2xl-letter-spacing, 0.05em);text-transform:uppercase}.accent-xl{font-family:var(--wcss-accent-xl-family, "Good OT"),var(--wcss-accent-xl-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-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));letter-spacing:var(--wcss-accent-xl-letter-spacing, 0.05em);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);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));letter-spacing:var(--wcss-accent-lg-letter-spacing, 0.05em);text-transform:uppercase}.accent-md{font-family:var(--wcss-accent-md-family, "Good OT"),var(--wcss-accent-md-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-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));letter-spacing:var(--wcss-accent-md-letter-spacing, 0.05em);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);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));letter-spacing:var(--wcss-accent-sm-letter-spacing, 0.05em);text-transform:uppercase}.accent-xs{font-family:var(--wcss-accent-xs-family, "Good OT"),var(--wcss-accent-xs-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-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));letter-spacing:var(--wcss-accent-xs-letter-spacing, 0.1em);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);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));letter-spacing:var(--wcss-accent-2xs-letter-spacing, 0.1em);text-transform:uppercase}:host{cursor:pointer;user-select:none;text-overflow:ellipsis;max-width:100dvw}:host .wrapper{display:flex;align-items:center;height:var(--ds-size-400, 2rem);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));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(.active){--ds-auro-menuoption-container-color: var(--ds-basic-color-surface-accent1-muted, #ebfafd)}@media(hover: hover){:host(:hover){--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].active){--ds-auro-menuoption-container-color: var(--ds-basic-color-surface-accent1-muted, #ebfafd)}@media(hover: hover){:host([selected]:hover){--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.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)}@media(hover: hover){:host(:focus:hover){--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.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)}@media(hover: hover){:host([selected]:focus:hover){--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
|
-
|
|
121
|
-
// Copyright (c) Alaska Air. All right reserved. Licensed under the Apache-2.0 license
|
|
122
|
-
// See LICENSE in the project root for license information.
|
|
117
|
+
/* eslint-disable */
|
|
123
118
|
|
|
124
|
-
|
|
119
|
+
class MenuService {
|
|
125
120
|
|
|
126
|
-
|
|
121
|
+
/**
|
|
122
|
+
* PROPERTIES AND GETTERS
|
|
123
|
+
*/
|
|
127
124
|
|
|
128
|
-
|
|
125
|
+
/**
|
|
126
|
+
* Gets the list of registered menu options.
|
|
127
|
+
* @returns {AuroMenuOption[]}
|
|
128
|
+
*/
|
|
129
|
+
get menuOptions() {
|
|
130
|
+
return this._menuOptions;
|
|
131
|
+
}
|
|
129
132
|
|
|
130
|
-
|
|
133
|
+
/**
|
|
134
|
+
* Gets the currently highlighted option.
|
|
135
|
+
* @returns {AuroMenuOption|null}
|
|
136
|
+
*/
|
|
137
|
+
get highlightedOption() {
|
|
138
|
+
return this._menuOptions[this.highlightedIndex] || null;
|
|
139
|
+
}
|
|
131
140
|
|
|
132
141
|
/**
|
|
133
|
-
*
|
|
134
|
-
* @
|
|
135
|
-
* @param {Object} componentClass - The class to register as a custom element.
|
|
136
|
-
* @returns {void}
|
|
142
|
+
* Gets the current value(s) of the selected option(s).
|
|
143
|
+
* @returns {string|string[]|undefined}
|
|
137
144
|
*/
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
}
|
|
145
|
+
get currentValue() {
|
|
146
|
+
const values = (this.selectedOptions || []).map(option => option.value);
|
|
147
|
+
return this.multiSelect ? values : values[0];
|
|
142
148
|
}
|
|
143
149
|
|
|
144
150
|
/**
|
|
145
|
-
*
|
|
146
|
-
* @returns {
|
|
151
|
+
* Gets the label(s) of the currently selected option(s).
|
|
152
|
+
* @returns {string}
|
|
147
153
|
*/
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
__Closest = (el, found = el && el.closest(selector)) =>
|
|
152
|
-
!el || el === document || el === window
|
|
153
|
-
? null // standard .closest() returns null for non-found selectors also
|
|
154
|
-
: found
|
|
155
|
-
? found // found a selector INside this element
|
|
156
|
-
: __Closest(el.getRootNode().host) // recursion!! break out to parent DOM
|
|
157
|
-
) {
|
|
158
|
-
return __Closest(base);
|
|
154
|
+
get currentLabel() {
|
|
155
|
+
const labels = (this.selectedOptions || []).map(option => option.textContent);
|
|
156
|
+
return this.multiSelect ? labels.join(", ") : labels[0] || '';
|
|
159
157
|
}
|
|
160
|
-
/* eslint-enable jsdoc/require-param */
|
|
161
158
|
|
|
162
159
|
/**
|
|
163
|
-
*
|
|
164
|
-
*
|
|
165
|
-
* @
|
|
166
|
-
* @returns {void}
|
|
160
|
+
* Gets the string representation of the current value(s).
|
|
161
|
+
* For multi-select, this is a JSON stringified array.
|
|
162
|
+
* @returns {string|undefined}
|
|
167
163
|
*/
|
|
168
|
-
|
|
169
|
-
const
|
|
170
|
-
const elemTag = elem.tagName.toLowerCase();
|
|
164
|
+
get stringValue() {
|
|
165
|
+
const { currentValue } = this;
|
|
171
166
|
|
|
172
|
-
if (
|
|
173
|
-
|
|
167
|
+
if (Array.isArray(currentValue)) {
|
|
168
|
+
if (currentValue.length > 0) {
|
|
169
|
+
return JSON.stringify(currentValue);
|
|
170
|
+
}
|
|
171
|
+
return undefined;
|
|
172
|
+
}
|
|
173
|
+
|
|
174
|
+
if (typeof currentValue === 'string') {
|
|
175
|
+
if (currentValue.length > 0) {
|
|
176
|
+
return currentValue;
|
|
177
|
+
}
|
|
178
|
+
return undefined;
|
|
174
179
|
}
|
|
180
|
+
|
|
181
|
+
// Future: handle other types here (e.g., number, object, etc.)
|
|
182
|
+
return undefined;
|
|
175
183
|
}
|
|
176
184
|
|
|
177
185
|
/**
|
|
178
|
-
*
|
|
179
|
-
* @
|
|
180
|
-
* @param {String} tagName - The name of the Auro component to check against.
|
|
181
|
-
* @returns {Boolean} - Returns true if the element is the specified Auro component.
|
|
186
|
+
* Gets the key(s) of the currently selected option(s).
|
|
187
|
+
* @returns {string|string[]|undefined}
|
|
182
188
|
*/
|
|
183
|
-
|
|
184
|
-
const
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
return elemTag === tag || elem.hasAttribute(tag);
|
|
189
|
+
get currentKeys() {
|
|
190
|
+
const keys = (this.selectedOptions || []).map(option => option.key);
|
|
191
|
+
return this.multiSelect ? keys : keys[0];
|
|
188
192
|
}
|
|
189
193
|
|
|
190
194
|
/**
|
|
191
|
-
*
|
|
192
|
-
* @returns {String}
|
|
193
|
-
* @private
|
|
195
|
+
* CONSTRUCTOR
|
|
194
196
|
*/
|
|
195
|
-
getSlotText(elem, name) {
|
|
196
|
-
const slot = elem.shadowRoot?.querySelector(`slot[name="${name}"]`);
|
|
197
|
-
const nodes = slot?.assignedNodes({ flatten: true }) || [];
|
|
198
|
-
const text = nodes.map(n => n.textContent?.trim()).join(' ').trim();
|
|
199
|
-
|
|
200
|
-
return text || null;
|
|
201
|
-
}
|
|
202
|
-
}
|
|
203
197
|
|
|
204
|
-
|
|
205
|
-
|
|
198
|
+
/**
|
|
199
|
+
* Creates a new MenuService instance.
|
|
200
|
+
* @param {Object} options - The options object.
|
|
201
|
+
* @param {AuroMenu} options.host - The host element that this service will control. Required.
|
|
202
|
+
* @throws {Error} If the host is not provided.
|
|
203
|
+
*/
|
|
204
|
+
constructor({ host } = {}) {
|
|
206
205
|
|
|
206
|
+
// Ensure a host was passed
|
|
207
|
+
if (!host) {
|
|
208
|
+
throw new Error("MenuService requires a host element.");
|
|
209
|
+
}
|
|
207
210
|
|
|
208
|
-
|
|
211
|
+
// Attach the service to the host
|
|
212
|
+
this.host = host;
|
|
213
|
+
this.host.addController(this);
|
|
209
214
|
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
215
|
+
// Set default properties
|
|
216
|
+
this.size = undefined;
|
|
217
|
+
this.shape = undefined;
|
|
218
|
+
this.noCheckmark = undefined;
|
|
219
|
+
this.disabled = undefined;
|
|
220
|
+
this.matchWord = undefined;
|
|
221
|
+
this.multiSelect = undefined;
|
|
222
|
+
this.allowDeselect = undefined;
|
|
223
|
+
this.selectAllMatchingOptions = undefined;
|
|
219
224
|
|
|
220
|
-
|
|
221
|
-
result += version.replace(/[.]/g, '_');
|
|
225
|
+
this.highlightedIndex = -1;
|
|
222
226
|
|
|
223
|
-
|
|
227
|
+
this._menuOptions = [];
|
|
228
|
+
this._subscribers = [];
|
|
229
|
+
this.internalUpdateInProgress = false;
|
|
230
|
+
this.selectedOptions = [];
|
|
231
|
+
this._pendingValue = null;
|
|
232
|
+
this._pendingRetryScheduled = false;
|
|
233
|
+
this._pendingRetryCount = 0;
|
|
224
234
|
}
|
|
225
235
|
|
|
226
236
|
/**
|
|
227
|
-
*
|
|
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.
|
|
237
|
+
* PROPERTY SYNCING
|
|
231
238
|
*/
|
|
232
|
-
generateTag(baseName, version, tagClass) {
|
|
233
|
-
const elementName = this.generateElementName(baseName, version);
|
|
234
|
-
const tag = literal`${unsafeStatic(elementName)}`;
|
|
235
239
|
|
|
236
|
-
|
|
237
|
-
|
|
240
|
+
/**
|
|
241
|
+
* Handles host updates.
|
|
242
|
+
* This is a lit reactive lifecycle method.
|
|
243
|
+
* This comes from the Lit controller interface provided by adding this service as a controller to the host.
|
|
244
|
+
* See constructor for `this.host.addController(this)`
|
|
245
|
+
* You can read more about Lit reactive controllers here: https://lit.dev/docs/composition/controllers/
|
|
246
|
+
*/
|
|
247
|
+
hostUpdated() {
|
|
248
|
+
|
|
249
|
+
// Reset selection if multiSelect mode changes
|
|
250
|
+
if (this.host.multiSelect !== this.multiSelect) {
|
|
251
|
+
this.selectedOptions = [];
|
|
238
252
|
}
|
|
239
253
|
|
|
240
|
-
|
|
254
|
+
// Update properties on host update
|
|
255
|
+
this.setProperties({
|
|
256
|
+
size: this.host.size,
|
|
257
|
+
shape: this.host.shape,
|
|
258
|
+
noCheckmark: this.host.noCheckmark,
|
|
259
|
+
disabled: this.host.disabled,
|
|
260
|
+
matchWord: this.host.matchWord,
|
|
261
|
+
multiSelect: this.host.multiSelect,
|
|
262
|
+
allowDeselect: this.host.allowDeselect,
|
|
263
|
+
selectAllMatchingOptions: this.host.selectAllMatchingOptions
|
|
264
|
+
});
|
|
241
265
|
}
|
|
242
|
-
}
|
|
243
|
-
|
|
244
|
-
class p{registerComponent(t,a){customElements.get(t)||customElements.define(t,class extends a{});}closestElement(t,a=this,e=(a,s=a&&a.closest(t))=>a&&a!==document&&a!==window?s||e(a.getRootNode().host):null){return e(a)}handleComponentTagRename(t,a){const e=a.toLowerCase();t.tagName.toLowerCase()!==e&&t.setAttribute(e,true);}elementMatch(t,a){const e=a.toLowerCase();return t.tagName.toLowerCase()===e||t.hasAttribute(e)}getSlotText(t,a){const e=t.shadowRoot?.querySelector(`slot[name="${a}"]`);return (e?.assignedNodes({flatten:true})||[]).map(t=>t.textContent?.trim()).join(" ").trim()||null}}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>',g='<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" style="min-width:100%;height:auto;fill:currentColor" viewBox="0 0 142 138" part="svg"><title id="tail-DEFAULT__title">Airplane tail default image with light gray color</title><path fill="url(#paint0_linear_9225_2069)" fill-rule="evenodd" d="M124.093 14.665a3.26 3.26 0 0 1 3.208 3.829L101.097 119.85c-.47 1.087-2.211 3.398-5.692 3.471l-.106.001-80.65.013A659230 659230 0 0 1 99.08 17.412c1.214-1.497 3.275-2.722 5.372-2.747z" clip-rule="evenodd"/><defs><linearGradient id="paint0_linear_9225_2069" x1="114.823" x2="60.061" y1="14.665" y2="123.335" gradientUnits="userSpaceOnUse"><stop offset=".5" stop-color="#707984"/><stop offset=".5" stop-color="#646E7B"/></linearGradient></defs></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 f=new Map,w=(t,a={})=>{const e=a.responseParser||(t=>t.text());return f.has(t)||f.set(t,fetch(t).then(e)),f.get(t)};var z=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;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;line-height:var(--ds-auro-icon-size)}.svgWrapper{height:var(--ds-auro-icon-size);width:var(--ds-auro-icon-size)}.svgWrapper [part=svg]{display:flex}.labelWrapper{margin-left:var(--ds-size-50, .25rem)}.labelWrapper ::slotted(*){line-height:inherit!important}
|
|
245
|
-
`;class y extends m{constructor(){super(),this._initializeDefaults();}_initializeDefaults(){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 z}async fetchIcon(t,a){let e="";e="logos"===t?await w(`${this.uri}/${t}/${a}.svg`):await w(`${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=this.name?.startsWith("tail-")?g:u;this.svg=(new DOMParser).parseFromString(t,"text/html").body.querySelector("svg");}}}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 M=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 _=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 k extends y{constructor(){super(),this._initializeDefaults();}_initializeDefaults(){this.variant=void 0,this.uri="https://cdn.jsdelivr.net/npm/@alaskaairux/icons@latest/dist",this.runtimeUtils=new p;}static get properties(){return {...y.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 [y.styles,M,z,_]}static register(t="auro-icon"){p.prototype.registerComponent(t,k);}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
266
|
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
+
/**
|
|
268
|
+
* Handles host disconnection and memory cleanup.
|
|
269
|
+
*/
|
|
270
|
+
hostDisconnected() {
|
|
271
|
+
this._subscribers = [];
|
|
272
|
+
this._menuOptions = [];
|
|
273
|
+
this._pendingValue = null;
|
|
274
|
+
this._pendingRetryScheduled = false;
|
|
275
|
+
this._pendingRetryCount = 0;
|
|
276
|
+
}
|
|
267
277
|
|
|
268
|
-
|
|
278
|
+
/**
|
|
279
|
+
* Sets a property value if it exists on the instance and the value has changed.
|
|
280
|
+
* @param {string} property
|
|
281
|
+
* @param {any} value
|
|
282
|
+
*/
|
|
283
|
+
setProperty(property, value) {
|
|
269
284
|
|
|
270
|
-
|
|
285
|
+
// Only update if we are tracking the property in this service
|
|
286
|
+
if (this.hasOwnProperty(property)) {
|
|
271
287
|
|
|
272
|
-
//
|
|
273
|
-
|
|
288
|
+
// Check if the value has changed
|
|
289
|
+
const valueChanged = this[property] !== value;
|
|
274
290
|
|
|
291
|
+
// Update and notify if changed
|
|
292
|
+
if (valueChanged) {
|
|
293
|
+
this[property] = value;
|
|
294
|
+
this.notify({ property, value });
|
|
295
|
+
}
|
|
296
|
+
}
|
|
297
|
+
}
|
|
275
298
|
|
|
276
|
-
/**
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
bubbles: true,
|
|
285
|
-
cancelable: false,
|
|
286
|
-
composed: true
|
|
287
|
-
};
|
|
288
|
-
|
|
289
|
-
if (detail !== null) {
|
|
290
|
-
eventConfig.detail = detail;
|
|
299
|
+
/**
|
|
300
|
+
* Sets multiple properties on the instance.
|
|
301
|
+
* @param {Object} properties - Key-value pairs of properties to set.
|
|
302
|
+
*/
|
|
303
|
+
setProperties(properties) {
|
|
304
|
+
for (const [key, value] of Object.entries(properties)) {
|
|
305
|
+
this.setProperty(key, value);
|
|
306
|
+
}
|
|
291
307
|
}
|
|
292
308
|
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
// Copyright (c) 2021 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
|
|
297
|
-
// See LICENSE in the project root for license information.
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
let menuOptionIdCounter = 0;
|
|
301
|
-
|
|
302
|
-
/**
|
|
303
|
-
* The `auro-menuoption` element provides users a way to define a menu option.
|
|
304
|
-
* @customElement auro-menuoption
|
|
305
|
-
*
|
|
306
|
-
* @slot default - The default slot for the menu option text.
|
|
307
|
-
*
|
|
308
|
-
* @event auroMenuOption-mouseover - Notifies that this option has been hovered over.
|
|
309
|
-
*/
|
|
310
|
-
class AuroMenuOption extends AuroElement {
|
|
309
|
+
/**
|
|
310
|
+
* MENU OPTION HIGHLIGHTING
|
|
311
|
+
*/
|
|
311
312
|
|
|
312
313
|
/**
|
|
313
|
-
*
|
|
314
|
-
* @param {string} [name="auro-menuoption"] - The name of the element that you want to register.
|
|
315
|
-
*
|
|
316
|
-
* @example
|
|
317
|
-
* AuroMenuOption.register("custom-menuoption") // this will register this element to <custom-menuoption/>
|
|
318
|
-
*
|
|
314
|
+
* Highlights the next active option in the menu.
|
|
319
315
|
*/
|
|
320
|
-
|
|
321
|
-
|
|
316
|
+
highlightNext() {
|
|
317
|
+
this.moveHighlightedOption("next");
|
|
322
318
|
}
|
|
323
319
|
|
|
324
320
|
/**
|
|
325
|
-
*
|
|
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.
|
|
321
|
+
* Highlights the previous active option in the menu.
|
|
328
322
|
*/
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
!this.disabled &&
|
|
332
|
-
!this.hasAttribute('static');
|
|
323
|
+
highlightPrevious() {
|
|
324
|
+
this.moveHighlightedOption("previous");
|
|
333
325
|
}
|
|
334
326
|
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
327
|
+
/**
|
|
328
|
+
* Moves the highlighted option in the specified direction.
|
|
329
|
+
* @param {string} direction - The direction to move the highlight ("next" or "previous").
|
|
330
|
+
*/
|
|
331
|
+
moveHighlightedOption(direction) {
|
|
339
332
|
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
*/
|
|
343
|
-
this.shape = undefined;
|
|
333
|
+
// Get the active options
|
|
334
|
+
const activeOptions = this._menuOptions.filter(option => option.isActive);
|
|
344
335
|
|
|
345
|
-
|
|
346
|
-
|
|
347
|
-
*/
|
|
348
|
-
this.size = undefined;
|
|
336
|
+
// Get the currently active option
|
|
337
|
+
const currentActiveOption = activeOptions[activeOptions.indexOf(this.highlightedOption)];
|
|
349
338
|
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
339
|
+
// Determine the new index based on the currently active option and direction
|
|
340
|
+
let newIndex = currentActiveOption
|
|
341
|
+
? direction === "previous"
|
|
342
|
+
? activeOptions.indexOf(currentActiveOption) - 1
|
|
343
|
+
: activeOptions.indexOf(currentActiveOption) + 1
|
|
344
|
+
: direction === "previous"
|
|
345
|
+
? activeOptions.length - 1
|
|
346
|
+
: 0;
|
|
355
347
|
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
this.disabled = false;
|
|
359
|
-
this.noMatch = false;
|
|
348
|
+
// Wrap around the index if needed
|
|
349
|
+
newIndex = newIndex < 0 ? activeOptions.length - 1 : newIndex >= activeOptions.length ? 0 : newIndex;
|
|
360
350
|
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
351
|
+
// Get the new active option and set it as highlighted
|
|
352
|
+
const newActiveOption = activeOptions[newIndex];
|
|
353
|
+
this.setHighlightedOption(newActiveOption);
|
|
354
|
+
}
|
|
365
355
|
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
356
|
+
/**
|
|
357
|
+
* Sets the highlighted index to the specified option.
|
|
358
|
+
* @param {AuroMenuOption} option - The option to highlight.
|
|
359
|
+
*/
|
|
360
|
+
setHighlightedOption(option) {
|
|
369
361
|
|
|
370
|
-
|
|
371
|
-
* @private
|
|
372
|
-
*/
|
|
373
|
-
this.handleMenuChange = this.handleMenuChange.bind(this);
|
|
374
|
-
}
|
|
362
|
+
if (!option) return;
|
|
375
363
|
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
...super.properties,
|
|
364
|
+
// Get the index of the option to highlight
|
|
365
|
+
const index = this._menuOptions.indexOf(option);
|
|
379
366
|
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
*/
|
|
383
|
-
disabled: {
|
|
384
|
-
type: Boolean,
|
|
385
|
-
reflect: true
|
|
386
|
-
},
|
|
367
|
+
// Update highlighted index
|
|
368
|
+
this.highlightedIndex = index;
|
|
387
369
|
|
|
388
|
-
|
|
389
|
-
|
|
390
|
-
*/
|
|
391
|
-
event: {
|
|
392
|
-
type: String,
|
|
393
|
-
reflect: true
|
|
394
|
-
},
|
|
370
|
+
// Notify subscribers of highlight change
|
|
371
|
+
this.notify({ type: 'highlightChange', option, index: this.highlightedIndex });
|
|
395
372
|
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
layout: {
|
|
400
|
-
type: String
|
|
401
|
-
},
|
|
373
|
+
// Dispatch the change event
|
|
374
|
+
this.dispatchChangeEvent('auroMenu-activatedOption', option);
|
|
375
|
+
}
|
|
402
376
|
|
|
403
|
-
|
|
404
|
-
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
|
|
409
|
-
|
|
377
|
+
/**
|
|
378
|
+
* Sets the highlighted option to the option at the specified index if it exists.
|
|
379
|
+
* @param {number} index
|
|
380
|
+
*/
|
|
381
|
+
setHighlightedIndex(index) {
|
|
382
|
+
const option = this._menuOptions[index] || null;
|
|
383
|
+
this.setHighlightedOption(option);
|
|
384
|
+
}
|
|
410
385
|
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
386
|
+
/**
|
|
387
|
+
* Selects the currently highlighted option.
|
|
388
|
+
*/
|
|
389
|
+
selectHighlightedOption() {
|
|
390
|
+
if (this.highlightedOption) {
|
|
391
|
+
this.toggleOption(this.highlightedOption);
|
|
392
|
+
}
|
|
393
|
+
}
|
|
418
394
|
|
|
419
|
-
|
|
420
|
-
|
|
421
|
-
|
|
422
|
-
matchWord: {
|
|
423
|
-
type: String,
|
|
424
|
-
state: true
|
|
425
|
-
},
|
|
395
|
+
/**
|
|
396
|
+
* SELECTION AND DESELECTION METHODS
|
|
397
|
+
*/
|
|
426
398
|
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
},
|
|
399
|
+
/**
|
|
400
|
+
* Selects one or more options in a batch operation
|
|
401
|
+
* @param {AuroMenuOption|AuroMenuOption[]} options - Single option or array of options to select
|
|
402
|
+
*/
|
|
403
|
+
selectOptions(options) {
|
|
404
|
+
let optionsToSelect = Array.isArray(options) ? options : [options];
|
|
434
405
|
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
*/
|
|
438
|
-
noMatch: {
|
|
439
|
-
type: Boolean,
|
|
440
|
-
reflect: true,
|
|
441
|
-
attribute: 'nomatch'
|
|
442
|
-
},
|
|
406
|
+
// Filter out options that are inactive
|
|
407
|
+
optionsToSelect = optionsToSelect.filter(option => option.isActive);
|
|
443
408
|
|
|
444
|
-
|
|
445
|
-
* Specifies that an option is selected.
|
|
446
|
-
*/
|
|
447
|
-
selected: {
|
|
448
|
-
type: Boolean,
|
|
449
|
-
reflect: true
|
|
450
|
-
},
|
|
409
|
+
if (!optionsToSelect.length) return;
|
|
451
410
|
|
|
452
|
-
|
|
453
|
-
|
|
454
|
-
|
|
455
|
-
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
},
|
|
411
|
+
if (this.multiSelect) {
|
|
412
|
+
this.selectedOptions = [...(this.selectedOptions || []), ...optionsToSelect];
|
|
413
|
+
} else {
|
|
414
|
+
// In single select mode, only take the last option
|
|
415
|
+
this.selectedOptions = [optionsToSelect[optionsToSelect.length - 1]];
|
|
416
|
+
}
|
|
459
417
|
|
|
460
|
-
|
|
461
|
-
* Specifies the value to be sent to a server.
|
|
462
|
-
*/
|
|
463
|
-
value: {
|
|
464
|
-
type: String,
|
|
465
|
-
reflect: true
|
|
466
|
-
},
|
|
467
|
-
};
|
|
418
|
+
this.stageUpdate();
|
|
468
419
|
}
|
|
469
420
|
|
|
470
|
-
|
|
471
|
-
|
|
472
|
-
|
|
473
|
-
|
|
474
|
-
|
|
475
|
-
];
|
|
476
|
-
}
|
|
421
|
+
/**
|
|
422
|
+
* Deselects one or more options in a batch operation
|
|
423
|
+
* @param {AuroMenuOption|AuroMenuOption[]} options - Single option or array of options to deselect
|
|
424
|
+
*/
|
|
425
|
+
deselectOptions(options) {
|
|
426
|
+
const optionsToDeselect = Array.isArray(options) ? options : [options];
|
|
477
427
|
|
|
478
|
-
|
|
479
|
-
super.connectedCallback();
|
|
428
|
+
if (!optionsToDeselect.length) return;
|
|
480
429
|
|
|
481
|
-
//
|
|
482
|
-
|
|
483
|
-
this.
|
|
430
|
+
// Check if deselection should be prevented
|
|
431
|
+
const shouldPreventDeselect = !this.allowDeselect && !this.multiSelect;
|
|
432
|
+
const isOnlySelectedOption = this.selectedOptions.length === 1 && optionsToDeselect.includes(this.selectedOptions[0]);
|
|
484
433
|
|
|
485
|
-
//
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
434
|
+
// Prevent deselecting the only selected option if not allowed
|
|
435
|
+
if (shouldPreventDeselect && isOnlySelectedOption) {
|
|
436
|
+
optionsToDeselect.forEach(option => {
|
|
437
|
+
option.selected = true;
|
|
438
|
+
});
|
|
439
|
+
this.dispatchChangeEvent('auroMenu-deselectPrevented', {
|
|
440
|
+
values: optionsToDeselect
|
|
441
|
+
});
|
|
442
|
+
return;
|
|
443
|
+
}
|
|
491
444
|
|
|
492
|
-
|
|
493
|
-
|
|
494
|
-
|
|
495
|
-
|
|
496
|
-
|
|
497
|
-
|
|
498
|
-
|
|
499
|
-
|
|
500
|
-
|
|
501
|
-
|
|
502
|
-
|
|
503
|
-
|
|
504
|
-
|
|
445
|
+
const optionsSet = new Set(optionsToDeselect);
|
|
446
|
+
this.selectedOptions = (this.selectedOptions || [])
|
|
447
|
+
.filter(opt => !optionsSet.has(opt));
|
|
448
|
+
|
|
449
|
+
this.stageUpdate();
|
|
450
|
+
}
|
|
451
|
+
|
|
452
|
+
/**
|
|
453
|
+
* Selects a single option.
|
|
454
|
+
* @param {AuroMenuOption} option
|
|
455
|
+
*/
|
|
456
|
+
selectOption(option) {
|
|
457
|
+
this.selectOptions(option);
|
|
458
|
+
}
|
|
459
|
+
|
|
460
|
+
/**
|
|
461
|
+
* Deselects a single option.
|
|
462
|
+
* @param {AuroMenuOption} option
|
|
463
|
+
*/
|
|
464
|
+
deselectOption(option) {
|
|
465
|
+
this.deselectOptions(option);
|
|
466
|
+
}
|
|
467
|
+
|
|
468
|
+
/**
|
|
469
|
+
* Toggles the selection state of a single option.
|
|
470
|
+
* @param {AuroMenuOption} option
|
|
471
|
+
*/
|
|
472
|
+
toggleOption(option) {
|
|
473
|
+
if (option.selected) {
|
|
474
|
+
this.deselectOption(option);
|
|
475
|
+
} else {
|
|
476
|
+
this.selectOption(option);
|
|
505
477
|
}
|
|
506
478
|
}
|
|
507
479
|
|
|
508
|
-
|
|
509
|
-
|
|
510
|
-
|
|
480
|
+
/**
|
|
481
|
+
* Selects options based on their value(s) when compared to a passed value or values.
|
|
482
|
+
* Value or values are normalized to an array of strings that can be matched to option keys.
|
|
483
|
+
* @param {string|number|Array<string|number>} value - The value(s) to select.
|
|
484
|
+
*/
|
|
485
|
+
selectByValue(value) {
|
|
486
|
+
const isEmptyValue = value === undefined ||
|
|
487
|
+
value === null ||
|
|
488
|
+
(Array.isArray(value) && value.length === 0) ||
|
|
489
|
+
(typeof value === 'string' && value.trim() === '');
|
|
511
490
|
|
|
512
|
-
//
|
|
513
|
-
if (
|
|
514
|
-
|
|
515
|
-
this.
|
|
491
|
+
// Early exit for invalid/empty values
|
|
492
|
+
if (isEmptyValue) {
|
|
493
|
+
this.selectedOptions.forEach(opt => opt.selected = false);
|
|
494
|
+
this.selectedOptions = [];
|
|
495
|
+
return;
|
|
516
496
|
}
|
|
517
497
|
|
|
518
|
-
|
|
519
|
-
|
|
498
|
+
// If an internal update cycle is still in progress, defer value application
|
|
499
|
+
// rather than dropping it.
|
|
500
|
+
if (this.internalUpdateInProgress || this.host.internalUpdateInProgress) {
|
|
501
|
+
this.queuePendingValue(value);
|
|
502
|
+
return;
|
|
503
|
+
}
|
|
520
504
|
|
|
521
|
-
|
|
522
|
-
|
|
523
|
-
|
|
524
|
-
|
|
525
|
-
|
|
526
|
-
|
|
527
|
-
|
|
505
|
+
// Normalize values to array of strings
|
|
506
|
+
const normalizedValues = this._getNormalizedValues(value);
|
|
507
|
+
|
|
508
|
+
// Validate for single-select mode
|
|
509
|
+
let validatedValues = normalizedValues;
|
|
510
|
+
if (normalizedValues.length > 1 && !this.multiSelect) {
|
|
511
|
+
console.warn("MenuService - Multiple values provided for single-select menu. Only the first value will be selected.");
|
|
512
|
+
validatedValues = [normalizedValues[0]];
|
|
513
|
+
}
|
|
514
|
+
|
|
515
|
+
if (this._menuOptions.length === 0) {
|
|
516
|
+
this.queuePendingValue(value);
|
|
517
|
+
return;
|
|
518
|
+
}
|
|
519
|
+
|
|
520
|
+
// Find matching options by comparing available options to validated values
|
|
521
|
+
const trackedKeys = new Set();
|
|
522
|
+
const optionsToSelect = this._menuOptions.filter(option => {
|
|
523
|
+
const passesFilter = validatedValues.includes(option.key);
|
|
524
|
+
const alreadyTracked = trackedKeys.has(option.key);
|
|
525
|
+
const isActive = option.isActive;
|
|
526
|
+
|
|
527
|
+
trackedKeys.add(option.key);
|
|
528
|
+
|
|
529
|
+
// Include the option in the options to be selected if it passes the filter check and
|
|
530
|
+
// either hasn't been tracked yet or selectAllMatchingOptions is true
|
|
531
|
+
return isActive && passesFilter && (!alreadyTracked || (alreadyTracked && this.selectAllMatchingOptions));
|
|
528
532
|
});
|
|
529
|
-
}
|
|
530
533
|
|
|
531
|
-
|
|
532
|
-
|
|
534
|
+
// Handle no matches: clear existing selection, but do not dispatch an intermediate
|
|
535
|
+
// undefined value that can overwrite the host value in parent components.
|
|
536
|
+
if (!optionsToSelect.length) {
|
|
537
|
+
const hasUnresolvedKeys = this._menuOptions.some((option) => option.isActive && option.key == null);
|
|
533
538
|
|
|
534
|
-
|
|
535
|
-
|
|
539
|
+
if (hasUnresolvedKeys) {
|
|
540
|
+
this.queuePendingValue(value);
|
|
541
|
+
return;
|
|
542
|
+
}
|
|
536
543
|
|
|
537
|
-
|
|
538
|
-
this.setAttribute('aria-selected', this.selected.toString());
|
|
544
|
+
this.clearPendingValue();
|
|
539
545
|
|
|
540
|
-
|
|
541
|
-
|
|
542
|
-
this.menuService[this.selected ? 'selectOption' : 'deselectOption'](this);
|
|
546
|
+
if (this.selectedOptions.length > 0) {
|
|
547
|
+
this.selectedOptions = [];
|
|
543
548
|
}
|
|
544
|
-
}
|
|
545
549
|
|
|
546
|
-
|
|
547
|
-
|
|
548
|
-
|
|
549
|
-
|
|
550
|
-
|
|
550
|
+
// Always notify so the host resets any stale invalid value, even when
|
|
551
|
+
// selectedOptions was already empty (e.g. double-clicking set-invalid).
|
|
552
|
+
this.stageUpdate({ reason: 'no-match' });
|
|
553
|
+
|
|
554
|
+
// Dispatch failure event if no matches found
|
|
555
|
+
if (validatedValues.length) {
|
|
556
|
+
this.dispatchChangeEvent('auroMenu-selectValueFailure', {
|
|
557
|
+
message: 'No matching options found for the provided value(s).',
|
|
558
|
+
values: validatedValues
|
|
559
|
+
});
|
|
551
560
|
}
|
|
552
|
-
}
|
|
553
561
|
|
|
554
|
-
|
|
555
|
-
this.updateActiveClasses();
|
|
562
|
+
return;
|
|
556
563
|
}
|
|
557
564
|
|
|
558
|
-
|
|
559
|
-
if (changedProperties.has('matchWord')) {
|
|
560
|
-
this.updateTextHighlight();
|
|
561
|
-
}
|
|
565
|
+
this.clearPendingValue();
|
|
562
566
|
|
|
563
|
-
|
|
564
|
-
|
|
565
|
-
// undefined. When a framework (e.g. Svelte, React) inserts the element
|
|
566
|
-
// before setting its value property, connectedCallback skips key
|
|
567
|
-
// assignment because both attributes are null at that point. The Lit
|
|
568
|
-
// property default for `key` is undefined (not null), so strict
|
|
569
|
-
// === null would miss the case and the fallback would never run.
|
|
570
|
-
if (changedProperties.has('value') && this.key == null) { // eslint-disable-line eqeqeq, no-eq-null
|
|
571
|
-
this.key = this.value;
|
|
567
|
+
if (this.optionsArraysMatch(optionsToSelect, this.selectedOptions)) {
|
|
568
|
+
return;
|
|
572
569
|
}
|
|
570
|
+
|
|
571
|
+
// Apply programmatic selection as a single transaction and emit one final state.
|
|
572
|
+
this.selectedOptions = optionsToSelect;
|
|
573
|
+
this.stageUpdate();
|
|
573
574
|
}
|
|
574
575
|
|
|
575
|
-
|
|
576
|
-
|
|
577
|
-
|
|
578
|
-
|
|
576
|
+
/**
|
|
577
|
+
* Queues a pending value and schedules a bounded retry.
|
|
578
|
+
* @param {string|number|Array<string|number>} value - The value to retry.
|
|
579
|
+
*/
|
|
580
|
+
queuePendingValue(value) {
|
|
581
|
+
this._pendingValue = value;
|
|
582
|
+
|
|
583
|
+
if (this._pendingRetryScheduled || this._pendingRetryCount >= 5) {
|
|
584
|
+
return;
|
|
579
585
|
}
|
|
586
|
+
|
|
587
|
+
this._pendingRetryScheduled = true;
|
|
588
|
+
this._pendingRetryCount += 1;
|
|
589
|
+
|
|
590
|
+
setTimeout(() => {
|
|
591
|
+
this._pendingRetryScheduled = false;
|
|
592
|
+
|
|
593
|
+
if (this._pendingValue == null) {
|
|
594
|
+
return;
|
|
595
|
+
}
|
|
596
|
+
|
|
597
|
+
const pendingValue = this._pendingValue;
|
|
598
|
+
this.selectByValue(pendingValue);
|
|
599
|
+
}, 0);
|
|
580
600
|
}
|
|
581
601
|
|
|
582
602
|
/**
|
|
583
|
-
*
|
|
584
|
-
* This function enables click and mouse enter events to trigger selection and highlighting logic.
|
|
603
|
+
* Clears pending retry state.
|
|
585
604
|
*/
|
|
586
|
-
|
|
587
|
-
this.
|
|
588
|
-
this.
|
|
605
|
+
clearPendingValue() {
|
|
606
|
+
this._pendingValue = null;
|
|
607
|
+
this._pendingRetryScheduled = false;
|
|
608
|
+
this._pendingRetryCount = 0;
|
|
589
609
|
}
|
|
590
610
|
|
|
591
611
|
/**
|
|
592
|
-
*
|
|
593
|
-
* This method enables the option to participate in menu selection and highlighting logic.
|
|
594
|
-
* @param {Object} service - The menu service instance to attach to.
|
|
612
|
+
* Resets the selected options to an empty array.
|
|
595
613
|
*/
|
|
596
|
-
|
|
597
|
-
|
|
598
|
-
|
|
614
|
+
reset() {
|
|
615
|
+
const previousOptions = [...this.selectedOptions];
|
|
616
|
+
previousOptions.forEach(opt => opt.selected = false);
|
|
617
|
+
this.selectedOptions = [];
|
|
618
|
+
|
|
619
|
+
// Single update after clearing all
|
|
620
|
+
if (previousOptions.length) {
|
|
621
|
+
this.stageUpdate();
|
|
599
622
|
}
|
|
600
|
-
this.menuService = service;
|
|
601
|
-
this.menuService.addMenuOption(this);
|
|
602
|
-
this.menuService.subscribe(this.handleMenuChange);
|
|
603
623
|
}
|
|
604
624
|
|
|
605
625
|
/**
|
|
606
|
-
*
|
|
607
|
-
* This function synchronizes the option's properties and selection/highlight state with menu events.
|
|
608
|
-
* @param {Object} event - The event object from the menu service.
|
|
626
|
+
* SUBSCRIPTION, NOTIFICATION AND EVENT DISPATCH METHODS
|
|
609
627
|
*/
|
|
610
|
-
handleMenuChange(event) {
|
|
611
|
-
|
|
612
|
-
// Ignore events without a type or property
|
|
613
|
-
if (!event || (!event.type && !event.property)) {
|
|
614
|
-
return;
|
|
615
|
-
}
|
|
616
|
-
|
|
617
|
-
// Update reactive properties based on event type
|
|
618
|
-
if (event.property && Object.keys(AuroMenuOption.properties).includes(event.property)) {
|
|
619
|
-
this[event.property] = event.value;
|
|
620
|
-
}
|
|
621
|
-
|
|
622
|
-
// Handle highlight changes
|
|
623
|
-
if (event.type === 'highlightChange') {
|
|
624
|
-
const isActive = event.option === this;
|
|
625
|
-
this.active = isActive;
|
|
626
|
-
this.updateActiveClasses();
|
|
627
|
-
}
|
|
628
628
|
|
|
629
|
-
|
|
630
|
-
|
|
631
|
-
|
|
632
|
-
|
|
629
|
+
/**
|
|
630
|
+
* Subscribes a callback to menu service events.
|
|
631
|
+
* @param {Function} callback - The callback to invoke on events.
|
|
632
|
+
*/
|
|
633
|
+
subscribe(callback) {
|
|
634
|
+
this._subscribers.push(callback);
|
|
633
635
|
}
|
|
634
636
|
|
|
635
637
|
/**
|
|
636
|
-
*
|
|
637
|
-
*
|
|
638
|
-
* @param {boolean} isSelected - Whether the option should be marked as selected.
|
|
638
|
+
* Remove a previously subscribed callback from menu service events.
|
|
639
|
+
* @param {Function} callback
|
|
639
640
|
*/
|
|
640
|
-
|
|
641
|
-
this.
|
|
642
|
-
this.selected = isSelected;
|
|
643
|
-
|
|
644
|
-
// Fire custom event if selected
|
|
645
|
-
if (isSelected) {
|
|
646
|
-
this.handleCustomEvent();
|
|
647
|
-
}
|
|
648
|
-
|
|
649
|
-
setTimeout(() => {
|
|
650
|
-
this.internalUpdateInProgress = false;
|
|
651
|
-
}, 0);
|
|
641
|
+
unsubscribe(callback) {
|
|
642
|
+
this._subscribers = this._subscribers.filter(cb => cb !== callback);
|
|
652
643
|
}
|
|
653
644
|
|
|
654
645
|
/**
|
|
655
|
-
*
|
|
656
|
-
* This function updates whether the option is currently selected.
|
|
657
|
-
* @param {boolean} isSelected - Whether the option should be marked as selected.
|
|
658
|
-
* @deprecated Simply modify the `selected` property directly instead.
|
|
646
|
+
* Stages an update to notify subscribers of state and value changes.
|
|
659
647
|
*/
|
|
660
|
-
|
|
661
|
-
this.
|
|
648
|
+
stageUpdate(meta = {}) {
|
|
649
|
+
this.notifyStateChange(meta);
|
|
650
|
+
this.notifyValueChange(meta);
|
|
662
651
|
}
|
|
663
652
|
|
|
664
653
|
/**
|
|
665
|
-
*
|
|
666
|
-
*
|
|
667
|
-
* @param {
|
|
668
|
-
* @deprecated Simply modify the `active` property directly instead.
|
|
654
|
+
* Notifies subscribers of a menu service event.
|
|
655
|
+
* All notifications are sent to all subscribers.
|
|
656
|
+
* @param {string} event - The event to send to subscribers.
|
|
669
657
|
*/
|
|
670
|
-
|
|
671
|
-
|
|
672
|
-
// Set active state
|
|
673
|
-
this.active = isActive;
|
|
674
|
-
this.updateActiveClasses();
|
|
658
|
+
notify(event) {
|
|
659
|
+
this._subscribers.forEach(callback => callback(event));
|
|
675
660
|
}
|
|
676
661
|
|
|
677
662
|
/**
|
|
678
|
-
*
|
|
679
|
-
* This function adds or removes the 'active' class to visually indicate the option's active status.
|
|
680
|
-
* @private
|
|
663
|
+
* Notifies subscribers of a state change (selected options has changed).
|
|
681
664
|
*/
|
|
682
|
-
|
|
683
|
-
|
|
684
|
-
|
|
685
|
-
|
|
665
|
+
notifyStateChange(meta = {}) {
|
|
666
|
+
this.notify({
|
|
667
|
+
type: 'stateChange',
|
|
668
|
+
selectedOptions: this.selectedOptions,
|
|
669
|
+
...meta
|
|
670
|
+
});
|
|
686
671
|
}
|
|
687
672
|
|
|
688
|
-
|
|
689
673
|
/**
|
|
690
|
-
*
|
|
691
|
-
* This function highlights matching text segments and manages nested spacers for display formatting.
|
|
692
|
-
* @private
|
|
674
|
+
* Notifies subscribers of a value change (current value has changed).
|
|
693
675
|
*/
|
|
694
|
-
|
|
695
|
-
|
|
696
|
-
// Regex for matchWord if needed
|
|
697
|
-
let regexWord = null;
|
|
698
|
-
|
|
699
|
-
if (this.matchWord && this.matchWord.length) {
|
|
700
|
-
const escapedWord = this.matchWord.replace(/[.*+?^${}()|[\]\\]/gu, '\\$&');
|
|
701
|
-
regexWord = new RegExp(escapedWord, 'giu');
|
|
702
|
-
}
|
|
703
|
-
|
|
704
|
-
// Update text highlighting if matchWord changed
|
|
705
|
-
if (regexWord &&
|
|
706
|
-
this.isActive && !this.hasAttribute('persistent')) {
|
|
707
|
-
const nested = this.querySelectorAll('.nestingSpacer');
|
|
676
|
+
notifyValueChange(meta = {}) {
|
|
708
677
|
|
|
709
|
-
|
|
710
|
-
|
|
711
|
-
|
|
712
|
-
|
|
678
|
+
// Prepare details for the event
|
|
679
|
+
const details = {
|
|
680
|
+
value: this.currentValue,
|
|
681
|
+
stringValue: this.stringValue,
|
|
682
|
+
keys: this.currentKeys,
|
|
683
|
+
options: this.selectedOptions,
|
|
684
|
+
label: this.currentLabel
|
|
685
|
+
};
|
|
713
686
|
|
|
714
|
-
|
|
715
|
-
|
|
687
|
+
// If only one option is selected, include its index
|
|
688
|
+
if (this.selectedOptions.length === 1) details.index = this._menuOptions.indexOf(this.selectedOptions[0]);
|
|
716
689
|
|
|
717
|
-
|
|
718
|
-
|
|
719
|
-
|
|
720
|
-
|
|
721
|
-
|
|
722
|
-
);
|
|
723
|
-
if (displayValueEl) {
|
|
724
|
-
this.append(displayValueEl);
|
|
725
|
-
}
|
|
726
|
-
}
|
|
690
|
+
this.notify({
|
|
691
|
+
type: 'valueChange',
|
|
692
|
+
...meta,
|
|
693
|
+
...details
|
|
694
|
+
});
|
|
727
695
|
}
|
|
728
696
|
|
|
729
697
|
/**
|
|
730
|
-
*
|
|
731
|
-
*
|
|
732
|
-
* @
|
|
698
|
+
* Dispatches a custom event from the host element.
|
|
699
|
+
* @param {string} eventName
|
|
700
|
+
* @param {any} detail
|
|
733
701
|
*/
|
|
734
|
-
|
|
735
|
-
|
|
736
|
-
|
|
737
|
-
|
|
738
|
-
|
|
702
|
+
dispatchChangeEvent(eventName, detail) {
|
|
703
|
+
this.host.dispatchEvent(new CustomEvent(eventName, {
|
|
704
|
+
bubbles: true,
|
|
705
|
+
cancelable: false,
|
|
706
|
+
composed: true,
|
|
707
|
+
detail
|
|
708
|
+
}));
|
|
739
709
|
}
|
|
740
710
|
|
|
741
711
|
/**
|
|
742
|
-
*
|
|
743
|
-
* This function updates the menu service to set this option as the currently highlighted item if not disabled.
|
|
744
|
-
* @private
|
|
712
|
+
* MENU OPTION MANAGEMENT METHODS
|
|
745
713
|
*/
|
|
746
|
-
|
|
747
|
-
|
|
748
|
-
|
|
714
|
+
|
|
715
|
+
/**
|
|
716
|
+
* Adds a menu option to the service's list.
|
|
717
|
+
* @param {AuroMenuOption} option - the option to track
|
|
718
|
+
*/
|
|
719
|
+
addMenuOption(option) {
|
|
720
|
+
this._menuOptions.push(option);
|
|
721
|
+
this.notify({ type: 'optionsChange', options: this._menuOptions });
|
|
722
|
+
|
|
723
|
+
if (this._pendingValue != null) {
|
|
724
|
+
this.queuePendingValue(this._pendingValue);
|
|
749
725
|
}
|
|
750
726
|
}
|
|
751
727
|
|
|
752
728
|
/**
|
|
753
|
-
*
|
|
754
|
-
*
|
|
755
|
-
* @private
|
|
729
|
+
* Removes a menu option from the service's list.
|
|
730
|
+
* @param {AuroMenuOption} option - the option to remove
|
|
756
731
|
*/
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
732
|
+
removeMenuOption(option) {
|
|
733
|
+
this._menuOptions = this._menuOptions.filter(opt => opt !== option);
|
|
734
|
+
this.notify({ type: 'optionsChange', options: this._menuOptions });
|
|
735
|
+
|
|
736
|
+
if (this._menuOptions.length === 0) {
|
|
737
|
+
this.clearPendingValue();
|
|
761
738
|
}
|
|
762
739
|
}
|
|
763
740
|
|
|
764
741
|
/**
|
|
765
|
-
*
|
|
766
|
-
* This function notifies listeners that the option has been clicked.
|
|
767
|
-
* @private
|
|
742
|
+
* UTILITIES
|
|
768
743
|
*/
|
|
769
|
-
dispatchClickEvent() {
|
|
770
|
-
this.dispatchEvent(new CustomEvent('auroMenuOption-click', {
|
|
771
|
-
bubbles: true,
|
|
772
|
-
cancelable: false,
|
|
773
|
-
composed: true,
|
|
774
|
-
detail: this
|
|
775
|
-
}));
|
|
776
|
-
}
|
|
777
744
|
|
|
778
745
|
/**
|
|
779
|
-
*
|
|
746
|
+
* Normalizes a value or array of values into an array of strings for option selection.
|
|
747
|
+
* This function ensures that input values are consistently formatted for matching menu options.
|
|
780
748
|
*
|
|
781
|
-
* @
|
|
782
|
-
* @
|
|
783
|
-
* @
|
|
749
|
+
* @param {string|number|Array<string|number>} value - The value(s) to normalize.
|
|
750
|
+
* @returns {Array<string>} An array of string values suitable for option matching.
|
|
751
|
+
* @throws {Error} If any value is not a string or number.
|
|
784
752
|
*/
|
|
785
|
-
|
|
786
|
-
|
|
787
|
-
const svg = dom.body.firstChild;
|
|
753
|
+
_getNormalizedValues(value) {
|
|
754
|
+
let values = value;
|
|
788
755
|
|
|
789
|
-
|
|
756
|
+
// Handle JSON string and single value string input
|
|
757
|
+
if (!Array.isArray(values) && typeof values === 'string') {
|
|
790
758
|
|
|
791
|
-
|
|
792
|
-
|
|
759
|
+
// Attempt to parse as JSON array
|
|
760
|
+
try {
|
|
793
761
|
|
|
794
|
-
|
|
795
|
-
|
|
796
|
-
|
|
797
|
-
* @returns {void}
|
|
798
|
-
*/
|
|
799
|
-
renderLayout() {
|
|
762
|
+
// Normalize single quotes to double quotes for JSON parsing
|
|
763
|
+
// This will not handle complex cases but will cover basic usage
|
|
764
|
+
const parseValue = values.replace(/'([^']*?)'/g, '"$1"');
|
|
800
765
|
|
|
801
|
-
|
|
802
|
-
|
|
803
|
-
sm: 'body-default',
|
|
804
|
-
md: 'body-default',
|
|
805
|
-
lg: 'body-lg',
|
|
806
|
-
xl: 'body-lg'
|
|
807
|
-
};
|
|
766
|
+
// Attempt parse
|
|
767
|
+
const parsed = JSON.parse(parseValue);
|
|
808
768
|
|
|
809
|
-
|
|
810
|
-
|
|
811
|
-
[this.size ? fontClassMap[this.size] : 'body-sm']: true,
|
|
812
|
-
});
|
|
769
|
+
// Ensure parsed value is an array
|
|
770
|
+
if (!Array.isArray(parsed)) throw new Error('Not an array');
|
|
813
771
|
|
|
814
|
-
|
|
815
|
-
|
|
816
|
-
|
|
817
|
-
? this.generateIconHtml(checkmarkIcon.svg)
|
|
818
|
-
: undefined}
|
|
819
|
-
<slot></slot>
|
|
820
|
-
</div>
|
|
821
|
-
`;
|
|
822
|
-
}
|
|
823
|
-
}
|
|
824
|
-
|
|
825
|
-
/* eslint-disable */
|
|
772
|
+
// Set values to parsed array
|
|
773
|
+
values = parsed;
|
|
774
|
+
} catch (err) {
|
|
826
775
|
|
|
827
|
-
|
|
776
|
+
// If parsing fails, treat as single value
|
|
777
|
+
values = [value];
|
|
778
|
+
}
|
|
779
|
+
}
|
|
828
780
|
|
|
829
|
-
|
|
830
|
-
|
|
831
|
-
|
|
781
|
+
// Handle a single number being passed
|
|
782
|
+
if (typeof values === 'number') {
|
|
783
|
+
values = [String(values)];
|
|
784
|
+
}
|
|
832
785
|
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
* @returns {AuroMenuOption[]}
|
|
836
|
-
*/
|
|
837
|
-
get menuOptions() {
|
|
838
|
-
return this._menuOptions;
|
|
839
|
-
}
|
|
786
|
+
// Coerce each value to string and validate types
|
|
787
|
+
values.forEach((val, index) => {
|
|
840
788
|
|
|
841
|
-
|
|
842
|
-
|
|
843
|
-
|
|
844
|
-
|
|
845
|
-
get highlightedOption() {
|
|
846
|
-
return this._menuOptions[this.highlightedIndex] || null;
|
|
847
|
-
}
|
|
789
|
+
// Throw an error for invalid value types
|
|
790
|
+
if (typeof val !== 'string' && typeof val !== 'number') {
|
|
791
|
+
throw new Error('Value contains invalid value type. Supported types are string and number.');
|
|
792
|
+
}
|
|
848
793
|
|
|
849
|
-
|
|
850
|
-
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
const values = (this.selectedOptions || []).map(option => option.value);
|
|
855
|
-
return this.multiSelect ? values : values[0];
|
|
856
|
-
}
|
|
794
|
+
// Convert numbers to strings for consistency
|
|
795
|
+
if (typeof val === 'number') {
|
|
796
|
+
values[index] = String(val);
|
|
797
|
+
}
|
|
798
|
+
});
|
|
857
799
|
|
|
858
|
-
|
|
859
|
-
|
|
860
|
-
* @returns {string}
|
|
861
|
-
*/
|
|
862
|
-
get currentLabel() {
|
|
863
|
-
const labels = (this.selectedOptions || []).map(option => option.textContent);
|
|
864
|
-
return this.multiSelect ? labels.join(", ") : labels[0] || '';
|
|
800
|
+
// Return the resulting array of string values
|
|
801
|
+
return values;
|
|
865
802
|
}
|
|
866
803
|
|
|
867
804
|
/**
|
|
868
|
-
*
|
|
869
|
-
*
|
|
870
|
-
* @
|
|
805
|
+
* Returns whether two arrays of options contain the same elements.
|
|
806
|
+
* @param {AuroMenuOption[]} arr1 - First array of options.
|
|
807
|
+
* @param {AuroMenuOption[]} arr2 - Second array of options.
|
|
808
|
+
* @returns {boolean} True if arrays match, false otherwise.
|
|
871
809
|
*/
|
|
872
|
-
|
|
873
|
-
|
|
810
|
+
optionsArraysMatch(arr1, arr2) {
|
|
811
|
+
if (arr1.length !== arr2.length) return false;
|
|
874
812
|
|
|
875
|
-
|
|
876
|
-
|
|
877
|
-
return JSON.stringify(currentValue);
|
|
878
|
-
}
|
|
879
|
-
return undefined;
|
|
880
|
-
}
|
|
813
|
+
const set1 = new Set(arr1);
|
|
814
|
+
const set2 = new Set(arr2);
|
|
881
815
|
|
|
882
|
-
|
|
883
|
-
if (
|
|
884
|
-
return
|
|
816
|
+
for (let item of set1) {
|
|
817
|
+
if (!set2.has(item)) {
|
|
818
|
+
return false;
|
|
885
819
|
}
|
|
886
|
-
return undefined;
|
|
887
820
|
}
|
|
888
821
|
|
|
889
|
-
|
|
890
|
-
return undefined;
|
|
891
|
-
}
|
|
892
|
-
|
|
893
|
-
/**
|
|
894
|
-
* Gets the key(s) of the currently selected option(s).
|
|
895
|
-
* @returns {string|string[]|undefined}
|
|
896
|
-
*/
|
|
897
|
-
get currentKeys() {
|
|
898
|
-
const keys = (this.selectedOptions || []).map(option => option.key);
|
|
899
|
-
return this.multiSelect ? keys : keys[0];
|
|
822
|
+
return true;
|
|
900
823
|
}
|
|
824
|
+
}
|
|
901
825
|
|
|
902
|
-
|
|
903
|
-
* CONSTRUCTOR
|
|
904
|
-
*/
|
|
905
|
-
|
|
906
|
-
/**
|
|
907
|
-
* Creates a new MenuService instance.
|
|
908
|
-
* @param {Object} options - The options object.
|
|
909
|
-
* @param {AuroMenu} options.host - The host element that this service will control. Required.
|
|
910
|
-
* @throws {Error} If the host is not provided.
|
|
911
|
-
*/
|
|
912
|
-
constructor({ host } = {}) {
|
|
913
|
-
|
|
914
|
-
// Ensure a host was passed
|
|
915
|
-
if (!host) {
|
|
916
|
-
throw new Error("MenuService requires a host element.");
|
|
917
|
-
}
|
|
826
|
+
const MenuContext = createContext('menu-context');
|
|
918
827
|
|
|
919
|
-
|
|
920
|
-
|
|
921
|
-
this.host.addController(this);
|
|
828
|
+
// Copyright (c) Alaska Air. All right reserved. Licensed under the Apache-2.0 license
|
|
829
|
+
// See LICENSE in the project root for license information.
|
|
922
830
|
|
|
923
|
-
|
|
924
|
-
this.size = undefined;
|
|
925
|
-
this.shape = undefined;
|
|
926
|
-
this.noCheckmark = undefined;
|
|
927
|
-
this.disabled = undefined;
|
|
928
|
-
this.matchWord = undefined;
|
|
929
|
-
this.multiSelect = undefined;
|
|
930
|
-
this.allowDeselect = undefined;
|
|
931
|
-
this.selectAllMatchingOptions = undefined;
|
|
831
|
+
// ---------------------------------------------------------------------
|
|
932
832
|
|
|
933
|
-
|
|
833
|
+
/* eslint-disable line-comment-position, no-inline-comments, no-confusing-arrow, no-nested-ternary, implicit-arrow-linebreak */
|
|
934
834
|
|
|
935
|
-
|
|
936
|
-
this._subscribers = [];
|
|
937
|
-
this.internalUpdateInProgress = false;
|
|
938
|
-
this.selectedOptions = [];
|
|
939
|
-
this._pendingValue = null;
|
|
940
|
-
this._pendingRetryScheduled = false;
|
|
941
|
-
this._pendingRetryCount = 0;
|
|
942
|
-
}
|
|
835
|
+
class AuroLibraryRuntimeUtils {
|
|
943
836
|
|
|
944
|
-
|
|
945
|
-
* PROPERTY SYNCING
|
|
946
|
-
*/
|
|
837
|
+
/* eslint-disable jsdoc/require-param */
|
|
947
838
|
|
|
948
839
|
/**
|
|
949
|
-
*
|
|
950
|
-
*
|
|
951
|
-
*
|
|
952
|
-
*
|
|
953
|
-
* You can read more about Lit reactive controllers here: https://lit.dev/docs/composition/controllers/
|
|
840
|
+
* This will register a new custom element with the browser.
|
|
841
|
+
* @param {String} name - The name of the custom element.
|
|
842
|
+
* @param {Object} componentClass - The class to register as a custom element.
|
|
843
|
+
* @returns {void}
|
|
954
844
|
*/
|
|
955
|
-
|
|
956
|
-
|
|
957
|
-
|
|
958
|
-
if (this.host.multiSelect !== this.multiSelect) {
|
|
959
|
-
this.selectedOptions = [];
|
|
845
|
+
registerComponent(name, componentClass) {
|
|
846
|
+
if (!customElements.get(name)) {
|
|
847
|
+
customElements.define(name, class extends componentClass {});
|
|
960
848
|
}
|
|
961
|
-
|
|
962
|
-
// Update properties on host update
|
|
963
|
-
this.setProperties({
|
|
964
|
-
size: this.host.size,
|
|
965
|
-
shape: this.host.shape,
|
|
966
|
-
noCheckmark: this.host.noCheckmark,
|
|
967
|
-
disabled: this.host.disabled,
|
|
968
|
-
matchWord: this.host.matchWord,
|
|
969
|
-
multiSelect: this.host.multiSelect,
|
|
970
|
-
allowDeselect: this.host.allowDeselect,
|
|
971
|
-
selectAllMatchingOptions: this.host.selectAllMatchingOptions
|
|
972
|
-
});
|
|
973
849
|
}
|
|
974
850
|
|
|
975
851
|
/**
|
|
976
|
-
*
|
|
852
|
+
* Finds and returns the closest HTML Element based on a selector.
|
|
853
|
+
* @returns {void}
|
|
977
854
|
*/
|
|
978
|
-
|
|
979
|
-
|
|
980
|
-
|
|
981
|
-
|
|
982
|
-
|
|
983
|
-
|
|
855
|
+
closestElement(
|
|
856
|
+
selector, // selector like in .closest()
|
|
857
|
+
base = this, // extra functionality to skip a parent
|
|
858
|
+
__Closest = (el, found = el && el.closest(selector)) =>
|
|
859
|
+
!el || el === document || el === window
|
|
860
|
+
? null // standard .closest() returns null for non-found selectors also
|
|
861
|
+
: found
|
|
862
|
+
? found // found a selector INside this element
|
|
863
|
+
: __Closest(el.getRootNode().host) // recursion!! break out to parent DOM
|
|
864
|
+
) {
|
|
865
|
+
return __Closest(base);
|
|
984
866
|
}
|
|
867
|
+
/* eslint-enable jsdoc/require-param */
|
|
985
868
|
|
|
986
869
|
/**
|
|
987
|
-
*
|
|
988
|
-
* @param {
|
|
989
|
-
* @param {
|
|
870
|
+
* If the element passed is registered with a different tag name than what is passed in, the tag name is added as an attribute to the element.
|
|
871
|
+
* @param {Object} elem - The element to check.
|
|
872
|
+
* @param {String} tagName - The name of the Auro component to check for or add as an attribute.
|
|
873
|
+
* @returns {void}
|
|
990
874
|
*/
|
|
991
|
-
|
|
992
|
-
|
|
993
|
-
|
|
994
|
-
if (this.hasOwnProperty(property)) {
|
|
995
|
-
|
|
996
|
-
// Check if the value has changed
|
|
997
|
-
const valueChanged = this[property] !== value;
|
|
875
|
+
handleComponentTagRename(elem, tagName) {
|
|
876
|
+
const tag = tagName.toLowerCase();
|
|
877
|
+
const elemTag = elem.tagName.toLowerCase();
|
|
998
878
|
|
|
999
|
-
|
|
1000
|
-
|
|
1001
|
-
this[property] = value;
|
|
1002
|
-
this.notify({ property, value });
|
|
1003
|
-
}
|
|
879
|
+
if (elemTag !== tag) {
|
|
880
|
+
elem.setAttribute(tag, true);
|
|
1004
881
|
}
|
|
1005
882
|
}
|
|
1006
883
|
|
|
1007
884
|
/**
|
|
1008
|
-
*
|
|
1009
|
-
* @param {Object}
|
|
885
|
+
* Validates if an element is a specific Auro component.
|
|
886
|
+
* @param {Object} elem - The element to validate.
|
|
887
|
+
* @param {String} tagName - The name of the Auro component to check against.
|
|
888
|
+
* @returns {Boolean} - Returns true if the element is the specified Auro component.
|
|
1010
889
|
*/
|
|
1011
|
-
|
|
1012
|
-
|
|
1013
|
-
|
|
1014
|
-
|
|
890
|
+
elementMatch(elem, tagName) {
|
|
891
|
+
const tag = tagName.toLowerCase();
|
|
892
|
+
const elemTag = elem.tagName.toLowerCase();
|
|
893
|
+
|
|
894
|
+
return elemTag === tag || elem.hasAttribute(tag);
|
|
1015
895
|
}
|
|
1016
896
|
|
|
1017
897
|
/**
|
|
1018
|
-
*
|
|
898
|
+
* Gets the text content of a named slot.
|
|
899
|
+
* @returns {String}
|
|
900
|
+
* @private
|
|
1019
901
|
*/
|
|
902
|
+
getSlotText(elem, name) {
|
|
903
|
+
const slot = elem.shadowRoot?.querySelector(`slot[name="${name}"]`);
|
|
904
|
+
const nodes = slot?.assignedNodes({ flatten: true }) || [];
|
|
905
|
+
const text = nodes.map(n => n.textContent?.trim()).join(' ').trim();
|
|
1020
906
|
|
|
1021
|
-
|
|
1022
|
-
* Highlights the next active option in the menu.
|
|
1023
|
-
*/
|
|
1024
|
-
highlightNext() {
|
|
1025
|
-
this.moveHighlightedOption("next");
|
|
907
|
+
return text || null;
|
|
1026
908
|
}
|
|
909
|
+
}
|
|
1027
910
|
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
911
|
+
// Copyright (c) 2021 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
|
|
912
|
+
// See LICENSE in the project root for license information.
|
|
913
|
+
|
|
914
|
+
|
|
915
|
+
/**
|
|
916
|
+
* Helper method to dispatch custom events.
|
|
917
|
+
* @param {HTMLElement} element - Element to dispatch event from.
|
|
918
|
+
* @param {string} eventName - Name of the event to dispatch.
|
|
919
|
+
* @param {Object} [detail] - Optional detail object to include with the event.
|
|
920
|
+
*/
|
|
921
|
+
function dispatchMenuEvent(element, eventName, detail = null) {
|
|
922
|
+
const eventConfig = {
|
|
923
|
+
bubbles: true,
|
|
924
|
+
cancelable: false,
|
|
925
|
+
composed: true
|
|
926
|
+
};
|
|
927
|
+
|
|
928
|
+
if (detail !== null) {
|
|
929
|
+
eventConfig.detail = detail;
|
|
1033
930
|
}
|
|
1034
931
|
|
|
1035
|
-
|
|
1036
|
-
|
|
1037
|
-
* @param {string} direction - The direction to move the highlight ("next" or "previous").
|
|
1038
|
-
*/
|
|
1039
|
-
moveHighlightedOption(direction) {
|
|
932
|
+
element.dispatchEvent(new CustomEvent(eventName, eventConfig));
|
|
933
|
+
}
|
|
1040
934
|
|
|
1041
|
-
|
|
1042
|
-
|
|
935
|
+
/* eslint-disable no-underscore-dangle */
|
|
936
|
+
// Copyright (c) 2025 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
|
|
937
|
+
// See LICENSE in the project root for license information.
|
|
1043
938
|
|
|
1044
|
-
// Get the currently active option
|
|
1045
|
-
const currentActiveOption = activeOptions[activeOptions.indexOf(this.highlightedOption)];
|
|
1046
939
|
|
|
1047
|
-
// Determine the new index based on the currently active option and direction
|
|
1048
|
-
let newIndex = currentActiveOption
|
|
1049
|
-
? direction === "previous"
|
|
1050
|
-
? activeOptions.indexOf(currentActiveOption) - 1
|
|
1051
|
-
: activeOptions.indexOf(currentActiveOption) + 1
|
|
1052
|
-
: direction === "previous"
|
|
1053
|
-
? activeOptions.length - 1
|
|
1054
|
-
: 0;
|
|
1055
940
|
|
|
1056
|
-
|
|
1057
|
-
|
|
941
|
+
/**
|
|
942
|
+
* The `auro-menu` element provides users a way to select from a list of options.
|
|
943
|
+
* @customElement auro-menu
|
|
944
|
+
*
|
|
945
|
+
* @event {CustomEvent<Element>} auroMenu-activatedOption - Notifies that a menuoption has been made `active`.
|
|
946
|
+
* @event {CustomEvent<any>} auroMenu-customEventFired - Notifies that a custom event has been fired.
|
|
947
|
+
* @event {CustomEvent<{ loading: boolean; hasLoadingPlaceholder: boolean; }>} auroMenu-loadingChange - Notifies when the loading attribute is changed.
|
|
948
|
+
* @event {CustomEvent<any>} auroMenu-selectValueFailure - Notifies that an attempt to select a menuoption by matching a value has failed.
|
|
949
|
+
* @event {CustomEvent<{ values: HTMLElement[] }>} auroMenu-deselectPrevented - Notifies that deselection was prevented and includes the affected options in `detail.values`.
|
|
950
|
+
* @event {CustomEvent<any>} auroMenu-selectValueReset - Notifies that the component value has been reset.
|
|
951
|
+
* @event {CustomEvent<any>} auroMenu-selectedOption - Notifies that a new menuoption selection has been made.
|
|
952
|
+
* @slot loadingText - Text to show while loading attribute is set
|
|
953
|
+
* @slot loadingIcon - Icon to show while loading attribute is set
|
|
954
|
+
* @slot - Slot for insertion of menu options.
|
|
955
|
+
*/
|
|
1058
956
|
|
|
1059
|
-
|
|
1060
|
-
|
|
1061
|
-
|
|
957
|
+
/* eslint-disable max-lines */
|
|
958
|
+
|
|
959
|
+
class AuroMenu extends AuroElement {
|
|
960
|
+
|
|
961
|
+
constructor() {
|
|
962
|
+
super();
|
|
963
|
+
|
|
964
|
+
// State properties (reactive)
|
|
965
|
+
|
|
966
|
+
/**
|
|
967
|
+
* @private
|
|
968
|
+
*/
|
|
969
|
+
this.shape = "box";
|
|
970
|
+
|
|
971
|
+
/**
|
|
972
|
+
* @private
|
|
973
|
+
*/
|
|
974
|
+
this.size = "sm";
|
|
975
|
+
|
|
976
|
+
// Value of the selected options
|
|
977
|
+
this.value = undefined;
|
|
978
|
+
// Currently selected option
|
|
979
|
+
this.optionSelected = undefined;
|
|
980
|
+
// String used for highlighting/filtering
|
|
981
|
+
this.matchWord = undefined;
|
|
982
|
+
// Hide the checkmark icon on selected options
|
|
983
|
+
this.noCheckmark = false;
|
|
984
|
+
// Currently active option
|
|
985
|
+
this.optionActive = undefined;
|
|
986
|
+
// Loading state
|
|
987
|
+
this.loading = false;
|
|
988
|
+
// Multi-select mode
|
|
989
|
+
this.multiSelect = false;
|
|
990
|
+
// Allow deselecting of menu options
|
|
991
|
+
this.allowDeselect = false;
|
|
992
|
+
// Select all matching options when setting value in multi-select mode
|
|
993
|
+
this.selectAllMatchingOptions = false;
|
|
994
|
+
|
|
995
|
+
// Event Bindings
|
|
996
|
+
|
|
997
|
+
/**
|
|
998
|
+
* @private
|
|
999
|
+
*/
|
|
1000
|
+
this.handleSlotChange = this.handleSlotChange.bind(this);
|
|
1001
|
+
|
|
1002
|
+
// Instance properties (non-reactive)
|
|
1003
|
+
|
|
1004
|
+
/**
|
|
1005
|
+
* @private
|
|
1006
|
+
*/
|
|
1007
|
+
Object.assign(this, {
|
|
1008
|
+
// Root-level menu (true) or a nested submenu (false)
|
|
1009
|
+
rootMenu: true,
|
|
1010
|
+
// Currently focused/active menu item index
|
|
1011
|
+
_index: -1,
|
|
1012
|
+
// Nested menu spacer
|
|
1013
|
+
nestingSpacer: '<span class="nestingSpacer"></span>',
|
|
1014
|
+
// Loading indicator for slot elements
|
|
1015
|
+
loadingSlots: null,
|
|
1016
|
+
});
|
|
1062
1017
|
}
|
|
1063
1018
|
|
|
1064
|
-
|
|
1065
|
-
|
|
1066
|
-
|
|
1067
|
-
*/
|
|
1068
|
-
setHighlightedOption(option) {
|
|
1019
|
+
static get properties() {
|
|
1020
|
+
return {
|
|
1021
|
+
...super.properties,
|
|
1069
1022
|
|
|
1070
|
-
|
|
1023
|
+
/**
|
|
1024
|
+
* Allows deselecting an already selected option when clicked again in single-select mode.
|
|
1025
|
+
*/
|
|
1026
|
+
allowDeselect: {
|
|
1027
|
+
type: Boolean,
|
|
1028
|
+
reflect: true,
|
|
1029
|
+
},
|
|
1071
1030
|
|
|
1072
|
-
|
|
1073
|
-
|
|
1031
|
+
/**
|
|
1032
|
+
* When true, the entire menu and all options are disabled.
|
|
1033
|
+
*/
|
|
1034
|
+
disabled: {
|
|
1035
|
+
type: Boolean,
|
|
1036
|
+
reflect: true
|
|
1037
|
+
},
|
|
1074
1038
|
|
|
1075
|
-
|
|
1076
|
-
|
|
1039
|
+
/**
|
|
1040
|
+
* Indicates whether the menu has a loadingIcon or loadingText to render when in a loading state.
|
|
1041
|
+
*/
|
|
1042
|
+
hasLoadingPlaceholder: {
|
|
1043
|
+
type: Boolean
|
|
1044
|
+
},
|
|
1077
1045
|
|
|
1078
|
-
|
|
1079
|
-
|
|
1046
|
+
/**
|
|
1047
|
+
* @private
|
|
1048
|
+
*/
|
|
1049
|
+
layout: {
|
|
1050
|
+
type: String
|
|
1051
|
+
},
|
|
1080
1052
|
|
|
1081
|
-
|
|
1082
|
-
|
|
1053
|
+
/**
|
|
1054
|
+
* Indent level for submenus.
|
|
1055
|
+
* @private
|
|
1056
|
+
*/
|
|
1057
|
+
level: {
|
|
1058
|
+
type: Number,
|
|
1059
|
+
reflect: false,
|
|
1060
|
+
attribute: false
|
|
1061
|
+
},
|
|
1062
|
+
|
|
1063
|
+
/**
|
|
1064
|
+
* When true, displays a loading state using the loadingIcon and loadingText slots if provided.
|
|
1065
|
+
*/
|
|
1066
|
+
loading: {
|
|
1067
|
+
type: Boolean,
|
|
1068
|
+
reflect: true
|
|
1069
|
+
},
|
|
1070
|
+
|
|
1071
|
+
/**
|
|
1072
|
+
* Specifies a string used to highlight matched string parts in options.
|
|
1073
|
+
*/
|
|
1074
|
+
matchWord: {
|
|
1075
|
+
type: String,
|
|
1076
|
+
attribute: 'matchword'
|
|
1077
|
+
},
|
|
1078
|
+
|
|
1079
|
+
/**
|
|
1080
|
+
* When true, the selected option can be multiple options.
|
|
1081
|
+
*/
|
|
1082
|
+
multiSelect: {
|
|
1083
|
+
type: Boolean,
|
|
1084
|
+
reflect: true,
|
|
1085
|
+
attribute: 'multiselect'
|
|
1086
|
+
},
|
|
1087
|
+
|
|
1088
|
+
/**
|
|
1089
|
+
* When true, selected option will not show the checkmark.
|
|
1090
|
+
*/
|
|
1091
|
+
noCheckmark: {
|
|
1092
|
+
type: Boolean,
|
|
1093
|
+
reflect: true,
|
|
1094
|
+
attribute: 'nocheckmark'
|
|
1095
|
+
},
|
|
1096
|
+
|
|
1097
|
+
/**
|
|
1098
|
+
* Specifies the current active menuOption.
|
|
1099
|
+
*/
|
|
1100
|
+
optionActive: {
|
|
1101
|
+
type: Object,
|
|
1102
|
+
attribute: 'optionactive'
|
|
1103
|
+
},
|
|
1104
|
+
|
|
1105
|
+
/**
|
|
1106
|
+
* An array of currently selected menu options, type `HTMLElement` by default. In multi-select mode, `optionSelected` is an array of HTML elements.
|
|
1107
|
+
*/
|
|
1108
|
+
optionSelected: {
|
|
1109
|
+
// Allow HTMLElement, HTMLElement[] arrays and undefined
|
|
1110
|
+
type: Object
|
|
1111
|
+
},
|
|
1112
|
+
|
|
1113
|
+
/**
|
|
1114
|
+
* Available menu options.
|
|
1115
|
+
* @readonly
|
|
1116
|
+
*/
|
|
1117
|
+
options: {
|
|
1118
|
+
type: Array,
|
|
1119
|
+
reflect: false,
|
|
1120
|
+
attribute: false
|
|
1121
|
+
},
|
|
1122
|
+
|
|
1123
|
+
/**
|
|
1124
|
+
* Sets the size of the menu.
|
|
1125
|
+
* @type {'sm' | 'md'}
|
|
1126
|
+
* @default 'sm'
|
|
1127
|
+
*/
|
|
1128
|
+
size: {
|
|
1129
|
+
type: String,
|
|
1130
|
+
reflect: true
|
|
1131
|
+
},
|
|
1132
|
+
|
|
1133
|
+
/**
|
|
1134
|
+
* When true, selects all options that match the provided value/key when setting value and multiselect is enabled.
|
|
1135
|
+
*/
|
|
1136
|
+
selectAllMatchingOptions: {
|
|
1137
|
+
type: Boolean,
|
|
1138
|
+
reflect: true,
|
|
1139
|
+
},
|
|
1140
|
+
|
|
1141
|
+
/**
|
|
1142
|
+
* Sets the shape of the menu.
|
|
1143
|
+
* @type {'box' | 'round'}
|
|
1144
|
+
* @default 'box'
|
|
1145
|
+
*/
|
|
1146
|
+
shape: {
|
|
1147
|
+
type: String,
|
|
1148
|
+
reflect: true
|
|
1149
|
+
},
|
|
1150
|
+
|
|
1151
|
+
/**
|
|
1152
|
+
* The value of the selected option. In multi-select mode, this is a JSON stringified array of selected option values.
|
|
1153
|
+
*/
|
|
1154
|
+
value: {
|
|
1155
|
+
type: String,
|
|
1156
|
+
reflect: true,
|
|
1157
|
+
attribute: 'value'
|
|
1158
|
+
}
|
|
1159
|
+
};
|
|
1160
|
+
}
|
|
1161
|
+
|
|
1162
|
+
static get styles() {
|
|
1163
|
+
return [
|
|
1164
|
+
styleCss$1,
|
|
1165
|
+
colorCss$1,
|
|
1166
|
+
tokensCss
|
|
1167
|
+
];
|
|
1168
|
+
}
|
|
1169
|
+
|
|
1170
|
+
/**
|
|
1171
|
+
* @readonly
|
|
1172
|
+
* @returns {string} - Returns the label of the currently selected option(s).
|
|
1173
|
+
*/
|
|
1174
|
+
get currentLabel() {
|
|
1175
|
+
return this.menuService.currentLabel;
|
|
1176
|
+
};
|
|
1177
|
+
|
|
1178
|
+
/**
|
|
1179
|
+
* @readonly
|
|
1180
|
+
* @returns {Array<HTMLElement>} - Returns the array of available menu options.
|
|
1181
|
+
* @deprecated Use `options` property instead.
|
|
1182
|
+
*/
|
|
1183
|
+
get items() {
|
|
1184
|
+
return this.options;
|
|
1083
1185
|
}
|
|
1084
1186
|
|
|
1085
1187
|
/**
|
|
1086
|
-
*
|
|
1087
|
-
* @param {number} index
|
|
1188
|
+
* @returns {number} - Returns the index of the currently active option.
|
|
1088
1189
|
*/
|
|
1089
|
-
|
|
1090
|
-
|
|
1091
|
-
this.setHighlightedOption(option);
|
|
1190
|
+
get index() {
|
|
1191
|
+
return this._index;
|
|
1092
1192
|
}
|
|
1093
1193
|
|
|
1094
1194
|
/**
|
|
1095
|
-
*
|
|
1195
|
+
* @param {number} value - Sets the index of the currently active option.
|
|
1096
1196
|
*/
|
|
1097
|
-
|
|
1098
|
-
|
|
1099
|
-
this.toggleOption(this.highlightedOption);
|
|
1100
|
-
}
|
|
1197
|
+
set index(value) {
|
|
1198
|
+
this.menuService.setHighlightedIndex(value);
|
|
1101
1199
|
}
|
|
1102
1200
|
|
|
1103
1201
|
/**
|
|
1104
|
-
*
|
|
1202
|
+
* This will register this element with the browser.
|
|
1203
|
+
* @param {string} [name="auro-menu"] - The name of the element that you want to register.
|
|
1204
|
+
*
|
|
1205
|
+
* @example
|
|
1206
|
+
* AuroMenu.register("custom-menu") // this will register this element to <custom-menu/>
|
|
1207
|
+
*
|
|
1105
1208
|
*/
|
|
1209
|
+
static register(name = "auro-menu") {
|
|
1210
|
+
AuroLibraryRuntimeUtils.prototype.registerComponent(name, AuroMenu);
|
|
1211
|
+
}
|
|
1106
1212
|
|
|
1107
1213
|
/**
|
|
1108
|
-
*
|
|
1109
|
-
*
|
|
1214
|
+
* Formatted value based on `multiSelect` state.
|
|
1215
|
+
* Default type is `String`, changing to `Array<String>` when `multiSelect` is true.
|
|
1216
|
+
* @private
|
|
1217
|
+
* @returns {String|Array<String>}
|
|
1110
1218
|
*/
|
|
1111
|
-
|
|
1112
|
-
|
|
1113
|
-
|
|
1114
|
-
// Filter out options that are inactive
|
|
1115
|
-
optionsToSelect = optionsToSelect.filter(option => option.isActive);
|
|
1116
|
-
|
|
1117
|
-
if (!optionsToSelect.length) return;
|
|
1118
|
-
|
|
1119
|
-
if (this.multiSelect) {
|
|
1120
|
-
this.selectedOptions = [...(this.selectedOptions || []), ...optionsToSelect];
|
|
1121
|
-
} else {
|
|
1122
|
-
// In single select mode, only take the last option
|
|
1123
|
-
this.selectedOptions = [optionsToSelect[optionsToSelect.length - 1]];
|
|
1124
|
-
}
|
|
1125
|
-
|
|
1126
|
-
this.stageUpdate();
|
|
1219
|
+
get formattedValue() {
|
|
1220
|
+
return this.menuService.currentValue;
|
|
1127
1221
|
}
|
|
1128
1222
|
|
|
1129
1223
|
/**
|
|
1130
|
-
*
|
|
1131
|
-
* @
|
|
1224
|
+
* Gets the current property values for the menu service.
|
|
1225
|
+
* @private
|
|
1226
|
+
* @returns {Object}
|
|
1132
1227
|
*/
|
|
1133
|
-
|
|
1134
|
-
|
|
1135
|
-
|
|
1136
|
-
|
|
1137
|
-
|
|
1138
|
-
|
|
1139
|
-
|
|
1140
|
-
|
|
1228
|
+
get propertyValues() {
|
|
1229
|
+
return {
|
|
1230
|
+
size: this.size,
|
|
1231
|
+
shape: this.shape,
|
|
1232
|
+
noCheckmark: this.nocheckmark,
|
|
1233
|
+
disabled: this.disabled
|
|
1234
|
+
};
|
|
1235
|
+
}
|
|
1141
1236
|
|
|
1142
|
-
|
|
1143
|
-
|
|
1144
|
-
|
|
1145
|
-
|
|
1146
|
-
|
|
1147
|
-
|
|
1148
|
-
|
|
1149
|
-
|
|
1237
|
+
/**
|
|
1238
|
+
* Provides the menu context to child components.
|
|
1239
|
+
* Initializes the MenuService and subscribes to menu changes.
|
|
1240
|
+
* @protected
|
|
1241
|
+
*/
|
|
1242
|
+
provideContext() {
|
|
1243
|
+
if (this.parentElement && this.parentElement.closest('auro-menu, [auro-menu]')) {
|
|
1244
|
+
this.rootMenu = false;
|
|
1245
|
+
this.menuService = this.parentElement.menuService;
|
|
1246
|
+
this._contextProvider = this.parentElement._contextProvider;
|
|
1150
1247
|
return;
|
|
1151
1248
|
}
|
|
1152
1249
|
|
|
1153
|
-
|
|
1154
|
-
this.
|
|
1155
|
-
|
|
1156
|
-
|
|
1157
|
-
|
|
1250
|
+
this.menuService = new MenuService({host: this});
|
|
1251
|
+
this.menuService.setProperties(this.propertyValues);
|
|
1252
|
+
this.menuService.subscribe(this.handleMenuChange.bind(this));
|
|
1253
|
+
this._contextProvider = new ContextProvider(this, {
|
|
1254
|
+
context: MenuContext,
|
|
1255
|
+
initialValue: this.menuService
|
|
1256
|
+
});
|
|
1158
1257
|
}
|
|
1159
1258
|
|
|
1160
1259
|
/**
|
|
1161
|
-
*
|
|
1162
|
-
* @param {
|
|
1260
|
+
* Updates the currently active option in the menu.
|
|
1261
|
+
* @param {HTMLElement} option - The option to set as active.
|
|
1163
1262
|
*/
|
|
1164
|
-
|
|
1165
|
-
this.
|
|
1263
|
+
updateActiveOption(option) {
|
|
1264
|
+
this.menuService.setHighlightedOption(option);
|
|
1166
1265
|
}
|
|
1167
1266
|
|
|
1168
1267
|
/**
|
|
1169
|
-
*
|
|
1170
|
-
* @param {
|
|
1268
|
+
* Sets the internal value and manages update state.
|
|
1269
|
+
* @param {String|Array<String>} value - The value to set.
|
|
1270
|
+
* @protected
|
|
1171
1271
|
*/
|
|
1172
|
-
|
|
1173
|
-
this.
|
|
1174
|
-
|
|
1272
|
+
setInternalValue(value) {
|
|
1273
|
+
if (this.value !== value) {
|
|
1274
|
+
this.internalUpdateInProgress = true;
|
|
1275
|
+
this.value = value;
|
|
1175
1276
|
|
|
1176
|
-
|
|
1177
|
-
|
|
1178
|
-
|
|
1179
|
-
*/
|
|
1180
|
-
toggleOption(option) {
|
|
1181
|
-
if (option.selected) {
|
|
1182
|
-
this.deselectOption(option);
|
|
1183
|
-
} else {
|
|
1184
|
-
this.selectOption(option);
|
|
1277
|
+
setTimeout(() => {
|
|
1278
|
+
this.internalUpdateInProgress = false;
|
|
1279
|
+
});
|
|
1185
1280
|
}
|
|
1186
1281
|
}
|
|
1187
1282
|
|
|
1188
1283
|
/**
|
|
1189
|
-
*
|
|
1190
|
-
*
|
|
1191
|
-
* @
|
|
1284
|
+
* Handles changes from the menu service and updates component state.
|
|
1285
|
+
* @param {Object} event - The event object from the menu service.
|
|
1286
|
+
* @protected
|
|
1192
1287
|
*/
|
|
1193
|
-
|
|
1194
|
-
|
|
1195
|
-
value === null ||
|
|
1196
|
-
(Array.isArray(value) && value.length === 0) ||
|
|
1197
|
-
(typeof value === 'string' && value.trim() === '');
|
|
1198
|
-
|
|
1199
|
-
// Early exit for invalid/empty values
|
|
1200
|
-
if (isEmptyValue) {
|
|
1201
|
-
this.selectedOptions.forEach(opt => opt.selected = false);
|
|
1202
|
-
this.selectedOptions = [];
|
|
1203
|
-
return;
|
|
1204
|
-
}
|
|
1288
|
+
handleMenuChange(event) {
|
|
1289
|
+
if (event.type === 'valueChange') {
|
|
1205
1290
|
|
|
1206
|
-
|
|
1207
|
-
|
|
1208
|
-
|
|
1209
|
-
this.queuePendingValue(value);
|
|
1210
|
-
return;
|
|
1211
|
-
}
|
|
1291
|
+
// New option is array value or first option with fallback to undefined for empty array in all cases
|
|
1292
|
+
const newOption = this.multiSelect && event.options.length ? event.options : event.options[0] || undefined;
|
|
1293
|
+
const newValue = event.stringValue;
|
|
1212
1294
|
|
|
1213
|
-
|
|
1214
|
-
|
|
1295
|
+
// Check if the option or value has actually changed
|
|
1296
|
+
if (this.optionSelected !== newOption || this.stringValue !== newValue) {
|
|
1297
|
+
this.optionSelected = newOption;
|
|
1298
|
+
this.setInternalValue(newValue);
|
|
1299
|
+
}
|
|
1215
1300
|
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
if (normalizedValues.length > 1 && !this.multiSelect) {
|
|
1219
|
-
console.warn("MenuService - Multiple values provided for single-select menu. Only the first value will be selected.");
|
|
1220
|
-
validatedValues = [normalizedValues[0]];
|
|
1301
|
+
// Notify components of selection change
|
|
1302
|
+
this.notifySelectionChange(event);
|
|
1221
1303
|
}
|
|
1222
1304
|
|
|
1223
|
-
if (
|
|
1224
|
-
this.
|
|
1225
|
-
|
|
1305
|
+
if (event.type === 'highlightChange') {
|
|
1306
|
+
this.optionActive = event.option;
|
|
1307
|
+
this._index = event.index;
|
|
1226
1308
|
}
|
|
1227
1309
|
|
|
1228
|
-
|
|
1229
|
-
|
|
1230
|
-
|
|
1231
|
-
|
|
1232
|
-
|
|
1233
|
-
|
|
1234
|
-
|
|
1235
|
-
|
|
1236
|
-
|
|
1237
|
-
// Include the option in the options to be selected if it passes the filter check and
|
|
1238
|
-
// either hasn't been tracked yet or selectAllMatchingOptions is true
|
|
1239
|
-
return isActive && passesFilter && (!alreadyTracked || (alreadyTracked && this.selectAllMatchingOptions));
|
|
1240
|
-
});
|
|
1310
|
+
if (event.type === 'optionsChange') {
|
|
1311
|
+
this.options = event.options;
|
|
1312
|
+
this.dispatchEvent(new CustomEvent('auroMenu-optionsChange', {
|
|
1313
|
+
detail: {
|
|
1314
|
+
options: event.options
|
|
1315
|
+
}
|
|
1316
|
+
}));
|
|
1317
|
+
}
|
|
1318
|
+
}
|
|
1241
1319
|
|
|
1242
|
-
|
|
1243
|
-
|
|
1244
|
-
|
|
1245
|
-
|
|
1320
|
+
/**
|
|
1321
|
+
* Gets the currently selected options.
|
|
1322
|
+
* @returns {Array<HTMLElement>}
|
|
1323
|
+
*/
|
|
1324
|
+
get selectedOptions() {
|
|
1325
|
+
return this.menuService ? this.menuService.selectedOptions : [];
|
|
1326
|
+
}
|
|
1246
1327
|
|
|
1247
|
-
|
|
1248
|
-
|
|
1249
|
-
|
|
1250
|
-
|
|
1328
|
+
/**
|
|
1329
|
+
* Gets the first selected option, or null if none.
|
|
1330
|
+
* @returns {HTMLElement|null}
|
|
1331
|
+
*/
|
|
1332
|
+
get selectedOption() {
|
|
1333
|
+
return this.menuService ? this.menuService.selectedOptions[0] : null;
|
|
1334
|
+
}
|
|
1251
1335
|
|
|
1252
|
-
|
|
1336
|
+
// Lifecycle Methods
|
|
1253
1337
|
|
|
1254
|
-
|
|
1255
|
-
|
|
1256
|
-
}
|
|
1338
|
+
connectedCallback() {
|
|
1339
|
+
super.connectedCallback();
|
|
1257
1340
|
|
|
1258
|
-
|
|
1259
|
-
// selectedOptions was already empty (e.g. double-clicking set-invalid).
|
|
1260
|
-
this.stageUpdate({ reason: 'no-match' });
|
|
1341
|
+
this.provideContext();
|
|
1261
1342
|
|
|
1262
|
-
|
|
1263
|
-
|
|
1264
|
-
|
|
1265
|
-
|
|
1266
|
-
|
|
1267
|
-
|
|
1268
|
-
}
|
|
1343
|
+
// this.addEventListener('keydown', this.handleKeyDown);
|
|
1344
|
+
this.addEventListener('auroMenuOption-click', this.handleMouseSelect);
|
|
1345
|
+
this.addEventListener('auroMenuOption-mouseover', this.handleOptionHover);
|
|
1346
|
+
this.addEventListener('slotchange', this.handleSlotChange);
|
|
1347
|
+
this.setTagAttribute("auro-menu");
|
|
1348
|
+
}
|
|
1269
1349
|
|
|
1270
|
-
|
|
1271
|
-
|
|
1350
|
+
disconnectedCallback() {
|
|
1351
|
+
// this.removeEventListener('keydown', this.handleKeyDown);
|
|
1352
|
+
this.removeEventListener('auroMenuOption-click', this.handleMouseSelect);
|
|
1353
|
+
this.removeEventListener('auroMenuOption-mouseover', this.handleOptionHover);
|
|
1354
|
+
this.removeEventListener('slotchange', this.handleSlotChange);
|
|
1272
1355
|
|
|
1273
|
-
|
|
1356
|
+
super.disconnectedCallback();
|
|
1357
|
+
}
|
|
1274
1358
|
|
|
1275
|
-
|
|
1276
|
-
|
|
1277
|
-
}
|
|
1359
|
+
firstUpdated() {
|
|
1360
|
+
AuroLibraryRuntimeUtils.prototype.handleComponentTagRename(this, 'auro-menu');
|
|
1278
1361
|
|
|
1279
|
-
|
|
1280
|
-
this.
|
|
1281
|
-
this.stageUpdate();
|
|
1362
|
+
this.loadingSlots = this.querySelectorAll("[slot='loadingText'], [slot='loadingIcon']");
|
|
1363
|
+
this.initializeMenu();
|
|
1282
1364
|
}
|
|
1283
1365
|
|
|
1284
|
-
/**
|
|
1285
|
-
* Queues a pending value and schedules a bounded retry.
|
|
1286
|
-
* @param {string|number|Array<string|number>} value - The value to retry.
|
|
1287
|
-
*/
|
|
1288
|
-
queuePendingValue(value) {
|
|
1289
|
-
this._pendingValue = value;
|
|
1290
1366
|
|
|
1291
|
-
|
|
1292
|
-
|
|
1293
|
-
}
|
|
1367
|
+
updated(changedProperties) {
|
|
1368
|
+
super.updated(changedProperties);
|
|
1294
1369
|
|
|
1295
|
-
|
|
1296
|
-
|
|
1370
|
+
// Apply value selection synchronously so that static-HTML fixtures
|
|
1371
|
+
// resolve within a single update cycle. The refactored selectByValue
|
|
1372
|
+
// no longer calls reset() first, so the destructive intermediate-event
|
|
1373
|
+
// cascade that originally required deferral is eliminated. If option
|
|
1374
|
+
// keys are not yet resolved (framework mount-order race), selectByValue
|
|
1375
|
+
// queues a bounded retry automatically via queuePendingValue.
|
|
1376
|
+
if (changedProperties.has('value') && !this.internalUpdateInProgress) {
|
|
1377
|
+
this.menuService.selectByValue(this.value);
|
|
1378
|
+
}
|
|
1297
1379
|
|
|
1298
|
-
|
|
1299
|
-
|
|
1380
|
+
// Handle loading state changes
|
|
1381
|
+
if (changedProperties.has('loading')) {
|
|
1382
|
+
this.setLoadingState(this.loading);
|
|
1383
|
+
}
|
|
1300
1384
|
|
|
1301
|
-
|
|
1302
|
-
|
|
1385
|
+
if (changedProperties.has('multiSelect') && this.rootMenu) {
|
|
1386
|
+
if (this.multiSelect) {
|
|
1387
|
+
this.setAttribute('aria-multiselectable', 'true');
|
|
1388
|
+
} else {
|
|
1389
|
+
this.removeAttribute('aria-multiselectable');
|
|
1303
1390
|
}
|
|
1304
|
-
|
|
1305
|
-
const pendingValue = this._pendingValue;
|
|
1306
|
-
this.selectByValue(pendingValue);
|
|
1307
|
-
}, 0);
|
|
1391
|
+
}
|
|
1308
1392
|
}
|
|
1309
1393
|
|
|
1310
1394
|
/**
|
|
1311
|
-
*
|
|
1395
|
+
* Sets an attribute that matches the default tag name if the tag name is not the default.
|
|
1396
|
+
* @param {string} tagName - The tag name to set as an attribute.
|
|
1397
|
+
* @private
|
|
1312
1398
|
*/
|
|
1313
|
-
|
|
1314
|
-
this.
|
|
1315
|
-
|
|
1316
|
-
|
|
1399
|
+
setTagAttribute(tagName) {
|
|
1400
|
+
if (this.tagName.toLowerCase() !== tagName) {
|
|
1401
|
+
this.setAttribute(tagName, true);
|
|
1402
|
+
}
|
|
1317
1403
|
}
|
|
1318
1404
|
|
|
1319
1405
|
/**
|
|
1320
|
-
*
|
|
1406
|
+
* Sets the loading state and dispatches a loading change event.
|
|
1407
|
+
* @param {boolean} isLoading - Whether the menu is loading.
|
|
1408
|
+
* @protected
|
|
1321
1409
|
*/
|
|
1322
|
-
|
|
1323
|
-
|
|
1324
|
-
|
|
1325
|
-
|
|
1326
|
-
|
|
1327
|
-
|
|
1328
|
-
if (previousOptions.length) {
|
|
1329
|
-
this.stageUpdate();
|
|
1330
|
-
}
|
|
1410
|
+
setLoadingState(isLoading) {
|
|
1411
|
+
this.setAttribute("aria-busy", isLoading);
|
|
1412
|
+
dispatchMenuEvent(this, "auroMenu-loadingChange", {
|
|
1413
|
+
loading: isLoading,
|
|
1414
|
+
hasLoadingPlaceholder: this.hasLoadingPlaceholder
|
|
1415
|
+
});
|
|
1331
1416
|
}
|
|
1332
1417
|
|
|
1333
|
-
|
|
1334
|
-
* SUBSCRIPTION, NOTIFICATION AND EVENT DISPATCH METHODS
|
|
1335
|
-
*/
|
|
1418
|
+
// Init Methods
|
|
1336
1419
|
|
|
1337
1420
|
/**
|
|
1338
|
-
*
|
|
1339
|
-
* @
|
|
1421
|
+
* Initializes the menu's state and structure.
|
|
1422
|
+
* @private
|
|
1340
1423
|
*/
|
|
1341
|
-
|
|
1342
|
-
this.
|
|
1343
|
-
|
|
1424
|
+
initializeMenu() {
|
|
1425
|
+
if (this.rootMenu) {
|
|
1426
|
+
this.setAttribute('role', 'listbox');
|
|
1427
|
+
this.setAttribute('root', '');
|
|
1344
1428
|
|
|
1345
|
-
|
|
1346
|
-
|
|
1347
|
-
|
|
1348
|
-
|
|
1349
|
-
|
|
1350
|
-
this.
|
|
1429
|
+
if (this.multiSelect) {
|
|
1430
|
+
this.setAttribute('aria-multiselectable', 'true');
|
|
1431
|
+
}
|
|
1432
|
+
}
|
|
1433
|
+
|
|
1434
|
+
this.handleNestedMenus(this);
|
|
1351
1435
|
}
|
|
1352
1436
|
|
|
1353
1437
|
/**
|
|
1354
|
-
*
|
|
1438
|
+
* Selects the currently highlighted option.
|
|
1439
|
+
* @protected
|
|
1355
1440
|
*/
|
|
1356
|
-
|
|
1357
|
-
this.
|
|
1358
|
-
this.notifyValueChange(meta);
|
|
1441
|
+
makeSelection() {
|
|
1442
|
+
this.menuService.selectHighlightedOption();
|
|
1359
1443
|
}
|
|
1360
1444
|
|
|
1361
1445
|
/**
|
|
1362
|
-
*
|
|
1363
|
-
*
|
|
1364
|
-
* @param {string} event - The event to send to subscribers.
|
|
1446
|
+
* Resets all options to their default state.
|
|
1447
|
+
* @private
|
|
1365
1448
|
*/
|
|
1366
|
-
|
|
1367
|
-
this.
|
|
1449
|
+
clearSelection() {
|
|
1450
|
+
this.optionSelected = undefined;
|
|
1451
|
+
this.value = undefined;
|
|
1452
|
+
this._index = -1;
|
|
1368
1453
|
}
|
|
1369
1454
|
|
|
1370
1455
|
/**
|
|
1371
|
-
*
|
|
1456
|
+
* Resets the menu to its initial state.
|
|
1457
|
+
* This is the only way to return value to undefined.
|
|
1458
|
+
* @public
|
|
1372
1459
|
*/
|
|
1373
|
-
|
|
1374
|
-
this.
|
|
1375
|
-
|
|
1376
|
-
|
|
1377
|
-
|
|
1378
|
-
});
|
|
1460
|
+
reset() {
|
|
1461
|
+
this.menuService.reset();
|
|
1462
|
+
|
|
1463
|
+
// Dispatch reset event
|
|
1464
|
+
dispatchMenuEvent(this, 'auroMenu-selectValueReset');
|
|
1379
1465
|
}
|
|
1380
1466
|
|
|
1381
1467
|
/**
|
|
1382
|
-
*
|
|
1468
|
+
* Handles nested menu structure.
|
|
1469
|
+
* @private
|
|
1470
|
+
* @param {HTMLElement} menu - Root menu element.
|
|
1383
1471
|
*/
|
|
1384
|
-
|
|
1385
|
-
|
|
1386
|
-
// Prepare details for the event
|
|
1387
|
-
const details = {
|
|
1388
|
-
value: this.currentValue,
|
|
1389
|
-
stringValue: this.stringValue,
|
|
1390
|
-
keys: this.currentKeys,
|
|
1391
|
-
options: this.selectedOptions,
|
|
1392
|
-
label: this.currentLabel
|
|
1393
|
-
};
|
|
1472
|
+
handleNestedMenus(menu) {
|
|
1473
|
+
menu.level = menu.parentElement.level >= 0 ? menu.parentElement.level + 1 : 0;
|
|
1394
1474
|
|
|
1395
|
-
|
|
1396
|
-
|
|
1475
|
+
if (menu.level > 0) {
|
|
1476
|
+
menu.setAttribute('role', 'group');
|
|
1477
|
+
menu.removeAttribute("root");
|
|
1478
|
+
if (!menu.hasAttribute('aria-label')) {
|
|
1479
|
+
menu.setAttribute('aria-label', 'submenu');
|
|
1480
|
+
}
|
|
1481
|
+
}
|
|
1397
1482
|
|
|
1398
|
-
|
|
1399
|
-
|
|
1400
|
-
|
|
1401
|
-
|
|
1483
|
+
const options = menu.querySelectorAll(':scope > auro-menuoption, :scope > [auro-menuoption]');
|
|
1484
|
+
options.forEach((option) => {
|
|
1485
|
+
const regex = new RegExp(this.nestingSpacer, "gu");
|
|
1486
|
+
option.innerHTML = this.nestingSpacer.repeat(menu.level) + option.innerHTML.replace(regex, '');
|
|
1402
1487
|
});
|
|
1403
1488
|
}
|
|
1404
1489
|
|
|
1405
1490
|
/**
|
|
1406
|
-
*
|
|
1407
|
-
* @param {
|
|
1408
|
-
* @
|
|
1491
|
+
* Navigates the menu options in the specified direction.
|
|
1492
|
+
* @param {'up'|'down'} direction - The direction to navigate.
|
|
1493
|
+
* @protected
|
|
1409
1494
|
*/
|
|
1410
|
-
|
|
1411
|
-
|
|
1412
|
-
|
|
1413
|
-
|
|
1414
|
-
|
|
1415
|
-
|
|
1416
|
-
}));
|
|
1495
|
+
navigateOptions(direction) {
|
|
1496
|
+
if (direction === 'up') {
|
|
1497
|
+
this.menuService.highlightPrevious();
|
|
1498
|
+
} else if (direction === 'down') {
|
|
1499
|
+
this.menuService.highlightNext();
|
|
1500
|
+
}
|
|
1417
1501
|
}
|
|
1418
1502
|
|
|
1419
1503
|
/**
|
|
1420
|
-
*
|
|
1504
|
+
* Handles slot change events.
|
|
1505
|
+
* @private
|
|
1421
1506
|
*/
|
|
1507
|
+
handleSlotChange() {
|
|
1508
|
+
if (this.rootMenu) {
|
|
1509
|
+
this.initializeMenu();
|
|
1510
|
+
}
|
|
1511
|
+
}
|
|
1422
1512
|
|
|
1423
1513
|
/**
|
|
1424
|
-
*
|
|
1425
|
-
* @
|
|
1514
|
+
* Handles custom events defined on options.
|
|
1515
|
+
* @private
|
|
1516
|
+
* @param {HTMLElement} option - Option with custom event.
|
|
1426
1517
|
*/
|
|
1427
|
-
|
|
1428
|
-
|
|
1429
|
-
this
|
|
1518
|
+
handleCustomEvent(option) {
|
|
1519
|
+
const eventName = option.getAttribute('event');
|
|
1520
|
+
dispatchMenuEvent(this, eventName);
|
|
1521
|
+
dispatchMenuEvent(this, 'auroMenu-customEventFired');
|
|
1522
|
+
}
|
|
1430
1523
|
|
|
1431
|
-
|
|
1432
|
-
|
|
1433
|
-
|
|
1524
|
+
/**
|
|
1525
|
+
* Notifies selection change to parent components.
|
|
1526
|
+
* @param {any} source - The source that triggers this event.
|
|
1527
|
+
* @private
|
|
1528
|
+
*/
|
|
1529
|
+
notifySelectionChange({value, stringValue, keys, options, reason} = {}) {
|
|
1530
|
+
dispatchMenuEvent(this, 'auroMenu-selectedOption', {
|
|
1531
|
+
value,
|
|
1532
|
+
stringValue,
|
|
1533
|
+
keys,
|
|
1534
|
+
options,
|
|
1535
|
+
reason
|
|
1536
|
+
});
|
|
1434
1537
|
}
|
|
1435
1538
|
|
|
1436
1539
|
/**
|
|
1437
|
-
*
|
|
1438
|
-
* @
|
|
1540
|
+
* Checks if an option is currently selected.
|
|
1541
|
+
* @private
|
|
1542
|
+
* @param {HTMLElement} option - The option to check.
|
|
1543
|
+
* @returns {boolean}
|
|
1439
1544
|
*/
|
|
1440
|
-
|
|
1441
|
-
|
|
1442
|
-
|
|
1545
|
+
isOptionSelected(option) {
|
|
1546
|
+
if (!this.optionSelected) {
|
|
1547
|
+
return false;
|
|
1548
|
+
}
|
|
1443
1549
|
|
|
1444
|
-
if (this.
|
|
1445
|
-
|
|
1550
|
+
if (this.multiSelect) {
|
|
1551
|
+
// In multi-select mode, check if the option is in the selected array
|
|
1552
|
+
return Array.isArray(this.optionSelected) && this.optionSelected.some((selectedOption) => selectedOption === option);
|
|
1446
1553
|
}
|
|
1554
|
+
|
|
1555
|
+
return this.optionSelected === option;
|
|
1447
1556
|
}
|
|
1448
1557
|
|
|
1449
1558
|
/**
|
|
1450
|
-
*
|
|
1559
|
+
* Getter for loading placeholder state.
|
|
1560
|
+
* @returns {boolean} - True if loading slots are present and non-empty.
|
|
1451
1561
|
*/
|
|
1562
|
+
get hasLoadingPlaceholder() {
|
|
1563
|
+
return this.loadingSlots && this.loadingSlots.length > 0;
|
|
1564
|
+
}
|
|
1452
1565
|
|
|
1453
1566
|
/**
|
|
1454
|
-
*
|
|
1455
|
-
*
|
|
1456
|
-
*
|
|
1457
|
-
* @param {string|number|Array<string|number>} value - The value(s) to normalize.
|
|
1458
|
-
* @returns {Array<string>} An array of string values suitable for option matching.
|
|
1459
|
-
* @throws {Error} If any value is not a string or number.
|
|
1567
|
+
* Getter for wrapper classes based on size.
|
|
1568
|
+
* @returns {Object} - Class map for the wrapper element.
|
|
1569
|
+
* @private
|
|
1460
1570
|
*/
|
|
1461
|
-
|
|
1462
|
-
|
|
1463
|
-
|
|
1464
|
-
|
|
1465
|
-
|
|
1466
|
-
|
|
1467
|
-
// Attempt to parse as JSON array
|
|
1468
|
-
try {
|
|
1571
|
+
get wrapperClasses() {
|
|
1572
|
+
return classMap({
|
|
1573
|
+
'menuWrapper': true,
|
|
1574
|
+
[this.size]: true,
|
|
1575
|
+
});
|
|
1576
|
+
}
|
|
1469
1577
|
|
|
1470
|
-
|
|
1471
|
-
|
|
1472
|
-
|
|
1578
|
+
/**
|
|
1579
|
+
* Logic to determine the layout of the component.
|
|
1580
|
+
* @protected
|
|
1581
|
+
* @returns {void}
|
|
1582
|
+
*/
|
|
1583
|
+
renderLayout() {
|
|
1584
|
+
if (this.loading) {
|
|
1585
|
+
return html`
|
|
1586
|
+
<div class="${this.wrapperClasses}">
|
|
1587
|
+
<auro-menuoption
|
|
1588
|
+
disabled
|
|
1589
|
+
loadingplaceholder
|
|
1590
|
+
class="${this.hasLoadingPlaceholder ? "" : "empty"}"
|
|
1591
|
+
>
|
|
1592
|
+
<div>
|
|
1593
|
+
<slot name="loadingIcon" class="body-lg"></slot>
|
|
1594
|
+
<slot name="loadingText"></slot>
|
|
1595
|
+
</div>
|
|
1596
|
+
</auro-menuoption>
|
|
1597
|
+
</div>
|
|
1598
|
+
`;
|
|
1599
|
+
}
|
|
1473
1600
|
|
|
1474
|
-
|
|
1475
|
-
|
|
1601
|
+
return html`
|
|
1602
|
+
<div class="${this.wrapperClasses}">
|
|
1603
|
+
<slot @slotchange=${this.handleSlotChange}></slot>
|
|
1604
|
+
</div>
|
|
1605
|
+
`;
|
|
1606
|
+
}
|
|
1607
|
+
}
|
|
1476
1608
|
|
|
1477
|
-
// Ensure parsed value is an array
|
|
1478
|
-
if (!Array.isArray(parsed)) throw new Error('Not an array');
|
|
1609
|
+
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-default-weight, );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-default-emphasized{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-default-emphasized-weight, );letter-spacing:var(--wcss-body-letter-spacing, 0);font-size:var(--wcss-body-default-emphasized-font-size, 1rem);line-height:var(--wcss-body-default-emphasized-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-lg-weight, );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-lg-emphasized{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-lg-emphasized-weight, );letter-spacing:var(--wcss-body-letter-spacing, 0);font-size:var(--wcss-body-lg-emphasized-font-size, 1.125rem);line-height:var(--wcss-body-lg-emphasized-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-sm-weight, );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-sm-emphasized{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-sm-emphasized-weight, );letter-spacing:var(--wcss-body-letter-spacing, 0);font-size:var(--wcss-body-sm-emphasized-font-size, 0.875rem);line-height:var(--wcss-body-sm-emphasized-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-xs-weight, );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-xs-emphasized{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-xs-emphasized-weight, );letter-spacing:var(--wcss-body-letter-spacing, 0);font-size:var(--wcss-body-xs-emphasized-font-size, 0.75rem);line-height:var(--wcss-body-xs-emphasized-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-2xs-weight, );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)}.body-2xs-emphasized{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-2xs-emphasized-weight, );letter-spacing:var(--wcss-body-letter-spacing, 0);font-size:var(--wcss-body-2xs-emphasized-font-size, 0.625rem);line-height:var(--wcss-body-2xs-emphasized-line-height, 0.875rem)}.display-2xl{font-family:var(--wcss-display-2xl-family, "AS Circular"),var(--wcss-display-2xl-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-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));letter-spacing:var(--wcss-display-2xl-letter-spacing, 0)}.display-xl{font-family:var(--wcss-display-xl-family, "AS Circular"),var(--wcss-display-xl-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-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));letter-spacing:var(--wcss-display-xl-letter-spacing, 0)}.display-lg{font-family:var(--wcss-display-lg-family, "AS Circular"),var(--wcss-display-lg-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-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));letter-spacing:var(--wcss-display-lg-letter-spacing, 0)}.display-md{font-family:var(--wcss-display-md-family, "AS Circular"),var(--wcss-display-md-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-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));letter-spacing:var(--wcss-display-md-letter-spacing, 0)}.display-sm{font-family:var(--wcss-display-sm-family, "AS Circular"),var(--wcss-display-sm-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-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));letter-spacing:var(--wcss-display-sm-letter-spacing, 0)}.display-xs{font-family:var(--wcss-display-xs-family, "AS Circular"),var(--wcss-display-xs-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-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));letter-spacing:var(--wcss-display-xs-letter-spacing, 0)}.heading-xl{font-family:var(--wcss-heading-xl-family, "AS Circular"),var(--wcss-heading-xl-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-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));letter-spacing:var(--wcss-heading-xl-letter-spacing, 0)}.heading-lg{font-family:var(--wcss-heading-lg-family, "AS Circular"),var(--wcss-heading-lg-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-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));letter-spacing:var(--wcss-heading-lg-letter-spacing, 0)}.heading-md{font-family:var(--wcss-heading-md-family, "AS Circular"),var(--wcss-heading-md-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-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));letter-spacing:var(--wcss-heading-md-letter-spacing, 0)}.heading-sm{font-family:var(--wcss-heading-sm-family, "AS Circular"),var(--wcss-heading-sm-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-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));letter-spacing:var(--wcss-heading-sm-letter-spacing, 0)}.heading-xs{font-family:var(--wcss-heading-xs-family, "AS Circular"),var(--wcss-heading-xs-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-weight:var(--wcss-heading-xs-weight, 300);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));letter-spacing:var(--wcss-heading-xs-letter-spacing, 0)}.heading-2xs{font-family:var(--wcss-heading-2xs-family, "AS Circular"),var(--wcss-heading-2xs-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-weight:var(--wcss-heading-2xs-weight, 300);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));letter-spacing:var(--wcss-heading-2xs-letter-spacing, 0)}.accent-2xl{font-family:var(--wcss-accent-2xl-family, "Good OT"),var(--wcss-accent-2xl-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-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));letter-spacing:var(--wcss-accent-2xl-letter-spacing, 0.05em);text-transform:uppercase}.accent-xl{font-family:var(--wcss-accent-xl-family, "Good OT"),var(--wcss-accent-xl-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-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));letter-spacing:var(--wcss-accent-xl-letter-spacing, 0.05em);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);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));letter-spacing:var(--wcss-accent-lg-letter-spacing, 0.05em);text-transform:uppercase}.accent-md{font-family:var(--wcss-accent-md-family, "Good OT"),var(--wcss-accent-md-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-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));letter-spacing:var(--wcss-accent-md-letter-spacing, 0.05em);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);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));letter-spacing:var(--wcss-accent-sm-letter-spacing, 0.05em);text-transform:uppercase}.accent-xs{font-family:var(--wcss-accent-xs-family, "Good OT"),var(--wcss-accent-xs-family-fallback, system-ui, -apple-system, BlinkMacSystemFont, "Segoe UI", Roboto, "Helvetica Neue", Arial, sans-serif);font-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));letter-spacing:var(--wcss-accent-xs-letter-spacing, 0.1em);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);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));letter-spacing:var(--wcss-accent-2xs-letter-spacing, 0.1em);text-transform:uppercase}:host{cursor:pointer;user-select:none;text-overflow:ellipsis;max-width:100dvw}:host .wrapper{display:flex;align-items:center;height:var(--ds-size-400, 2rem);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));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}`;
|
|
1479
1610
|
|
|
1480
|
-
|
|
1481
|
-
values = parsed;
|
|
1482
|
-
} catch (err) {
|
|
1611
|
+
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(.active){--ds-auro-menuoption-container-color: var(--ds-basic-color-surface-accent1-muted, #ebfafd)}@media(hover: hover){:host(:hover){--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].active){--ds-auro-menuoption-container-color: var(--ds-basic-color-surface-accent1-muted, #ebfafd)}@media(hover: hover){:host([selected]:hover){--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.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)}@media(hover: hover){:host(:focus:hover){--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.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)}@media(hover: hover){:host([selected]:focus:hover){--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)}}`;
|
|
1483
1612
|
|
|
1484
|
-
|
|
1485
|
-
|
|
1486
|
-
}
|
|
1487
|
-
}
|
|
1613
|
+
// Copyright (c) Alaska Air. All right reserved. Licensed under the Apache-2.0 license
|
|
1614
|
+
// See LICENSE in the project root for license information.
|
|
1488
1615
|
|
|
1489
|
-
// Handle a single number being passed
|
|
1490
|
-
if (typeof values === 'number') {
|
|
1491
|
-
values = [String(values)];
|
|
1492
|
-
}
|
|
1493
1616
|
|
|
1494
|
-
|
|
1495
|
-
values.forEach((val, index) => {
|
|
1617
|
+
class AuroDependencyVersioning {
|
|
1496
1618
|
|
|
1497
|
-
|
|
1498
|
-
|
|
1499
|
-
|
|
1500
|
-
|
|
1619
|
+
/**
|
|
1620
|
+
* Generates a unique string to be used for child auro element naming.
|
|
1621
|
+
* @private
|
|
1622
|
+
* @param {string} baseName - Defines the first part of the unique element name.
|
|
1623
|
+
* @param {string} version - Version of the component that will be appended to the baseName.
|
|
1624
|
+
* @returns {string} - Unique string to be used for naming.
|
|
1625
|
+
*/
|
|
1626
|
+
generateElementName(baseName, version) {
|
|
1627
|
+
let result = baseName;
|
|
1501
1628
|
|
|
1502
|
-
|
|
1503
|
-
|
|
1504
|
-
values[index] = String(val);
|
|
1505
|
-
}
|
|
1506
|
-
});
|
|
1629
|
+
result += '-';
|
|
1630
|
+
result += version.replace(/[.]/g, '_');
|
|
1507
1631
|
|
|
1508
|
-
|
|
1509
|
-
return values;
|
|
1632
|
+
return result;
|
|
1510
1633
|
}
|
|
1511
1634
|
|
|
1512
1635
|
/**
|
|
1513
|
-
*
|
|
1514
|
-
* @param {
|
|
1515
|
-
* @param {
|
|
1516
|
-
* @returns {
|
|
1636
|
+
* Generates a unique string to be used for child auro element naming.
|
|
1637
|
+
* @param {string} baseName - Defines the first part of the unique element name.
|
|
1638
|
+
* @param {string} version - Version of the component that will be appended to the baseName.
|
|
1639
|
+
* @returns {string} - Unique string to be used for naming.
|
|
1517
1640
|
*/
|
|
1518
|
-
|
|
1519
|
-
|
|
1520
|
-
|
|
1521
|
-
const set1 = new Set(arr1);
|
|
1522
|
-
const set2 = new Set(arr2);
|
|
1641
|
+
generateTag(baseName, version, tagClass) {
|
|
1642
|
+
const elementName = this.generateElementName(baseName, version);
|
|
1643
|
+
const tag = literal`${unsafeStatic(elementName)}`;
|
|
1523
1644
|
|
|
1524
|
-
|
|
1525
|
-
|
|
1526
|
-
return false;
|
|
1527
|
-
}
|
|
1645
|
+
if (!customElements.get(elementName)) {
|
|
1646
|
+
customElements.define(elementName, class extends tagClass {});
|
|
1528
1647
|
}
|
|
1529
1648
|
|
|
1530
|
-
return
|
|
1649
|
+
return tag;
|
|
1531
1650
|
}
|
|
1532
1651
|
}
|
|
1533
1652
|
|
|
1534
|
-
const
|
|
1653
|
+
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)}getSlotText(t,a){const e=t.shadowRoot?.querySelector(`slot[name="${a}"]`);return (e?.assignedNodes({flatten:true})||[]).map(t=>t.textContent?.trim()).join(" ").trim()||null}}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>',g='<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" aria-hidden="true" role="img" style="min-width:100%;height:auto;fill:currentColor" viewBox="0 0 142 138" part="svg"><title id="tail-DEFAULT__title">Airplane tail default image with light gray color</title><path fill="url(#paint0_linear_9225_2069)" fill-rule="evenodd" d="M124.093 14.665a3.26 3.26 0 0 1 3.208 3.829L101.097 119.85c-.47 1.087-2.211 3.398-5.692 3.471l-.106.001-80.65.013A659230 659230 0 0 1 99.08 17.412c1.214-1.497 3.275-2.722 5.372-2.747z" clip-rule="evenodd"/><defs><linearGradient id="paint0_linear_9225_2069" x1="114.823" x2="60.061" y1="14.665" y2="123.335" gradientUnits="userSpaceOnUse"><stop offset=".5" stop-color="#707984"/><stop offset=".5" stop-color="#646E7B"/></linearGradient></defs></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 f=new Map,w=(t,a={})=>{const e=a.responseParser||(t=>t.text());return f.has(t)||f.set(t,fetch(t).then(e)),f.get(t)};var z=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;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;line-height:var(--ds-auro-icon-size)}.svgWrapper{height:var(--ds-auro-icon-size);width:var(--ds-auro-icon-size)}.svgWrapper [part=svg]{display:flex}.labelWrapper{margin-left:var(--ds-size-50, .25rem)}.labelWrapper ::slotted(*){line-height:inherit!important}
|
|
1654
|
+
`;class y extends m{constructor(){super(),this._initializeDefaults();}_initializeDefaults(){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 z}async fetchIcon(t,a){let e="";e="logos"===t?await w(`${this.uri}/${t}/${a}.svg`):await w(`${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=this.name?.startsWith("tail-")?g:u;this.svg=(new DOMParser).parseFromString(t,"text/html").body.querySelector("svg");}}}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}
|
|
1655
|
+
`;var M=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)}
|
|
1656
|
+
`;var _=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)}
|
|
1657
|
+
`;class k extends y{constructor(){super(),this._initializeDefaults();}_initializeDefaults(){this.variant=void 0,this.uri="https://cdn.jsdelivr.net/npm/@alaskaairux/icons@latest/dist",this.runtimeUtils=new p;}static get properties(){return {...y.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 [y.styles,M,z,_]}static register(t="auro-icon"){p.prototype.registerComponent(t,k);}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`
|
|
1658
|
+
<div class="componentWrapper">
|
|
1659
|
+
<div
|
|
1660
|
+
class="${classMap({svgWrapper:true})}"
|
|
1661
|
+
title="${ifDefined(this.title||void 0)}">
|
|
1662
|
+
<span aria-hidden="${ifDefined(this.ariaHidden||true)}" part="svg">
|
|
1663
|
+
${this.customSvg?html`
|
|
1664
|
+
<slot name="svg"></slot>
|
|
1665
|
+
`:html`
|
|
1666
|
+
${this.svg}
|
|
1667
|
+
`}
|
|
1668
|
+
</span>
|
|
1669
|
+
</div>
|
|
1535
1670
|
|
|
1536
|
-
|
|
1537
|
-
|
|
1671
|
+
<div class="${classMap(t)}" part="label">
|
|
1672
|
+
<slot></slot>
|
|
1673
|
+
</div>
|
|
1674
|
+
</div>
|
|
1675
|
+
`}}
|
|
1676
|
+
|
|
1677
|
+
var iconVersion = '9.1.2';
|
|
1678
|
+
|
|
1679
|
+
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>"};
|
|
1680
|
+
|
|
1681
|
+
// Copyright (c) 2021 Alaska Airlines. All right reserved. Licensed under the Apache-2.0 license
|
|
1538
1682
|
// See LICENSE in the project root for license information.
|
|
1539
1683
|
|
|
1540
1684
|
|
|
1685
|
+
let menuOptionIdCounter = 0;
|
|
1541
1686
|
|
|
1542
1687
|
/**
|
|
1543
|
-
* The `auro-
|
|
1544
|
-
* @customElement auro-
|
|
1688
|
+
* The `auro-menuoption` element provides users a way to define a menu option.
|
|
1689
|
+
* @customElement auro-menuoption
|
|
1545
1690
|
*
|
|
1546
|
-
* @
|
|
1547
|
-
*
|
|
1548
|
-
* @event
|
|
1549
|
-
* @event {CustomEvent<any>} auroMenu-selectValueFailure - Notifies that an attempt to select a menuoption by matching a value has failed.
|
|
1550
|
-
* @event {CustomEvent<{ values: HTMLElement[] }>} auroMenu-deselectPrevented - Notifies that deselection was prevented and includes the affected options in `detail.values`.
|
|
1551
|
-
* @event {CustomEvent<any>} auroMenu-selectValueReset - Notifies that the component value has been reset.
|
|
1552
|
-
* @event {CustomEvent<any>} auroMenu-selectedOption - Notifies that a new menuoption selection has been made.
|
|
1553
|
-
* @slot loadingText - Text to show while loading attribute is set
|
|
1554
|
-
* @slot loadingIcon - Icon to show while loading attribute is set
|
|
1555
|
-
* @slot - Slot for insertion of menu options.
|
|
1691
|
+
* @slot default - The default slot for the menu option text.
|
|
1692
|
+
*
|
|
1693
|
+
* @event auroMenuOption-mouseover - Notifies that this option has been hovered over.
|
|
1556
1694
|
*/
|
|
1695
|
+
class AuroMenuOption extends AuroElement {
|
|
1557
1696
|
|
|
1558
|
-
|
|
1697
|
+
/**
|
|
1698
|
+
* This will register this element with the browser.
|
|
1699
|
+
* @param {string} [name="auro-menuoption"] - The name of the element that you want to register.
|
|
1700
|
+
*
|
|
1701
|
+
* @example
|
|
1702
|
+
* AuroMenuOption.register("custom-menuoption") // this will register this element to <custom-menuoption/>
|
|
1703
|
+
*
|
|
1704
|
+
*/
|
|
1705
|
+
static register(name = "auro-menuoption") {
|
|
1706
|
+
AuroLibraryRuntimeUtils.prototype.registerComponent(name, AuroMenuOption);
|
|
1707
|
+
}
|
|
1559
1708
|
|
|
1560
|
-
|
|
1709
|
+
/**
|
|
1710
|
+
* Returns whether the menu option is currently active and selectable.
|
|
1711
|
+
* An option is considered active if it is not hidden, not disabled, and not static.
|
|
1712
|
+
* @returns {boolean} True if the option is active, false otherwise.
|
|
1713
|
+
*/
|
|
1714
|
+
get isActive() {
|
|
1715
|
+
return !this.hasAttribute('hidden') &&
|
|
1716
|
+
!this.disabled &&
|
|
1717
|
+
!this.hasAttribute('static');
|
|
1718
|
+
}
|
|
1561
1719
|
|
|
1562
1720
|
constructor() {
|
|
1563
1721
|
super();
|
|
1564
1722
|
|
|
1565
|
-
|
|
1723
|
+
this.bindEvents();
|
|
1566
1724
|
|
|
1567
1725
|
/**
|
|
1568
1726
|
* @private
|
|
1569
1727
|
*/
|
|
1570
|
-
this.shape =
|
|
1728
|
+
this.shape = undefined;
|
|
1571
1729
|
|
|
1572
1730
|
/**
|
|
1573
1731
|
* @private
|
|
1574
1732
|
*/
|
|
1575
|
-
this.size =
|
|
1576
|
-
|
|
1577
|
-
// Value of the selected options
|
|
1578
|
-
this.value = undefined;
|
|
1579
|
-
// Currently selected option
|
|
1580
|
-
this.optionSelected = undefined;
|
|
1581
|
-
// String used for highlighting/filtering
|
|
1582
|
-
this.matchWord = undefined;
|
|
1583
|
-
// Hide the checkmark icon on selected options
|
|
1584
|
-
this.noCheckmark = false;
|
|
1585
|
-
// Currently active option
|
|
1586
|
-
this.optionActive = undefined;
|
|
1587
|
-
// Loading state
|
|
1588
|
-
this.loading = false;
|
|
1589
|
-
// Multi-select mode
|
|
1590
|
-
this.multiSelect = false;
|
|
1591
|
-
// Allow deselecting of menu options
|
|
1592
|
-
this.allowDeselect = false;
|
|
1593
|
-
// Select all matching options when setting value in multi-select mode
|
|
1594
|
-
this.selectAllMatchingOptions = false;
|
|
1595
|
-
|
|
1596
|
-
// Event Bindings
|
|
1733
|
+
this.size = undefined;
|
|
1597
1734
|
|
|
1598
1735
|
/**
|
|
1599
|
-
*
|
|
1736
|
+
* Generate unique names for dependency components.
|
|
1600
1737
|
*/
|
|
1601
|
-
|
|
1738
|
+
const versioning = new AuroDependencyVersioning();
|
|
1739
|
+
this.iconTag = versioning.generateTag('auro-formkit-menuoption-icon', iconVersion, k);
|
|
1602
1740
|
|
|
1603
|
-
|
|
1741
|
+
this.selected = false;
|
|
1742
|
+
this.noCheckmark = false;
|
|
1743
|
+
this.disabled = false;
|
|
1744
|
+
this.noMatch = false;
|
|
1604
1745
|
|
|
1605
1746
|
/**
|
|
1606
1747
|
* @private
|
|
1607
1748
|
*/
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1612
|
-
|
|
1613
|
-
|
|
1614
|
-
|
|
1615
|
-
|
|
1616
|
-
|
|
1617
|
-
|
|
1749
|
+
this.runtimeUtils = new AuroLibraryRuntimeUtils();
|
|
1750
|
+
|
|
1751
|
+
// Initialize context-related properties
|
|
1752
|
+
this.menuService = null;
|
|
1753
|
+
this.unsubscribe = null;
|
|
1754
|
+
|
|
1755
|
+
/**
|
|
1756
|
+
* @private
|
|
1757
|
+
*/
|
|
1758
|
+
this.handleMenuChange = this.handleMenuChange.bind(this);
|
|
1618
1759
|
}
|
|
1619
1760
|
|
|
1620
1761
|
static get properties() {
|
|
@@ -1622,15 +1763,7 @@ class AuroMenu extends AuroElement {
|
|
|
1622
1763
|
...super.properties,
|
|
1623
1764
|
|
|
1624
1765
|
/**
|
|
1625
|
-
*
|
|
1626
|
-
*/
|
|
1627
|
-
allowDeselect: {
|
|
1628
|
-
type: Boolean,
|
|
1629
|
-
reflect: true,
|
|
1630
|
-
},
|
|
1631
|
-
|
|
1632
|
-
/**
|
|
1633
|
-
* When true, the entire menu and all options are disabled.
|
|
1766
|
+
* When true, disables the menu option.
|
|
1634
1767
|
*/
|
|
1635
1768
|
disabled: {
|
|
1636
1769
|
type: Boolean,
|
|
@@ -1638,542 +1771,409 @@ class AuroMenu extends AuroElement {
|
|
|
1638
1771
|
},
|
|
1639
1772
|
|
|
1640
1773
|
/**
|
|
1641
|
-
* Indicates whether the menu has a loadingIcon or loadingText to render when in a loading state.
|
|
1642
|
-
*/
|
|
1643
|
-
hasLoadingPlaceholder: {
|
|
1644
|
-
type: Boolean
|
|
1645
|
-
},
|
|
1646
|
-
|
|
1647
|
-
/**
|
|
1648
|
-
* @private
|
|
1649
|
-
*/
|
|
1650
|
-
layout: {
|
|
1651
|
-
type: String
|
|
1652
|
-
},
|
|
1653
|
-
|
|
1654
|
-
/**
|
|
1655
|
-
* Indent level for submenus.
|
|
1656
1774
|
* @private
|
|
1657
1775
|
*/
|
|
1658
|
-
|
|
1659
|
-
type: Number,
|
|
1660
|
-
reflect: false,
|
|
1661
|
-
attribute: false
|
|
1662
|
-
},
|
|
1663
|
-
|
|
1664
|
-
/**
|
|
1665
|
-
* When true, displays a loading state using the loadingIcon and loadingText slots if provided.
|
|
1666
|
-
*/
|
|
1667
|
-
loading: {
|
|
1668
|
-
type: Boolean,
|
|
1669
|
-
reflect: true
|
|
1670
|
-
},
|
|
1671
|
-
|
|
1672
|
-
/**
|
|
1673
|
-
* Specifies a string used to highlight matched string parts in options.
|
|
1674
|
-
*/
|
|
1675
|
-
matchWord: {
|
|
1676
|
-
type: String,
|
|
1677
|
-
attribute: 'matchword'
|
|
1678
|
-
},
|
|
1679
|
-
|
|
1680
|
-
/**
|
|
1681
|
-
* When true, the selected option can be multiple options.
|
|
1682
|
-
*/
|
|
1683
|
-
multiSelect: {
|
|
1684
|
-
type: Boolean,
|
|
1685
|
-
reflect: true,
|
|
1686
|
-
attribute: 'multiselect'
|
|
1687
|
-
},
|
|
1688
|
-
|
|
1689
|
-
/**
|
|
1690
|
-
* When true, selected option will not show the checkmark.
|
|
1691
|
-
*/
|
|
1692
|
-
noCheckmark: {
|
|
1693
|
-
type: Boolean,
|
|
1694
|
-
reflect: true,
|
|
1695
|
-
attribute: 'nocheckmark'
|
|
1696
|
-
},
|
|
1697
|
-
|
|
1698
|
-
/**
|
|
1699
|
-
* Specifies the current active menuOption.
|
|
1700
|
-
*/
|
|
1701
|
-
optionActive: {
|
|
1702
|
-
type: Object,
|
|
1703
|
-
attribute: 'optionactive'
|
|
1704
|
-
},
|
|
1705
|
-
|
|
1706
|
-
/**
|
|
1707
|
-
* An array of currently selected menu options, type `HTMLElement` by default. In multi-select mode, `optionSelected` is an array of HTML elements.
|
|
1708
|
-
*/
|
|
1709
|
-
optionSelected: {
|
|
1710
|
-
// Allow HTMLElement, HTMLElement[] arrays and undefined
|
|
1711
|
-
type: Object
|
|
1712
|
-
},
|
|
1713
|
-
|
|
1714
|
-
/**
|
|
1715
|
-
* Available menu options.
|
|
1716
|
-
* @readonly
|
|
1717
|
-
*/
|
|
1718
|
-
options: {
|
|
1719
|
-
type: Array,
|
|
1720
|
-
reflect: false,
|
|
1721
|
-
attribute: false
|
|
1722
|
-
},
|
|
1723
|
-
|
|
1724
|
-
/**
|
|
1725
|
-
* Sets the size of the menu.
|
|
1726
|
-
* @type {'sm' | 'md'}
|
|
1727
|
-
* @default 'sm'
|
|
1728
|
-
*/
|
|
1729
|
-
size: {
|
|
1776
|
+
event: {
|
|
1730
1777
|
type: String,
|
|
1731
1778
|
reflect: true
|
|
1732
1779
|
},
|
|
1733
1780
|
|
|
1734
1781
|
/**
|
|
1735
|
-
*
|
|
1782
|
+
* @private
|
|
1736
1783
|
*/
|
|
1737
|
-
|
|
1738
|
-
type:
|
|
1739
|
-
reflect: true,
|
|
1784
|
+
layout: {
|
|
1785
|
+
type: String
|
|
1740
1786
|
},
|
|
1741
1787
|
|
|
1742
1788
|
/**
|
|
1743
|
-
*
|
|
1744
|
-
* @type {'box' | 'round'}
|
|
1745
|
-
* @default 'box'
|
|
1789
|
+
* Allows users to set a unique key for the menu option for specified option selection. If no key is provided, the value property will be used.
|
|
1746
1790
|
*/
|
|
1747
|
-
|
|
1791
|
+
key: {
|
|
1748
1792
|
type: String,
|
|
1749
1793
|
reflect: true
|
|
1750
1794
|
},
|
|
1751
1795
|
|
|
1752
1796
|
/**
|
|
1753
|
-
*
|
|
1797
|
+
* @private
|
|
1754
1798
|
*/
|
|
1755
|
-
|
|
1756
|
-
type:
|
|
1757
|
-
|
|
1758
|
-
|
|
1759
|
-
}
|
|
1760
|
-
};
|
|
1761
|
-
}
|
|
1762
|
-
|
|
1763
|
-
static get styles() {
|
|
1764
|
-
return [
|
|
1765
|
-
styleCss$1,
|
|
1766
|
-
colorCss$1,
|
|
1767
|
-
tokensCss
|
|
1768
|
-
];
|
|
1769
|
-
}
|
|
1770
|
-
|
|
1771
|
-
/**
|
|
1772
|
-
* @readonly
|
|
1773
|
-
* @returns {string} - Returns the label of the currently selected option(s).
|
|
1774
|
-
*/
|
|
1775
|
-
get currentLabel() {
|
|
1776
|
-
return this.menuService.currentLabel;
|
|
1777
|
-
};
|
|
1778
|
-
|
|
1779
|
-
/**
|
|
1780
|
-
* @readonly
|
|
1781
|
-
* @returns {Array<HTMLElement>} - Returns the array of available menu options.
|
|
1782
|
-
* @deprecated Use `options` property instead.
|
|
1783
|
-
*/
|
|
1784
|
-
get items() {
|
|
1785
|
-
return this.options;
|
|
1786
|
-
}
|
|
1787
|
-
|
|
1788
|
-
/**
|
|
1789
|
-
* @returns {number} - Returns the index of the currently active option.
|
|
1790
|
-
*/
|
|
1791
|
-
get index() {
|
|
1792
|
-
return this._index;
|
|
1793
|
-
}
|
|
1794
|
-
|
|
1795
|
-
/**
|
|
1796
|
-
* @param {number} value - Sets the index of the currently active option.
|
|
1797
|
-
*/
|
|
1798
|
-
set index(value) {
|
|
1799
|
-
this.menuService.setHighlightedIndex(value);
|
|
1800
|
-
}
|
|
1801
|
-
|
|
1802
|
-
/**
|
|
1803
|
-
* This will register this element with the browser.
|
|
1804
|
-
* @param {string} [name="auro-menu"] - The name of the element that you want to register.
|
|
1805
|
-
*
|
|
1806
|
-
* @example
|
|
1807
|
-
* AuroMenu.register("custom-menu") // this will register this element to <custom-menu/>
|
|
1808
|
-
*
|
|
1809
|
-
*/
|
|
1810
|
-
static register(name = "auro-menu") {
|
|
1811
|
-
AuroLibraryRuntimeUtils.prototype.registerComponent(name, AuroMenu);
|
|
1812
|
-
}
|
|
1813
|
-
|
|
1814
|
-
/**
|
|
1815
|
-
* Formatted value based on `multiSelect` state.
|
|
1816
|
-
* Default type is `String`, changing to `Array<String>` when `multiSelect` is true.
|
|
1817
|
-
* @private
|
|
1818
|
-
* @returns {String|Array<String>}
|
|
1819
|
-
*/
|
|
1820
|
-
get formattedValue() {
|
|
1821
|
-
return this.menuService.currentValue;
|
|
1822
|
-
}
|
|
1823
|
-
|
|
1824
|
-
/**
|
|
1825
|
-
* Gets the current property values for the menu service.
|
|
1826
|
-
* @private
|
|
1827
|
-
* @returns {Object}
|
|
1828
|
-
*/
|
|
1829
|
-
get propertyValues() {
|
|
1830
|
-
return {
|
|
1831
|
-
size: this.size,
|
|
1832
|
-
shape: this.shape,
|
|
1833
|
-
noCheckmark: this.nocheckmark,
|
|
1834
|
-
disabled: this.disabled
|
|
1835
|
-
};
|
|
1836
|
-
}
|
|
1837
|
-
|
|
1838
|
-
/**
|
|
1839
|
-
* Provides the menu context to child components.
|
|
1840
|
-
* Initializes the MenuService and subscribes to menu changes.
|
|
1841
|
-
* @protected
|
|
1842
|
-
*/
|
|
1843
|
-
provideContext() {
|
|
1844
|
-
if (this.parentElement && this.parentElement.closest('auro-menu, [auro-menu]')) {
|
|
1845
|
-
this.rootMenu = false;
|
|
1846
|
-
this.menuService = this.parentElement.menuService;
|
|
1847
|
-
this._contextProvider = this.parentElement._contextProvider;
|
|
1848
|
-
return;
|
|
1849
|
-
}
|
|
1850
|
-
|
|
1851
|
-
this.menuService = new MenuService({host: this});
|
|
1852
|
-
this.menuService.setProperties(this.propertyValues);
|
|
1853
|
-
this.menuService.subscribe(this.handleMenuChange.bind(this));
|
|
1854
|
-
this._contextProvider = new ContextProvider(this, {
|
|
1855
|
-
context: MenuContext,
|
|
1856
|
-
initialValue: this.menuService
|
|
1857
|
-
});
|
|
1858
|
-
}
|
|
1859
|
-
|
|
1860
|
-
/**
|
|
1861
|
-
* Updates the currently active option in the menu.
|
|
1862
|
-
* @param {HTMLElement} option - The option to set as active.
|
|
1863
|
-
*/
|
|
1864
|
-
updateActiveOption(option) {
|
|
1865
|
-
this.menuService.setHighlightedOption(option);
|
|
1866
|
-
}
|
|
1867
|
-
|
|
1868
|
-
/**
|
|
1869
|
-
* Sets the internal value and manages update state.
|
|
1870
|
-
* @param {String|Array<String>} value - The value to set.
|
|
1871
|
-
* @protected
|
|
1872
|
-
*/
|
|
1873
|
-
setInternalValue(value) {
|
|
1874
|
-
if (this.value !== value) {
|
|
1875
|
-
this.internalUpdateInProgress = true;
|
|
1876
|
-
this.value = value;
|
|
1877
|
-
|
|
1878
|
-
setTimeout(() => {
|
|
1879
|
-
this.internalUpdateInProgress = false;
|
|
1880
|
-
});
|
|
1881
|
-
}
|
|
1882
|
-
}
|
|
1883
|
-
|
|
1884
|
-
/**
|
|
1885
|
-
* Handles changes from the menu service and updates component state.
|
|
1886
|
-
* @param {Object} event - The event object from the menu service.
|
|
1887
|
-
* @protected
|
|
1888
|
-
*/
|
|
1889
|
-
handleMenuChange(event) {
|
|
1890
|
-
if (event.type === 'valueChange') {
|
|
1799
|
+
menuService: {
|
|
1800
|
+
type: Object,
|
|
1801
|
+
state: true
|
|
1802
|
+
},
|
|
1891
1803
|
|
|
1892
|
-
|
|
1893
|
-
|
|
1894
|
-
|
|
1804
|
+
/**
|
|
1805
|
+
* @private
|
|
1806
|
+
*/
|
|
1807
|
+
matchWord: {
|
|
1808
|
+
type: String,
|
|
1809
|
+
state: true
|
|
1810
|
+
},
|
|
1895
1811
|
|
|
1896
|
-
|
|
1897
|
-
|
|
1898
|
-
|
|
1899
|
-
|
|
1900
|
-
|
|
1812
|
+
/**
|
|
1813
|
+
* @private
|
|
1814
|
+
*/
|
|
1815
|
+
noCheckmark: {
|
|
1816
|
+
type: Boolean,
|
|
1817
|
+
reflect: true
|
|
1818
|
+
},
|
|
1901
1819
|
|
|
1902
|
-
|
|
1903
|
-
|
|
1904
|
-
|
|
1820
|
+
/**
|
|
1821
|
+
* When true, marks this option as the "no matching results" placeholder shown by combobox when the user's input does not match any available options. Enables distinct styling and prevents the option from being treated as a selectable match.
|
|
1822
|
+
*/
|
|
1823
|
+
noMatch: {
|
|
1824
|
+
type: Boolean,
|
|
1825
|
+
reflect: true,
|
|
1826
|
+
attribute: 'nomatch'
|
|
1827
|
+
},
|
|
1905
1828
|
|
|
1906
|
-
|
|
1907
|
-
|
|
1908
|
-
|
|
1909
|
-
|
|
1829
|
+
/**
|
|
1830
|
+
* Specifies that an option is selected.
|
|
1831
|
+
*/
|
|
1832
|
+
selected: {
|
|
1833
|
+
type: Boolean,
|
|
1834
|
+
reflect: true
|
|
1835
|
+
},
|
|
1910
1836
|
|
|
1911
|
-
|
|
1912
|
-
|
|
1913
|
-
|
|
1914
|
-
|
|
1915
|
-
|
|
1916
|
-
|
|
1917
|
-
}
|
|
1918
|
-
}
|
|
1919
|
-
}
|
|
1837
|
+
/**
|
|
1838
|
+
* Specifies the tab index of the menu option.
|
|
1839
|
+
*/
|
|
1840
|
+
tabIndex: {
|
|
1841
|
+
type: Number,
|
|
1842
|
+
reflect: true
|
|
1843
|
+
},
|
|
1920
1844
|
|
|
1921
|
-
|
|
1922
|
-
|
|
1923
|
-
|
|
1924
|
-
|
|
1925
|
-
|
|
1926
|
-
|
|
1845
|
+
/**
|
|
1846
|
+
* Specifies the value to be sent to a server.
|
|
1847
|
+
*/
|
|
1848
|
+
value: {
|
|
1849
|
+
type: String,
|
|
1850
|
+
reflect: true
|
|
1851
|
+
},
|
|
1852
|
+
};
|
|
1927
1853
|
}
|
|
1928
1854
|
|
|
1929
|
-
|
|
1930
|
-
|
|
1931
|
-
|
|
1932
|
-
|
|
1933
|
-
|
|
1934
|
-
|
|
1855
|
+
static get styles() {
|
|
1856
|
+
return [
|
|
1857
|
+
styleCss,
|
|
1858
|
+
colorCss,
|
|
1859
|
+
tokensCss
|
|
1860
|
+
];
|
|
1935
1861
|
}
|
|
1936
1862
|
|
|
1937
|
-
// Lifecycle Methods
|
|
1938
|
-
|
|
1939
1863
|
connectedCallback() {
|
|
1940
1864
|
super.connectedCallback();
|
|
1941
1865
|
|
|
1942
|
-
|
|
1943
|
-
|
|
1944
|
-
|
|
1945
|
-
this.addEventListener('auroMenuOption-click', this.handleMouseSelect);
|
|
1946
|
-
this.addEventListener('auroMenuOption-mouseover', this.handleOptionHover);
|
|
1947
|
-
this.addEventListener('slotchange', this.handleSlotChange);
|
|
1948
|
-
this.setTagAttribute("auro-menu");
|
|
1949
|
-
}
|
|
1866
|
+
// Add the tag name as an attribute if it is different than the component name
|
|
1867
|
+
// Add this step soon as this node gets attached to the DOM to avoid racing condition with menu's value setting logic.
|
|
1868
|
+
this.runtimeUtils.handleComponentTagRename(this, 'auro-menuoption');
|
|
1950
1869
|
|
|
1951
|
-
|
|
1952
|
-
|
|
1953
|
-
|
|
1954
|
-
|
|
1955
|
-
|
|
1870
|
+
// Set up context consumption in connectedCallback
|
|
1871
|
+
this._contextConsumer = new ContextConsumer(this, {
|
|
1872
|
+
context: MenuContext,
|
|
1873
|
+
callback: this.attachTo.bind(this),
|
|
1874
|
+
subscribe: true
|
|
1875
|
+
});
|
|
1956
1876
|
|
|
1957
|
-
|
|
1877
|
+
// Establish the key property as early as possible.
|
|
1878
|
+
// When a framework (e.g. Svelte) inserts the element into the DOM before
|
|
1879
|
+
// setting its `value` property, both `getAttribute('value')` and
|
|
1880
|
+
// `getAttribute('key')` return null here. Setting `this.key = null`
|
|
1881
|
+
// would block the fallback in `updated()` that assigns key from the
|
|
1882
|
+
// value property (the guard checked `=== undefined`). Only assign key
|
|
1883
|
+
// if at least one source attribute is actually present so that the
|
|
1884
|
+
// `updated()` fallback can run when the value property arrives later.
|
|
1885
|
+
const valueAttr = this.getAttribute('value');
|
|
1886
|
+
const keyAttr = this.getAttribute('key');
|
|
1887
|
+
const resolvedKey = keyAttr !== null ? keyAttr : valueAttr;
|
|
1888
|
+
if (resolvedKey !== null) {
|
|
1889
|
+
this.key = resolvedKey;
|
|
1890
|
+
}
|
|
1958
1891
|
}
|
|
1959
1892
|
|
|
1960
1893
|
firstUpdated() {
|
|
1961
|
-
|
|
1894
|
+
// Add the tag name as an attribute if it is different than the component name
|
|
1895
|
+
this.runtimeUtils.handleComponentTagRename(this, 'auro-menuoption');
|
|
1962
1896
|
|
|
1963
|
-
|
|
1964
|
-
this.
|
|
1965
|
-
|
|
1897
|
+
// Generate unique ID if not already set (required for aria-activedescendant)
|
|
1898
|
+
if (!this.id) {
|
|
1899
|
+
menuOptionIdCounter += 1;
|
|
1900
|
+
this.id = `menuoption-${menuOptionIdCounter}`;
|
|
1901
|
+
}
|
|
1902
|
+
|
|
1903
|
+
this.setAttribute('role', 'option');
|
|
1904
|
+
this.setAttribute('aria-selected', 'false');
|
|
1966
1905
|
|
|
1906
|
+
this.addEventListener('mouseover', () => {
|
|
1907
|
+
this.dispatchEvent(new CustomEvent('auroMenuOption-mouseover', {
|
|
1908
|
+
bubbles: true,
|
|
1909
|
+
cancelable: false,
|
|
1910
|
+
composed: true,
|
|
1911
|
+
detail: this
|
|
1912
|
+
}));
|
|
1913
|
+
});
|
|
1914
|
+
}
|
|
1967
1915
|
|
|
1968
1916
|
updated(changedProperties) {
|
|
1969
1917
|
super.updated(changedProperties);
|
|
1970
1918
|
|
|
1971
|
-
//
|
|
1972
|
-
|
|
1973
|
-
// no longer calls reset() first, so the destructive intermediate-event
|
|
1974
|
-
// cascade that originally required deferral is eliminated. If option
|
|
1975
|
-
// keys are not yet resolved (framework mount-order race), selectByValue
|
|
1976
|
-
// queues a bounded retry automatically via queuePendingValue.
|
|
1977
|
-
if (changedProperties.has('value') && !this.internalUpdateInProgress) {
|
|
1978
|
-
this.menuService.selectByValue(this.value);
|
|
1979
|
-
}
|
|
1919
|
+
// Update aria-selected attribute if selected changed
|
|
1920
|
+
if (changedProperties.has('selected')) {
|
|
1980
1921
|
|
|
1981
|
-
|
|
1982
|
-
|
|
1983
|
-
|
|
1922
|
+
// Update aria-selected attribute
|
|
1923
|
+
this.setAttribute('aria-selected', this.selected.toString());
|
|
1924
|
+
|
|
1925
|
+
// Update menu service selection state if this isn't an internal update
|
|
1926
|
+
if (this.internalUpdateInProgress !== true && this.menuService) {
|
|
1927
|
+
this.menuService[this.selected ? 'selectOption' : 'deselectOption'](this);
|
|
1928
|
+
}
|
|
1984
1929
|
}
|
|
1985
1930
|
|
|
1986
|
-
if (changedProperties.has('
|
|
1987
|
-
if (this.
|
|
1988
|
-
this.setAttribute('aria-
|
|
1931
|
+
if (changedProperties.has('disabled')) {
|
|
1932
|
+
if (this.disabled) {
|
|
1933
|
+
this.setAttribute('aria-disabled', 'true');
|
|
1989
1934
|
} else {
|
|
1990
|
-
this.removeAttribute('aria-
|
|
1935
|
+
this.removeAttribute('aria-disabled');
|
|
1991
1936
|
}
|
|
1992
1937
|
}
|
|
1938
|
+
|
|
1939
|
+
if (changedProperties.has('active')) {
|
|
1940
|
+
this.updateActiveClasses();
|
|
1941
|
+
}
|
|
1942
|
+
|
|
1943
|
+
// Update text highlight if matchWord changed
|
|
1944
|
+
if (changedProperties.has('matchWord')) {
|
|
1945
|
+
this.updateTextHighlight();
|
|
1946
|
+
}
|
|
1947
|
+
|
|
1948
|
+
// Set the key to be the passed value if no key is provided.
|
|
1949
|
+
// Loose equality (== null) is intentional: it catches both null AND
|
|
1950
|
+
// undefined. When a framework (e.g. Svelte, React) inserts the element
|
|
1951
|
+
// before setting its value property, connectedCallback skips key
|
|
1952
|
+
// assignment because both attributes are null at that point. The Lit
|
|
1953
|
+
// property default for `key` is undefined (not null), so strict
|
|
1954
|
+
// === null would miss the case and the fallback would never run.
|
|
1955
|
+
if (changedProperties.has('value') && this.key == null) { // eslint-disable-line eqeqeq, no-eq-null
|
|
1956
|
+
this.key = this.value;
|
|
1957
|
+
}
|
|
1958
|
+
}
|
|
1959
|
+
|
|
1960
|
+
disconnectedCallback() {
|
|
1961
|
+
if (this.menuService) {
|
|
1962
|
+
this.menuService.unsubscribe(this.handleMenuChange);
|
|
1963
|
+
this.menuService.removeMenuOption(this);
|
|
1964
|
+
}
|
|
1993
1965
|
}
|
|
1994
1966
|
|
|
1995
1967
|
/**
|
|
1996
|
-
* Sets
|
|
1997
|
-
*
|
|
1998
|
-
* @private
|
|
1968
|
+
* Sets up event listeners for user interaction with the menu option.
|
|
1969
|
+
* This function enables click and mouse enter events to trigger selection and highlighting logic.
|
|
1999
1970
|
*/
|
|
2000
|
-
|
|
2001
|
-
|
|
2002
|
-
|
|
2003
|
-
}
|
|
1971
|
+
bindEvents() {
|
|
1972
|
+
this.addEventListener('click', this.handleClick.bind(this));
|
|
1973
|
+
this.addEventListener('mouseenter', this.handleMouseEnter.bind(this));
|
|
2004
1974
|
}
|
|
2005
1975
|
|
|
2006
1976
|
/**
|
|
2007
|
-
*
|
|
2008
|
-
*
|
|
2009
|
-
* @
|
|
1977
|
+
* Attaches this menu option to a menu service and subscribes to its events.
|
|
1978
|
+
* This method enables the option to participate in menu selection and highlighting logic.
|
|
1979
|
+
* @param {Object} service - The menu service instance to attach to.
|
|
2010
1980
|
*/
|
|
2011
|
-
|
|
2012
|
-
|
|
2013
|
-
|
|
2014
|
-
|
|
2015
|
-
|
|
2016
|
-
|
|
1981
|
+
attachTo(service) {
|
|
1982
|
+
if (!service) {
|
|
1983
|
+
return;
|
|
1984
|
+
}
|
|
1985
|
+
this.menuService = service;
|
|
1986
|
+
this.menuService.addMenuOption(this);
|
|
1987
|
+
this.menuService.subscribe(this.handleMenuChange);
|
|
2017
1988
|
}
|
|
2018
1989
|
|
|
2019
|
-
|
|
1990
|
+
/**
|
|
1991
|
+
* Handles changes from the menu service and updates the option's state.
|
|
1992
|
+
* This function synchronizes the option's properties and selection/highlight state with menu events.
|
|
1993
|
+
* @param {Object} event - The event object from the menu service.
|
|
1994
|
+
*/
|
|
1995
|
+
handleMenuChange(event) {
|
|
1996
|
+
|
|
1997
|
+
// Ignore events without a type or property
|
|
1998
|
+
if (!event || (!event.type && !event.property)) {
|
|
1999
|
+
return;
|
|
2000
|
+
}
|
|
2001
|
+
|
|
2002
|
+
// Update reactive properties based on event type
|
|
2003
|
+
if (event.property && Object.keys(AuroMenuOption.properties).includes(event.property)) {
|
|
2004
|
+
this[event.property] = event.value;
|
|
2005
|
+
}
|
|
2006
|
+
|
|
2007
|
+
// Handle highlight changes
|
|
2008
|
+
if (event.type === 'highlightChange') {
|
|
2009
|
+
const isActive = event.option === this;
|
|
2010
|
+
this.active = isActive;
|
|
2011
|
+
this.updateActiveClasses();
|
|
2012
|
+
}
|
|
2013
|
+
|
|
2014
|
+
if (event.type === 'stateChange') {
|
|
2015
|
+
const isSelected = event.selectedOptions.includes(this);
|
|
2016
|
+
this.setInternalSelected(isSelected);
|
|
2017
|
+
}
|
|
2018
|
+
}
|
|
2020
2019
|
|
|
2021
2020
|
/**
|
|
2022
|
-
*
|
|
2023
|
-
*
|
|
2021
|
+
* Updates the internal selected state of the menu option bypassing 'updated' and triggers custom events if selected.
|
|
2022
|
+
* This function ensures the option's selection state is synchronized with menu logic and notifies listeners.
|
|
2023
|
+
* @param {boolean} isSelected - Whether the option should be marked as selected.
|
|
2024
2024
|
*/
|
|
2025
|
-
|
|
2026
|
-
|
|
2027
|
-
|
|
2028
|
-
this.setAttribute('root', '');
|
|
2025
|
+
setInternalSelected(isSelected) {
|
|
2026
|
+
this.internalUpdateInProgress = true;
|
|
2027
|
+
this.selected = isSelected;
|
|
2029
2028
|
|
|
2030
|
-
|
|
2031
|
-
|
|
2032
|
-
|
|
2029
|
+
// Fire custom event if selected
|
|
2030
|
+
if (isSelected) {
|
|
2031
|
+
this.handleCustomEvent();
|
|
2033
2032
|
}
|
|
2034
2033
|
|
|
2035
|
-
|
|
2034
|
+
setTimeout(() => {
|
|
2035
|
+
this.internalUpdateInProgress = false;
|
|
2036
|
+
}, 0);
|
|
2036
2037
|
}
|
|
2037
2038
|
|
|
2038
2039
|
/**
|
|
2039
|
-
*
|
|
2040
|
-
*
|
|
2040
|
+
* Sets the selected state of the menu option.
|
|
2041
|
+
* This function updates whether the option is currently selected.
|
|
2042
|
+
* @param {boolean} isSelected - Whether the option should be marked as selected.
|
|
2043
|
+
* @deprecated Simply modify the `selected` property directly instead.
|
|
2041
2044
|
*/
|
|
2042
|
-
|
|
2043
|
-
this.
|
|
2045
|
+
setSelected(isSelected) {
|
|
2046
|
+
this.selected = isSelected;
|
|
2044
2047
|
}
|
|
2045
2048
|
|
|
2046
2049
|
/**
|
|
2047
|
-
*
|
|
2048
|
-
*
|
|
2050
|
+
* Updates the active state and visual highlighting of the menu option.
|
|
2051
|
+
* This function toggles the option's active status and applies or removes the active CSS class.
|
|
2052
|
+
* @param {boolean} isActive - Whether the option should be marked as active.
|
|
2053
|
+
* @deprecated Simply modify the `active` property directly instead.
|
|
2049
2054
|
*/
|
|
2050
|
-
|
|
2051
|
-
|
|
2052
|
-
|
|
2053
|
-
this.
|
|
2055
|
+
updateActive(isActive) {
|
|
2056
|
+
|
|
2057
|
+
// Set active state
|
|
2058
|
+
this.active = isActive;
|
|
2059
|
+
this.updateActiveClasses();
|
|
2054
2060
|
}
|
|
2055
2061
|
|
|
2056
2062
|
/**
|
|
2057
|
-
*
|
|
2058
|
-
* This
|
|
2059
|
-
* @
|
|
2063
|
+
* Updates the CSS class for the menu option based on its active state.
|
|
2064
|
+
* This function adds or removes the 'active' class to visually indicate the option's active status.
|
|
2065
|
+
* @private
|
|
2060
2066
|
*/
|
|
2061
|
-
|
|
2062
|
-
|
|
2063
|
-
|
|
2064
|
-
|
|
2065
|
-
dispatchMenuEvent(this, 'auroMenu-selectValueReset');
|
|
2067
|
+
updateActiveClasses() {
|
|
2068
|
+
// Update class based on active state
|
|
2069
|
+
if (this.active) this.classList.add('active');
|
|
2070
|
+
else this.classList.remove('active');
|
|
2066
2071
|
}
|
|
2067
2072
|
|
|
2073
|
+
|
|
2068
2074
|
/**
|
|
2069
|
-
*
|
|
2075
|
+
* Updates the visual highlighting of text within the menu option based on the current match word.
|
|
2076
|
+
* This function highlights matching text segments and manages nested spacers for display formatting.
|
|
2070
2077
|
* @private
|
|
2071
|
-
* @param {HTMLElement} menu - Root menu element.
|
|
2072
2078
|
*/
|
|
2073
|
-
|
|
2074
|
-
menu.level = menu.parentElement.level >= 0 ? menu.parentElement.level + 1 : 0;
|
|
2079
|
+
updateTextHighlight() {
|
|
2075
2080
|
|
|
2076
|
-
|
|
2077
|
-
|
|
2078
|
-
|
|
2079
|
-
|
|
2080
|
-
|
|
2081
|
-
|
|
2081
|
+
// Regex for matchWord if needed
|
|
2082
|
+
let regexWord = null;
|
|
2083
|
+
|
|
2084
|
+
if (this.matchWord && this.matchWord.length) {
|
|
2085
|
+
const escapedWord = this.matchWord.replace(/[.*+?^${}()|[\]\\]/gu, '\\$&');
|
|
2086
|
+
regexWord = new RegExp(escapedWord, 'giu');
|
|
2082
2087
|
}
|
|
2083
2088
|
|
|
2084
|
-
|
|
2085
|
-
|
|
2086
|
-
|
|
2087
|
-
|
|
2088
|
-
});
|
|
2089
|
-
}
|
|
2089
|
+
// Update text highlighting if matchWord changed
|
|
2090
|
+
if (regexWord &&
|
|
2091
|
+
this.isActive && !this.hasAttribute('persistent')) {
|
|
2092
|
+
const nested = this.querySelectorAll('.nestingSpacer');
|
|
2090
2093
|
|
|
2091
|
-
|
|
2092
|
-
|
|
2093
|
-
|
|
2094
|
-
|
|
2095
|
-
*/
|
|
2096
|
-
navigateOptions(direction) {
|
|
2097
|
-
if (direction === 'up') {
|
|
2098
|
-
this.menuService.highlightPrevious();
|
|
2099
|
-
} else if (direction === 'down') {
|
|
2100
|
-
this.menuService.highlightNext();
|
|
2101
|
-
}
|
|
2102
|
-
}
|
|
2094
|
+
const displayValueEl = this.querySelector('[slot="displayValue"]');
|
|
2095
|
+
if (displayValueEl) {
|
|
2096
|
+
this.removeChild(displayValueEl);
|
|
2097
|
+
}
|
|
2103
2098
|
|
|
2104
|
-
|
|
2105
|
-
|
|
2106
|
-
|
|
2107
|
-
|
|
2108
|
-
|
|
2109
|
-
|
|
2110
|
-
|
|
2099
|
+
// Create nested spacers
|
|
2100
|
+
const nestingSpacerBundle = [...nested].map(() => this.nestingSpacer).join('');
|
|
2101
|
+
|
|
2102
|
+
// Update with spacers and matchWord
|
|
2103
|
+
this.innerHTML = nestingSpacerBundle +
|
|
2104
|
+
this.textContent.replace(
|
|
2105
|
+
regexWord,
|
|
2106
|
+
(match) => `<strong>${match}</strong>`
|
|
2107
|
+
);
|
|
2108
|
+
if (displayValueEl) {
|
|
2109
|
+
this.append(displayValueEl);
|
|
2110
|
+
}
|
|
2111
2111
|
}
|
|
2112
2112
|
}
|
|
2113
2113
|
|
|
2114
2114
|
/**
|
|
2115
|
-
* Handles
|
|
2115
|
+
* Handles click events on the menu option, toggling its selected state.
|
|
2116
|
+
* This function dispatches a click event and updates selection if the option is not disabled.
|
|
2116
2117
|
* @private
|
|
2117
|
-
* @param {HTMLElement} option - Option with custom event.
|
|
2118
2118
|
*/
|
|
2119
|
-
|
|
2120
|
-
|
|
2121
|
-
|
|
2122
|
-
|
|
2119
|
+
handleClick() {
|
|
2120
|
+
if (!this.disabled) {
|
|
2121
|
+
this.dispatchClickEvent();
|
|
2122
|
+
this.selected = !this.selected;
|
|
2123
|
+
}
|
|
2123
2124
|
}
|
|
2124
2125
|
|
|
2125
2126
|
/**
|
|
2126
|
-
*
|
|
2127
|
-
*
|
|
2127
|
+
* Handles mouse enter events to highlight the menu option.
|
|
2128
|
+
* This function updates the menu service to set this option as the currently highlighted item if not disabled.
|
|
2128
2129
|
* @private
|
|
2129
2130
|
*/
|
|
2130
|
-
|
|
2131
|
-
|
|
2132
|
-
|
|
2133
|
-
|
|
2134
|
-
keys,
|
|
2135
|
-
options,
|
|
2136
|
-
reason
|
|
2137
|
-
});
|
|
2131
|
+
handleMouseEnter() {
|
|
2132
|
+
if (!this.disabled) {
|
|
2133
|
+
this.menuService.setHighlightedOption(this);
|
|
2134
|
+
}
|
|
2138
2135
|
}
|
|
2139
2136
|
|
|
2140
2137
|
/**
|
|
2141
|
-
*
|
|
2138
|
+
* Dispatches custom events defined for this menu option.
|
|
2139
|
+
* This function notifies listeners when a custom event is triggered by the option.
|
|
2142
2140
|
* @private
|
|
2143
|
-
* @param {HTMLElement} option - The option to check.
|
|
2144
|
-
* @returns {boolean}
|
|
2145
2141
|
*/
|
|
2146
|
-
|
|
2147
|
-
if (
|
|
2148
|
-
|
|
2149
|
-
|
|
2150
|
-
|
|
2151
|
-
if (this.multiSelect) {
|
|
2152
|
-
// In multi-select mode, check if the option is in the selected array
|
|
2153
|
-
return Array.isArray(this.optionSelected) && this.optionSelected.some((selectedOption) => selectedOption === option);
|
|
2142
|
+
handleCustomEvent() {
|
|
2143
|
+
if (this.event) {
|
|
2144
|
+
dispatchMenuEvent(this, this.event, { option: this });
|
|
2145
|
+
dispatchMenuEvent(this, 'auroMenu-customEventFired', { option: this });
|
|
2154
2146
|
}
|
|
2155
|
-
|
|
2156
|
-
return this.optionSelected === option;
|
|
2157
2147
|
}
|
|
2158
2148
|
|
|
2159
2149
|
/**
|
|
2160
|
-
*
|
|
2161
|
-
*
|
|
2150
|
+
* Dispatches a click event for this menu option.
|
|
2151
|
+
* This function notifies listeners that the option has been clicked.
|
|
2152
|
+
* @private
|
|
2162
2153
|
*/
|
|
2163
|
-
|
|
2164
|
-
|
|
2154
|
+
dispatchClickEvent() {
|
|
2155
|
+
this.dispatchEvent(new CustomEvent('auroMenuOption-click', {
|
|
2156
|
+
bubbles: true,
|
|
2157
|
+
cancelable: false,
|
|
2158
|
+
composed: true,
|
|
2159
|
+
detail: this
|
|
2160
|
+
}));
|
|
2165
2161
|
}
|
|
2166
2162
|
|
|
2167
2163
|
/**
|
|
2168
|
-
*
|
|
2169
|
-
*
|
|
2164
|
+
* Generates an HTML element containing an SVG icon based on the provided `svgContent`.
|
|
2165
|
+
*
|
|
2170
2166
|
* @private
|
|
2167
|
+
* @param {string} svgContent - The SVG content to be embedded.
|
|
2168
|
+
* @returns {Element} The HTML element containing the SVG icon.
|
|
2171
2169
|
*/
|
|
2172
|
-
|
|
2173
|
-
|
|
2174
|
-
|
|
2175
|
-
|
|
2176
|
-
|
|
2170
|
+
generateIconHtml(svgContent) {
|
|
2171
|
+
const dom = new DOMParser().parseFromString(svgContent, 'text/html');
|
|
2172
|
+
const svg = dom.body.firstChild;
|
|
2173
|
+
|
|
2174
|
+
svg.setAttribute('slot', 'svg');
|
|
2175
|
+
|
|
2176
|
+
return html$1`<${this.iconTag} customColor customSvg>${svg}</${this.iconTag}>`;
|
|
2177
2177
|
}
|
|
2178
2178
|
|
|
2179
2179
|
/**
|
|
@@ -2182,26 +2182,26 @@ class AuroMenu extends AuroElement {
|
|
|
2182
2182
|
* @returns {void}
|
|
2183
2183
|
*/
|
|
2184
2184
|
renderLayout() {
|
|
2185
|
-
if (this.loading) {
|
|
2186
|
-
return html`
|
|
2187
|
-
<div class="${this.wrapperClasses}">
|
|
2188
|
-
<auro-menuoption
|
|
2189
|
-
disabled
|
|
2190
|
-
loadingplaceholder
|
|
2191
|
-
class="${this.hasLoadingPlaceholder ? "" : "empty"}"
|
|
2192
|
-
>
|
|
2193
|
-
<div>
|
|
2194
|
-
<slot name="loadingIcon" class="body-lg"></slot>
|
|
2195
|
-
<slot name="loadingText"></slot>
|
|
2196
|
-
</div>
|
|
2197
|
-
</auro-menuoption>
|
|
2198
|
-
</div>
|
|
2199
|
-
`;
|
|
2200
|
-
}
|
|
2201
2185
|
|
|
2202
|
-
|
|
2203
|
-
|
|
2204
|
-
|
|
2186
|
+
const fontClassMap = {
|
|
2187
|
+
xs: 'body-sm',
|
|
2188
|
+
sm: 'body-default',
|
|
2189
|
+
md: 'body-default',
|
|
2190
|
+
lg: 'body-lg',
|
|
2191
|
+
xl: 'body-lg'
|
|
2192
|
+
};
|
|
2193
|
+
|
|
2194
|
+
const classes = classMap({
|
|
2195
|
+
'wrapper': true,
|
|
2196
|
+
[this.size ? fontClassMap[this.size] : 'body-sm']: true,
|
|
2197
|
+
});
|
|
2198
|
+
|
|
2199
|
+
return html$1`
|
|
2200
|
+
<div class="${classes}">
|
|
2201
|
+
${this.selected && !this.noCheckmark
|
|
2202
|
+
? this.generateIconHtml(checkmarkIcon.svg)
|
|
2203
|
+
: undefined}
|
|
2204
|
+
<slot></slot>
|
|
2205
2205
|
</div>
|
|
2206
2206
|
`;
|
|
2207
2207
|
}
|