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