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