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