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