@m3e/nav-menu 1.0.0-rc.3 → 1.0.0-rc.4

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/dist/index.js CHANGED
@@ -3,9 +3,9 @@
3
3
  * Copyright (c) 2025 matraic
4
4
  * See LICENSE file in the project root for full license text.
5
5
  */
6
- import { LitElement, html, css, unsafeCSS } from 'lit';
7
- import { Role, scrollIntoViewIfNeeded, PressedController, FocusController, DesignToken, Selected, Disabled, EventAttribute, AttachInternals, hasAssignedNodes } from '@m3e/core';
8
- import { SelectionManager, selectionManager } from '@m3e/core/a11y';
6
+ import { LitElement, html, unsafeCSS, css } from 'lit';
7
+ import { Selected, Disabled, EventAttribute, AttachInternals, Role, DesignToken, hasAssignedNodes, scrollIntoViewIfNeeded, PressedController, FocusController } from '@m3e/core';
8
+ import { selectionManager, SelectionManager } from '@m3e/core/a11y';
9
9
 
10
10
  /******************************************************************************
11
11
  Copyright (c) Microsoft Corporation.
@@ -94,19 +94,60 @@ const e$2=(e,t,c)=>(c.configurable=true,c.enumerable=true,Reflect.decorate&&"obj
94
94
  * SPDX-License-Identifier: BSD-3-Clause
95
95
  */function e$1(e,r){return (n,s,i)=>{const o=t=>t.renderRoot?.querySelector(e)??null;return e$2(n,s,{get(){return o(this)}})}}
96
96
 
97
- var _M3eNavMenuElement_instances, _M3eNavMenuElement_ignoreFocusVisible, _M3eNavMenuElement_ignoreFocus, _M3eNavMenuElement_keyDownHandler, _M3eNavMenuElement_keyUpHandler, _M3eNavMenuElement_pointerDownHandler, _M3eNavMenuElement_handleSlotChange, _M3eNavMenuElement_handleKeyDown, _M3eNavMenuElement_handleKeyUp, _M3eNavMenuElement_handlePointerDown, _M3eNavMenuElement_activateItem, _M3eNavMenuElement_updateFocusVisible, _M3eNavMenuElement_updateItemFocusVisible, _b;
98
- var M3eNavMenuElement_1;
99
97
  /**
100
- * Presents a hierarchical menu.
98
+ * @license
99
+ * Copyright 2017 Google LLC
100
+ * SPDX-License-Identifier: BSD-3-Clause
101
+ */
102
+ const t=globalThis,i=t.trustedTypes,s=i?i.createPolicy("lit-html",{createHTML:t=>t}):void 0,e="$lit$",h=`lit$${Math.random().toFixed(9).slice(2)}$`,o$1="?"+h,n=`<${o$1}>`,r=document,l=()=>r.createComment(""),c=t=>null===t||"object"!=typeof t&&"function"!=typeof t,a=Array.isArray,u=t=>a(t)||"function"==typeof t?.[Symbol.iterator],d="[ \t\n\f\r]",f=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,v=/-->/g,_=/>/g,m=RegExp(`>|${d}(?:([^\\s"'>=/]+)(${d}*=${d}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`,"g"),p=/'/g,g=/"/g,$=/^(?:script|style|textarea|title)$/i,T=Symbol.for("lit-noChange"),E=Symbol.for("lit-nothing"),A=new WeakMap,C=r.createTreeWalker(r,129);function P(t,i){if(!a(t)||!t.hasOwnProperty("raw"))throw Error("invalid template strings array");return void 0!==s?s.createHTML(i):i}const V=(t,i)=>{const s=t.length-1,o=[];let r,l=2===i?"<svg>":3===i?"<math>":"",c=f;for(let i=0;i<s;i++){const s=t[i];let a,u,d=-1,y=0;for(;y<s.length&&(c.lastIndex=y,u=c.exec(s),null!==u);)y=c.lastIndex,c===f?"!--"===u[1]?c=v:void 0!==u[1]?c=_:void 0!==u[2]?($.test(u[2])&&(r=RegExp("</"+u[2],"g")),c=m):void 0!==u[3]&&(c=m):c===m?">"===u[0]?(c=r??f,d=-1):void 0===u[1]?d=-2:(d=c.lastIndex-u[2].length,a=u[1],c=void 0===u[3]?m:'"'===u[3]?g:p):c===g||c===p?c=m:c===v||c===_?c=f:(c=m,r=void 0);const x=c===m&&t[i+1].startsWith("/>")?" ":"";l+=c===f?s+n:d>=0?(o.push(a),s.slice(0,d)+e+s.slice(d)+h+x):s+h+(-2===d?i:x);}return [P(t,l+(t[s]||"<?>")+(2===i?"</svg>":3===i?"</math>":"")),o]};class N{constructor({strings:t,_$litType$:s},n){let r;this.parts=[];let c=0,a=0;const u=t.length-1,d=this.parts,[f,v]=V(t,s);if(this.el=N.createElement(f,n),C.currentNode=this.el.content,2===s||3===s){const t=this.el.content.firstChild;t.replaceWith(...t.childNodes);}for(;null!==(r=C.nextNode())&&d.length<u;){if(1===r.nodeType){if(r.hasAttributes())for(const t of r.getAttributeNames())if(t.endsWith(e)){const i=v[a++],s=r.getAttribute(t).split(h),e=/([.?@])?(.*)/.exec(i);d.push({type:1,index:c,name:e[2],strings:s,ctor:"."===e[1]?H:"?"===e[1]?I:"@"===e[1]?L:k}),r.removeAttribute(t);}else t.startsWith(h)&&(d.push({type:6,index:c}),r.removeAttribute(t));if($.test(r.tagName)){const t=r.textContent.split(h),s=t.length-1;if(s>0){r.textContent=i?i.emptyScript:"";for(let i=0;i<s;i++)r.append(t[i],l()),C.nextNode(),d.push({type:2,index:++c});r.append(t[s],l());}}}else if(8===r.nodeType)if(r.data===o$1)d.push({type:2,index:c});else {let t=-1;for(;-1!==(t=r.data.indexOf(h,t+1));)d.push({type:7,index:c}),t+=h.length-1;}c++;}}static createElement(t,i){const s=r.createElement("template");return s.innerHTML=t,s}}function S(t,i,s=t,e){if(i===T)return i;let h=void 0!==e?s._$Co?.[e]:s._$Cl;const o=c(i)?void 0:i._$litDirective$;return h?.constructor!==o&&(h?._$AO?.(false),void 0===o?h=void 0:(h=new o(t),h._$AT(t,s,e)),void 0!==e?(s._$Co??=[])[e]=h:s._$Cl=h),void 0!==h&&(i=S(t,h._$AS(t,i.values),h,e)),i}class M{constructor(t,i){this._$AV=[],this._$AN=void 0,this._$AD=t,this._$AM=i;}get parentNode(){return this._$AM.parentNode}get _$AU(){return this._$AM._$AU}u(t){const{el:{content:i},parts:s}=this._$AD,e=(t?.creationScope??r).importNode(i,true);C.currentNode=e;let h=C.nextNode(),o=0,n=0,l=s[0];for(;void 0!==l;){if(o===l.index){let i;2===l.type?i=new R(h,h.nextSibling,this,t):1===l.type?i=new l.ctor(h,l.name,l.strings,this,t):6===l.type&&(i=new z(h,this,t)),this._$AV.push(i),l=s[++n];}o!==l?.index&&(h=C.nextNode(),o++);}return C.currentNode=r,e}p(t){let i=0;for(const s of this._$AV) void 0!==s&&(void 0!==s.strings?(s._$AI(t,s,i),i+=s.strings.length-2):s._$AI(t[i])),i++;}}class R{get _$AU(){return this._$AM?._$AU??this._$Cv}constructor(t,i,s,e){this.type=2,this._$AH=E,this._$AN=void 0,this._$AA=t,this._$AB=i,this._$AM=s,this.options=e,this._$Cv=e?.isConnected??true;}get parentNode(){let t=this._$AA.parentNode;const i=this._$AM;return void 0!==i&&11===t?.nodeType&&(t=i.parentNode),t}get startNode(){return this._$AA}get endNode(){return this._$AB}_$AI(t,i=this){t=S(this,t,i),c(t)?t===E||null==t||""===t?(this._$AH!==E&&this._$AR(),this._$AH=E):t!==this._$AH&&t!==T&&this._(t):void 0!==t._$litType$?this.$(t):void 0!==t.nodeType?this.T(t):u(t)?this.k(t):this._(t);}O(t){return this._$AA.parentNode.insertBefore(t,this._$AB)}T(t){this._$AH!==t&&(this._$AR(),this._$AH=this.O(t));}_(t){this._$AH!==E&&c(this._$AH)?this._$AA.nextSibling.data=t:this.T(r.createTextNode(t)),this._$AH=t;}$(t){const{values:i,_$litType$:s}=t,e="number"==typeof s?this._$AC(t):(void 0===s.el&&(s.el=N.createElement(P(s.h,s.h[0]),this.options)),s);if(this._$AH?._$AD===e)this._$AH.p(i);else {const t=new M(e,this),s=t.u(this.options);t.p(i),this.T(s),this._$AH=t;}}_$AC(t){let i=A.get(t.strings);return void 0===i&&A.set(t.strings,i=new N(t)),i}k(t){a(this._$AH)||(this._$AH=[],this._$AR());const i=this._$AH;let s,e=0;for(const h of t)e===i.length?i.push(s=new R(this.O(l()),this.O(l()),this,this.options)):s=i[e],s._$AI(h),e++;e<i.length&&(this._$AR(s&&s._$AB.nextSibling,e),i.length=e);}_$AR(t=this._$AA.nextSibling,i){for(this._$AP?.(false,true,i);t!==this._$AB;){const i=t.nextSibling;t.remove(),t=i;}}setConnected(t){ void 0===this._$AM&&(this._$Cv=t,this._$AP?.(t));}}class k{get tagName(){return this.element.tagName}get _$AU(){return this._$AM._$AU}constructor(t,i,s,e,h){this.type=1,this._$AH=E,this._$AN=void 0,this.element=t,this.name=i,this._$AM=e,this.options=h,s.length>2||""!==s[0]||""!==s[1]?(this._$AH=Array(s.length-1).fill(new String),this.strings=s):this._$AH=E;}_$AI(t,i=this,s,e){const h=this.strings;let o=false;if(void 0===h)t=S(this,t,i,0),o=!c(t)||t!==this._$AH&&t!==T,o&&(this._$AH=t);else {const e=t;let n,r;for(t=h[0],n=0;n<h.length-1;n++)r=S(this,e[s+n],i,n),r===T&&(r=this._$AH[n]),o||=!c(r)||r!==this._$AH[n],r===E?t=E:t!==E&&(t+=(r??"")+h[n+1]),this._$AH[n]=r;}o&&!e&&this.j(t);}j(t){t===E?this.element.removeAttribute(this.name):this.element.setAttribute(this.name,t??"");}}class H extends k{constructor(){super(...arguments),this.type=3;}j(t){this.element[this.name]=t===E?void 0:t;}}class I extends k{constructor(){super(...arguments),this.type=4;}j(t){this.element.toggleAttribute(this.name,!!t&&t!==E);}}class L extends k{constructor(t,i,s,e,h){super(t,i,s,e,h),this.type=5;}_$AI(t,i=this){if((t=S(this,t,i,0)??E)===T)return;const s=this._$AH,e=t===E&&s!==E||t.capture!==s.capture||t.once!==s.once||t.passive!==s.passive,h=t!==E&&(s===E||e);e&&this.element.removeEventListener(this.name,this,s),h&&this.element.addEventListener(this.name,this,t),this._$AH=t;}handleEvent(t){"function"==typeof this._$AH?this._$AH.call(this.options?.host??this.element,t):this._$AH.handleEvent(t);}}class z{constructor(t,i,s){this.element=t,this.type=6,this._$AN=void 0,this._$AM=i,this.options=s;}get _$AU(){return this._$AM._$AU}_$AI(t){S(this,t);}}const j=t.litHtmlPolyfillSupport;j?.(N,R),(t.litHtmlVersions??=[]).push("3.3.1");
103
+
104
+ /**
105
+ * @license
106
+ * Copyright 2018 Google LLC
107
+ * SPDX-License-Identifier: BSD-3-Clause
108
+ */const o=o=>o??E;
109
+
110
+ var _M3eNavMenuItemElement_instances, _M3eNavMenuItemElement_items, _M3eNavMenuItemElement_menu, _M3eNavMenuItemElement_path, _M3eNavMenuItemElement_link, _M3eNavMenuItemElement_renderIcon, _M3eNavMenuItemElement_handleIconSlotChange, _M3eNavMenuItemElement_handleSlotChange, _M3eNavMenuItemElement_handleItemSlotChange, _M3eNavMenuItemElement_handleClick, _M3eNavMenuItemElement_handleCollapsibleEvent;
111
+ var M3eNavMenuItemElement_1;
112
+ /**
113
+ * An expandable item, selectable item within a navigation menu.
101
114
  *
102
115
  * @description
103
- * The `m3e-nav-menu` component provides a hierarchical, accessible navigation menu supporting
104
- * nested expandable items, keyboard navigation, and focus management. It is highly customizable
105
- * via slots and CSS custom properties, and is designed for use in sidebars, navigation drawers,
106
- * and complex menu structures.
116
+ * The `m3e-nav-menu-item` component represents an expandable, selectable item within a navigation menu.
117
+ * It supports nested child items, selection, disabled and indeterminate states, and emits events for
118
+ * open/close transitions. The component is highly customizable via slots and CSS custom properties, and
119
+ * is designed for accessible, keyboard-navigable menu structures.
120
+ *
121
+ *
122
+ * @example
123
+ * The following example illustrates a navigation menu with a top-level group of menu items.
124
+ * ```html
125
+ * <m3e-nav-menu>
126
+ * <m3e-nav-menu-item-group>
127
+ * <m3e-heading slot="label" variant="label" size="large">Mail</m3e-heading>
128
+ * <m3e-nav-menu-item>
129
+ * <m3e-icon slot="icon" name="mail"></m3e-icon>
130
+ * <span slot="label">Inbox</span>
131
+ * <span slot="badge">24</span>
132
+ * </m3e-nav-menu-item>
133
+ * <m3e-nav-menu-item>
134
+ * <m3e-icon slot="icon" name="send"></m3e-icon>
135
+ * <span slot="label">Outbox</span>
136
+ * </m3e-nav-menu-item>
137
+ * <m3e-nav-menu-item>
138
+ * <m3e-icon slot="icon" name="favorite"></m3e-icon>
139
+ * <span slot="label">Favorites</span>
140
+ * </m3e-nav-menu-item>
141
+ * <m3e-nav-menu-item>
142
+ * <m3e-icon slot="icon" name="delete"></m3e-icon>
143
+ * <span slot="label">Trash</span>
144
+ * </m3e-nav-menu-item>
145
+ * </m3e-nav-menu-item-group>
146
+ * </m3e-nav-menu>
147
+ * ```
107
148
  *
108
149
  * @example
109
- * The following example illustrates a multilevel navigation menu.
150
+ * The next example illustrates a multilevel navigation menu.
110
151
  * ```html
111
152
  * <m3e-nav-menu>
112
153
  * <m3e-nav-menu-item open>
@@ -130,295 +171,510 @@ var M3eNavMenuElement_1;
130
171
  * </m3e-nav-menu>
131
172
  * ```
132
173
  *
133
- * @tag m3e-nav-menu
174
+ * @tag m3e-nav-menu-item
134
175
  *
135
- * @slot - Renders the items of the menu.
176
+ * @slot - Renders the nested child items.
177
+ * @slot label - Renders the label of the item.
178
+ * @slot icon - Renders the icon of the item.
179
+ * @slot badge - Renders the badge of the item.
180
+ * @slot selected-icon - Renders the icon of the item when selected.
181
+ * @slot toggle-icon - Renders the toggle icon.
136
182
  *
137
- * @cssprop --m3e-nav-menu-padding-top - Top padding for the menu.
138
- * @cssprop --m3e-nav-menu-padding-bottom - Bottom padding for the menu.
139
- * @cssprop --m3e-nav-menu-padding-left - Left padding for the menu.
140
- * @cssprop --m3e-nav-menu-padding-right - Right padding for the menu.
141
- * @cssprop --m3e-nav-menu-divider-margin - Margin for divider elements in the menu.
142
- * @cssprop --m3e-nav-menu-scrollbar-width - Width of the menu scrollbar.
143
- * @cssprop --m3e-nav-menu-scrollbar-color - Color of the menu scrollbar.
183
+ * @attr disabled - Whether the element is disabled.
184
+ * @attr indeterminate - Whether the element's selected / checked state is indeterminate.
185
+ * @attr open - Whether the item is expanded.
186
+ * @attr selected - Whether the item is selected.
187
+ *
188
+ * @fires opening - Emitted when the item begins to open.
189
+ * @fires opened - Emitted when the item has opened.
190
+ * @fires closing - Emitted when the item begins to close.
191
+ * @fires closed - Emitted when the item has closed.
192
+ * @fires click - Emitted when the element is clicked.
193
+ *
194
+ * @cssprop --m3e-nav-menu-item-font-size - Font size for the item label.
195
+ * @cssprop --m3e-nav-menu-item-font-weight - Font weight for the item label.
196
+ * @cssprop --m3e-nav-menu-item-line-height - Line height for the item label.
197
+ * @cssprop --m3e-nav-menu-item-tracking - Letter spacing for the item label.
198
+ * @cssprop --m3e-nav-menu-item-padding - Inline padding for the item.
199
+ * @cssprop --m3e-nav-menu-item-height - Height of the item.
200
+ * @cssprop --m3e-nav-menu-item-spacing - Spacing between icon and label.
201
+ * @cssprop --m3e-nav-menu-item-shape - Border radius of the item and focus ring.
202
+ * @cssprop --m3e-nav-menu-item-icon-size - Size of the icon.
203
+ * @cssprop --m3e-nav-menu-item-inset - Indentation for nested items.
204
+ * @cssprop --m3e-nav-menu-item-label-color - Text color for the item label.
205
+ * @cssprop --m3e-nav-menu-item-selected-label-color - Text color for selected item label.
206
+ * @cssprop --m3e-nav-menu-item-selected-container-color - Background color for selected item.
207
+ * @cssprop --m3e-nav-menu-item-selected-container-focus-color - Focus color for selected item container.
208
+ * @cssprop --m3e-nav-menu-item-selected-container-hover-color - Hover color for selected item container.
209
+ * @cssprop --m3e-nav-menu-item-selected-ripple-color - Ripple color for selected item.
210
+ * @cssprop --m3e-nav-menu-item-unselected-container-focus-color - Focus color for unselected item container.
211
+ * @cssprop --m3e-nav-menu-item-unselected-container-hover-color - Hover color for unselected item container.
212
+ * @cssprop --m3e-nav-menu-item-unselected-ripple-color - Ripple color for unselected item.
213
+ * @cssprop --m3e-nav-menu-item-open-container-color - Background color for open item with children.
214
+ * @cssprop --m3e-nav-menu-item-open-container-focus-color - Focus color for open item container.
215
+ * @cssprop --m3e-nav-menu-item-open-container-hover-color - Hover color for open item container.
216
+ * @cssprop --m3e-nav-menu-item-open-ripple-color - Ripple color for open item.
217
+ * @cssprop --m3e-nav-menu-item-disabled-color - Text color for disabled item.
218
+ * @cssprop --m3e-nav-menu-item-disabled-color-opacity - Opacity for disabled item text color.
219
+ * @cssprop --m3e-nav-menu-item-badge-font-size - Font size for badge slot.
220
+ * @cssprop --m3e-nav-menu-item-badge-font-weight - Font weight for badge slot.
221
+ * @cssprop --m3e-nav-menu-item-badge-line-height - Line height for badge slot.
222
+ * @cssprop --m3e-nav-menu-badge-item-tracking - Letter spacing for badge slot.
223
+ * @cssprop --m3e-nav-menu-divider-margin - Margin for divider elements.
224
+ * @cssprop --m3e-nav-menu-item-vertical-inset - Vertical margin for first/last child items.
144
225
  */
145
- let M3eNavMenuElement = M3eNavMenuElement_1 = class M3eNavMenuElement extends Role(LitElement, "tree") {
226
+ let M3eNavMenuItemElement = M3eNavMenuItemElement_1 = class M3eNavMenuItemElement extends Selected(Disabled(EventAttribute(AttachInternals(Role(LitElement, "treeitem"), true), "opening", "opened", "closing", "closed"))) {
146
227
  constructor() {
147
- super();
148
- _M3eNavMenuElement_instances.add(this);
149
- /** @private */ _M3eNavMenuElement_ignoreFocusVisible.set(this, false);
150
- /** @private */ _M3eNavMenuElement_ignoreFocus.set(this, false);
151
- /** @private */
152
- this[_b] = new SelectionManager()
153
- .withVerticalOrientation()
154
- .withHomeAndEnd()
155
- .withTypeahead()
156
- .withSkipPredicate((x) => x.disabled || !x.visible)
157
- .disableRovingTabIndex()
158
- .onActiveItemChange(() => {
159
- if (this[selectionManager].activeItem) {
160
- __classPrivateFieldGet(this, _M3eNavMenuElement_instances, "m", _M3eNavMenuElement_activateItem).call(this, this[selectionManager].activeItem);
161
- }
162
- })
163
- .onSelectedItemsChange(() => {
164
- const selected = this.selected;
165
- for (const item of this.items) {
166
- if (item !== selected) {
167
- __classPrivateFieldGet(this, _M3eNavMenuElement_instances, "m", _M3eNavMenuElement_updateItemFocusVisible).call(this, item, false, false);
168
- }
169
- }
170
- if (selected?.label) {
171
- scrollIntoViewIfNeeded(selected.label, this, { block: "start", behavior: "smooth" });
172
- }
173
- });
174
- /** @private */ _M3eNavMenuElement_keyDownHandler.set(this, (e) => __classPrivateFieldGet(this, _M3eNavMenuElement_instances, "m", _M3eNavMenuElement_handleKeyDown).call(this, e));
175
- /** @private */ _M3eNavMenuElement_keyUpHandler.set(this, (e) => __classPrivateFieldGet(this, _M3eNavMenuElement_instances, "m", _M3eNavMenuElement_handleKeyUp).call(this, e));
176
- /** @private */ _M3eNavMenuElement_pointerDownHandler.set(this, (e) => __classPrivateFieldGet(this, _M3eNavMenuElement_instances, "m", _M3eNavMenuElement_handlePointerDown).call(this, e));
177
- new PressedController(this, { callback: (pressed) => (__classPrivateFieldSet(this, _M3eNavMenuElement_ignoreFocus, pressed, "f")) });
178
- new FocusController(this, {
179
- callback: () => {
180
- if (!__classPrivateFieldGet(this, _M3eNavMenuElement_ignoreFocus, "f")) {
181
- __classPrivateFieldGet(this, _M3eNavMenuElement_instances, "m", _M3eNavMenuElement_updateFocusVisible).call(this);
182
- }
183
- },
184
- });
228
+ super(...arguments);
229
+ _M3eNavMenuItemElement_instances.add(this);
230
+ /** @private */ this._hasChildItems = false;
231
+ /** @private */ _M3eNavMenuItemElement_items.set(this, []);
232
+ /** @private */ _M3eNavMenuItemElement_menu.set(this, null);
233
+ /** @private */ _M3eNavMenuItemElement_path.set(this, new Array());
234
+ /** @private */ _M3eNavMenuItemElement_link.set(this, null);
235
+ /**
236
+ * Whether the item is expanded.
237
+ * @default false
238
+ */
239
+ this.open = false;
185
240
  }
186
- /** The selected item of the menu. */
187
- get selected() {
188
- return this[selectionManager].selectedItems[0] ?? null;
241
+ /** A reference to the nested `HTMLAnchorElement`. */
242
+ get link() {
243
+ return __classPrivateFieldGet(this, _M3eNavMenuItemElement_link, "f");
189
244
  }
190
- /** All the items of the menu. */
191
- get items() {
192
- return this[selectionManager].items;
245
+ /** A reference to the element used to present the label of the item. */
246
+ get label() {
247
+ return this._base ?? null;
248
+ }
249
+ /** Whether the item is visible. */
250
+ get visible() {
251
+ return !__classPrivateFieldGet(this, _M3eNavMenuItemElement_path, "f").some((x) => !x.open);
252
+ }
253
+ /** The full path of the item, starting with the top-most ancestor, including this item. */
254
+ get path() {
255
+ return [...__classPrivateFieldGet(this, _M3eNavMenuItemElement_path, "f"), this];
256
+ }
257
+ /** Whether the item has child items. */
258
+ get hasChildItems() {
259
+ return this._hasChildItems;
260
+ }
261
+ /** The parenting item. */
262
+ get parentItem() {
263
+ return __classPrivateFieldGet(this, _M3eNavMenuItemElement_path, "f")[__classPrivateFieldGet(this, _M3eNavMenuItemElement_path, "f").length - 1] ?? null;
264
+ }
265
+ /** The items that immediately descend from this item. */
266
+ get childItems() {
267
+ return __classPrivateFieldGet(this, _M3eNavMenuItemElement_items, "f");
268
+ }
269
+ /** The one-based level of the item. */
270
+ get level() {
271
+ return __classPrivateFieldGet(this, _M3eNavMenuItemElement_path, "f").length + 1;
193
272
  }
194
273
  /**
195
- * Expands the specified items, or all items if no items are provided.
196
- * @param {M3eNavMenuItemElement | undefined} items The items to expand.
274
+ * Expands this item, and optionally, all descendants.
275
+ * @param {boolean} [descendants=false] Whether to expand all descendants.
197
276
  */
198
- expand(items) {
199
- (items ?? this[selectionManager].items).forEach((x) => x.expand());
277
+ expand(descendants = false) {
278
+ if (this.hasChildItems) {
279
+ this.open = true;
280
+ if (descendants) {
281
+ this.childItems.forEach((x) => x.expand(true));
282
+ }
283
+ }
200
284
  }
201
285
  /**
202
- * Collapses the specified items, or all items if no items are provided.
203
- * @param {M3eNavMenuItemElement | undefined} items The items to collapse.
286
+ * Collapses this item, and optionally, all descendants.
287
+ * @param {boolean} [descendants=false] Whether to expand all descendants.
204
288
  */
205
- collapse(items) {
206
- (items ?? this[selectionManager].items).forEach((x) => x.collapse());
207
- const activeItem = this[selectionManager].activeItem;
208
- if (activeItem && !activeItem.visible) {
209
- for (let parent = activeItem.parentItem; parent; parent = parent.parentItem) {
210
- if (parent.visible) {
211
- this[selectionManager].setActiveItem(parent);
212
- break;
213
- }
289
+ collapse(descendants = false) {
290
+ if (this.hasChildItems) {
291
+ this.open = false;
292
+ if (descendants) {
293
+ this.childItems.forEach((x) => x.collapse(true));
214
294
  }
215
295
  }
216
296
  }
297
+ /** Toggles the expanded state of the item. */
298
+ toggle() {
299
+ if (this.hasChildItems) {
300
+ this.open = !this.open;
301
+ }
302
+ }
217
303
  /** @inheritdoc */
218
304
  connectedCallback() {
219
305
  super.connectedCallback();
220
- this.setAttribute("tabindex", "0");
221
- this.addEventListener("keydown", __classPrivateFieldGet(this, _M3eNavMenuElement_keyDownHandler, "f"));
222
- this.addEventListener("keyup", __classPrivateFieldGet(this, _M3eNavMenuElement_keyUpHandler, "f"));
223
- this.addEventListener("pointerdown", __classPrivateFieldGet(this, _M3eNavMenuElement_pointerDownHandler, "f"));
306
+ __classPrivateFieldGet(this, _M3eNavMenuItemElement_path, "f").length = 0;
307
+ for (let item = this.parentElement?.closest("m3e-nav-menu-item"); item; item = item.parentElement?.closest("m3e-nav-menu-item")) {
308
+ __classPrivateFieldGet(this, _M3eNavMenuItemElement_path, "f").push(item);
309
+ }
310
+ __classPrivateFieldGet(this, _M3eNavMenuItemElement_path, "f").reverse();
311
+ this.style.setProperty("--_nav-menu-item-level", `${this.level}`);
312
+ __classPrivateFieldSet(this, _M3eNavMenuItemElement_menu, this.closest("m3e-nav-menu"), "f");
224
313
  }
225
314
  /** @inheritdoc */
226
315
  disconnectedCallback() {
227
316
  super.disconnectedCallback();
228
- this.removeEventListener("keydown", __classPrivateFieldGet(this, _M3eNavMenuElement_keyDownHandler, "f"));
229
- this.removeEventListener("keyup", __classPrivateFieldGet(this, _M3eNavMenuElement_keyUpHandler, "f"));
230
- this.removeEventListener("pointerdown", __classPrivateFieldGet(this, _M3eNavMenuElement_pointerDownHandler, "f"));
317
+ __classPrivateFieldGet(this, _M3eNavMenuItemElement_path, "f").length = 0;
231
318
  }
232
319
  /** @inheritdoc */
233
- render() {
234
- return html `<slot @slotchange="${__classPrivateFieldGet(this, _M3eNavMenuElement_instances, "m", _M3eNavMenuElement_handleSlotChange)}"></slot>`;
320
+ update(changedProperties) {
321
+ super.update(changedProperties);
322
+ if (changedProperties.has("selected")) {
323
+ // Remove aria-selected and just use aria-current.
324
+ this.ariaSelected = null;
325
+ this.ariaCurrent = this.hasChildItems ? null : `${this.selected}`;
326
+ for (const icon of this.querySelectorAll(":scope > m3e-icon[slot]")) {
327
+ icon.toggleAttribute("filled", this.selected);
328
+ }
329
+ __classPrivateFieldGet(this, _M3eNavMenuItemElement_path, "f").forEach((x) => (x.selected = this.selected));
330
+ if (this.selected && !this.hasChildItems) {
331
+ this.closest("m3e-nav-menu")?.[selectionManager].notifySelectionChange(this);
332
+ }
333
+ }
334
+ if (changedProperties.has("open") || changedProperties.has("_hasChildItems")) {
335
+ this.ariaExpanded = this._hasChildItems ? `${this.open}` : null;
336
+ }
337
+ if ((changedProperties.has("_hasChildItems") && this.disabled) || changedProperties.has("disabled")) {
338
+ __classPrivateFieldGet(this, _M3eNavMenuItemElement_items, "f").forEach((x) => (x.disabled = this.disabled));
339
+ }
235
340
  }
236
- };
237
- _M3eNavMenuElement_ignoreFocusVisible = new WeakMap();
238
- _M3eNavMenuElement_ignoreFocus = new WeakMap();
239
- _M3eNavMenuElement_keyDownHandler = new WeakMap();
240
- _M3eNavMenuElement_keyUpHandler = new WeakMap();
241
- _M3eNavMenuElement_pointerDownHandler = new WeakMap();
242
- _M3eNavMenuElement_instances = new WeakSet();
243
- _b = selectionManager;
244
- _M3eNavMenuElement_handleSlotChange = function _M3eNavMenuElement_handleSlotChange() {
245
- const { added } = this[selectionManager].setItems([...this.querySelectorAll("m3e-nav-menu-item")]);
246
- for (const item of added) {
247
- item.id = item.id || `m3e-nav-menu-item-${M3eNavMenuElement_1.__nextId++}`;
248
- }
249
- if (this[selectionManager].activeItem) {
250
- this.setAttribute("aria-activedescendant", this[selectionManager].activeItem.id);
251
- __classPrivateFieldGet(this, _M3eNavMenuElement_instances, "m", _M3eNavMenuElement_updateFocusVisible).call(this);
341
+ /** @inheritdoc */
342
+ firstUpdated(_changedProperties) {
343
+ super.firstUpdated(_changedProperties);
344
+ const base = this._base;
345
+ if (base) {
346
+ [this.focusRing, this.stateLayer, this.ripple].forEach((x) => x?.attach(base));
347
+ }
252
348
  }
253
- else {
254
- this.removeAttribute("aria-activedescendant");
349
+ /** @inheritdoc */
350
+ render() {
351
+ return html `<div class="base" @click="${__classPrivateFieldGet(this, _M3eNavMenuItemElement_instances, "m", _M3eNavMenuItemElement_handleClick)}">
352
+ <m3e-state-layer class="state-layer" ?disabled="${this.disabled}"></m3e-state-layer>
353
+ <m3e-focus-ring class="focus-ring" inward ?disabled="${this.disabled}"></m3e-focus-ring>
354
+ <m3e-ripple class="ripple" centered ?disabled="${this.disabled}"></m3e-ripple>
355
+ <div class="icon" aria-hidden="true">${__classPrivateFieldGet(this, _M3eNavMenuItemElement_instances, "m", _M3eNavMenuItemElement_renderIcon).call(this)}</div>
356
+ <div class="label">
357
+ <slot name="label" @slotchange="${__classPrivateFieldGet(this, _M3eNavMenuItemElement_instances, "m", _M3eNavMenuItemElement_handleSlotChange)}"></slot>
358
+ </div>
359
+ <slot name="badge"></slot>
360
+ <div aria-hidden="true" class="toggle">
361
+ <slot name="toggle-icon">
362
+ <svg class="toggle-icon" viewBox="0 -960 960 960" fill="currentColor">
363
+ <path d="M480-360 280-560h400L480-360Z" />
364
+ </svg>
365
+ </slot>
366
+ </div>
367
+ </div>
368
+ <m3e-collapsible
369
+ class="group"
370
+ role="group"
371
+ aria-hidden="${o(this._hasChildItems ? undefined : "true")}"
372
+ ?open="${this._hasChildItems && this.open}"
373
+ @opening="${__classPrivateFieldGet(this, _M3eNavMenuItemElement_instances, "m", _M3eNavMenuItemElement_handleCollapsibleEvent)}"
374
+ @opened="${__classPrivateFieldGet(this, _M3eNavMenuItemElement_instances, "m", _M3eNavMenuItemElement_handleCollapsibleEvent)}"
375
+ @closing="${__classPrivateFieldGet(this, _M3eNavMenuItemElement_instances, "m", _M3eNavMenuItemElement_handleCollapsibleEvent)}"
376
+ @closed="${__classPrivateFieldGet(this, _M3eNavMenuItemElement_instances, "m", _M3eNavMenuItemElement_handleCollapsibleEvent)}"
377
+ >
378
+ <slot @slotchange="${__classPrivateFieldGet(this, _M3eNavMenuItemElement_instances, "m", _M3eNavMenuItemElement_handleItemSlotChange)}"></slot>
379
+ </m3e-collapsible>`;
255
380
  }
256
381
  };
257
- _M3eNavMenuElement_handleKeyDown = function _M3eNavMenuElement_handleKeyDown(e) {
258
- __classPrivateFieldSet(this, _M3eNavMenuElement_ignoreFocusVisible, false, "f");
259
- __classPrivateFieldGet(this, _M3eNavMenuElement_instances, "m", _M3eNavMenuElement_updateFocusVisible).call(this);
260
- const item = this[selectionManager].activeItem;
261
- if (e.defaultPrevented || !item || item.disabled)
262
- return;
263
- switch (e.key) {
264
- case "Enter":
265
- case " ":
266
- e.preventDefault();
267
- if (item.ripple && !item.ripple.visible) {
268
- item.ripple.show(0, 0, true);
269
- }
270
- if (item.hasChildItems) {
271
- item.toggle();
272
- }
273
- else if (!item.selected) {
274
- this[selectionManager].select(item);
275
- item.link?.click();
276
- }
277
- break;
278
- case "*":
279
- e.preventDefault();
280
- item.expand(true);
281
- break;
282
- case "Left":
283
- case "ArrowLeft":
284
- e.preventDefault();
285
- if (item.hasChildItems && item.open) {
286
- item.collapse();
287
- }
288
- else {
289
- const parent = item.parentItem;
290
- if (parent) {
291
- parent.collapse();
292
- this[selectionManager].setActiveItem(parent);
293
- }
294
- }
295
- break;
296
- case "Right":
297
- case "ArrowRight":
298
- if (item.hasChildItems) {
299
- if (!item.open) {
300
- e.preventDefault();
301
- item.expand();
302
- }
303
- else {
304
- try {
305
- this[selectionManager].vertical = false;
306
- this[selectionManager].onKeyDown(e);
307
- }
308
- finally {
309
- this[selectionManager].vertical = true;
310
- }
311
- }
312
- }
313
- else {
314
- e.preventDefault();
315
- }
316
- break;
317
- default:
318
- this[selectionManager].onKeyDown(e);
319
- break;
320
- }
382
+ _M3eNavMenuItemElement_items = new WeakMap();
383
+ _M3eNavMenuItemElement_menu = new WeakMap();
384
+ _M3eNavMenuItemElement_path = new WeakMap();
385
+ _M3eNavMenuItemElement_link = new WeakMap();
386
+ _M3eNavMenuItemElement_instances = new WeakSet();
387
+ _M3eNavMenuItemElement_renderIcon = function _M3eNavMenuItemElement_renderIcon() {
388
+ const icon = html `<slot name="icon" @slotchange="${__classPrivateFieldGet(this, _M3eNavMenuItemElement_instances, "m", _M3eNavMenuItemElement_handleIconSlotChange)}"></slot>`;
389
+ return this.selected && !this.hasChildItems
390
+ ? html `<slot name="selected-icon" @slotchange="${__classPrivateFieldGet(this, _M3eNavMenuItemElement_instances, "m", _M3eNavMenuItemElement_handleIconSlotChange)}">${icon}</slot>`
391
+ : icon;
321
392
  };
322
- _M3eNavMenuElement_handleKeyUp = function _M3eNavMenuElement_handleKeyUp(e) {
323
- const item = this[selectionManager].activeItem;
324
- if (e.defaultPrevented || !item || item.disabled)
325
- return;
326
- switch (e.key) {
327
- case "Enter":
328
- case " ":
329
- item.ripple?.hide();
330
- break;
331
- }
393
+ _M3eNavMenuItemElement_handleIconSlotChange = function _M3eNavMenuItemElement_handleIconSlotChange(e) {
394
+ this.classList.toggle("-with-icon", hasAssignedNodes(e.target));
332
395
  };
333
- _M3eNavMenuElement_handlePointerDown = function _M3eNavMenuElement_handlePointerDown(e) {
334
- if (!e.defaultPrevented && !__classPrivateFieldGet(this, _M3eNavMenuElement_ignoreFocusVisible, "f")) {
335
- __classPrivateFieldSet(this, _M3eNavMenuElement_ignoreFocusVisible, true, "f");
336
- if (this[selectionManager].activeItem) {
337
- __classPrivateFieldGet(this, _M3eNavMenuElement_instances, "m", _M3eNavMenuElement_updateItemFocusVisible).call(this, this[selectionManager].activeItem, true, false);
338
- }
339
- }
396
+ _M3eNavMenuItemElement_handleSlotChange = function _M3eNavMenuItemElement_handleSlotChange(e) {
397
+ __classPrivateFieldSet(this, _M3eNavMenuItemElement_link, e.target.assignedElements({ flatten: true }).find((x) => x instanceof HTMLAnchorElement) ??
398
+ null, "f");
399
+ __classPrivateFieldGet(this, _M3eNavMenuItemElement_link, "f")?.setAttribute("tabindex", "-1");
340
400
  };
341
- _M3eNavMenuElement_activateItem = function _M3eNavMenuElement_activateItem(item) {
342
- this.setAttribute("aria-activedescendant", item.id);
343
- if (item.label) {
344
- scrollIntoViewIfNeeded(item.label, this, { block: "nearest", behavior: "smooth" });
401
+ _M3eNavMenuItemElement_handleItemSlotChange = function _M3eNavMenuItemElement_handleItemSlotChange(e) {
402
+ __classPrivateFieldSet(this, _M3eNavMenuItemElement_items, e.target
403
+ .assignedElements({ flatten: true })
404
+ .filter((x) => x instanceof M3eNavMenuItemElement_1), "f");
405
+ const hadChildItems = this._hasChildItems;
406
+ this._hasChildItems = __classPrivateFieldGet(this, _M3eNavMenuItemElement_items, "f").length > 0;
407
+ this.classList.toggle("-has-items", this._hasChildItems);
408
+ if (hadChildItems || this._hasChildItems) {
409
+ this.selected = __classPrivateFieldGet(this, _M3eNavMenuItemElement_items, "f").some((x) => x.selected);
345
410
  }
346
- __classPrivateFieldGet(this, _M3eNavMenuElement_instances, "m", _M3eNavMenuElement_updateFocusVisible).call(this);
347
- };
348
- _M3eNavMenuElement_updateFocusVisible = function _M3eNavMenuElement_updateFocusVisible() {
349
- const focused = this.matches(":focus") || this.matches(":focus-within");
350
- const focusVisible = !__classPrivateFieldGet(this, _M3eNavMenuElement_ignoreFocusVisible, "f") && this.matches(":focus-visible");
351
- this[selectionManager].items.forEach((x) => {
352
- const active = x === this[selectionManager].activeItem;
353
- __classPrivateFieldGet(this, _M3eNavMenuElement_instances, "m", _M3eNavMenuElement_updateItemFocusVisible).call(this, x, active && focused, active && focusVisible);
354
- });
355
411
  };
356
- _M3eNavMenuElement_updateItemFocusVisible = function _M3eNavMenuElement_updateItemFocusVisible(item, focused, focusVisible) {
357
- if (focused) {
358
- item.stateLayer?.show("focused");
359
- }
360
- else {
361
- item.stateLayer?.hide("focused");
362
- }
363
- if (focusVisible) {
364
- item.focusRing?.show();
412
+ _M3eNavMenuItemElement_handleClick = function _M3eNavMenuItemElement_handleClick() {
413
+ if (this.disabled)
414
+ return;
415
+ __classPrivateFieldGet(this, _M3eNavMenuItemElement_menu, "f")?.[selectionManager].setActiveItem(this);
416
+ if (!this._hasChildItems) {
417
+ __classPrivateFieldGet(this, _M3eNavMenuItemElement_menu, "f")?.[selectionManager].select(this);
418
+ __classPrivateFieldGet(this, _M3eNavMenuItemElement_path, "f").forEach((x) => (x.selected = this.selected));
419
+ __classPrivateFieldGet(this, _M3eNavMenuItemElement_link, "f")?.click();
420
+ const drawerContainer = this.closest("m3e-drawer-container");
421
+ if (drawerContainer) {
422
+ const drawer = this.closest("[slot='start']") ?? this.closest("[slot='end')");
423
+ if (drawer &&
424
+ (drawerContainer.classList.contains(`-${drawer.slot}-push`) ||
425
+ drawerContainer.classList.contains(`-${drawer.slot}-over`))) {
426
+ setTimeout(() => drawerContainer.removeAttribute(drawer.slot), 300);
427
+ }
428
+ }
365
429
  }
366
430
  else {
367
- item.focusRing?.hide();
431
+ this.toggle();
368
432
  }
369
433
  };
434
+ _M3eNavMenuItemElement_handleCollapsibleEvent = function _M3eNavMenuItemElement_handleCollapsibleEvent(e) {
435
+ e.stopPropagation();
436
+ this.dispatchEvent(new Event(e.type, { bubbles: true }));
437
+ };
370
438
  /** The styles of the element. */
371
- M3eNavMenuElement.styles = css `
439
+ M3eNavMenuItemElement.styles = css `
372
440
  :host {
373
- display: flex;
374
- flex-direction: column;
441
+ display: block;
442
+ flex: none;
375
443
  outline: none;
376
- overflow-y: auto;
377
- overflow-x: hidden;
378
444
  position: relative;
379
- min-height: 0;
380
- padding-block-start: var(--m3e-nav-menu-padding-top, 0.5rem);
381
- padding-block-end: var(--m3e-nav-menu-padding-bottom, 0.5rem);
382
- padding-inline-start: var(--m3e-nav-menu-padding-left, 0.75rem);
383
- padding-inline-end: var(--m3e-nav-menu-padding-right, 0.75rem);
384
- scrollbar-width: ${DesignToken.scrollbar.width};
385
- scrollbar-color: ${DesignToken.scrollbar.color};
445
+ font-size: var(--m3e-nav-menu-item-font-size, ${DesignToken.typescale.standard.label.large.fontSize});
446
+ font-weight: var(--m3e-nav-menu-item-font-weight, ${DesignToken.typescale.standard.label.large.fontWeight});
447
+ line-height: var(--m3e-nav-menu-item-line-height, ${DesignToken.typescale.standard.label.large.lineHeight});
448
+ letter-spacing: var(--m3e-nav-menu-item-tracking, ${DesignToken.typescale.standard.label.large.tracking});
386
449
  }
387
- ::slotted(m3e-divider) {
388
- margin-block: var(--m3e-nav-menu-divider-margin, 0.25rem);
450
+ .base {
451
+ display: flex;
452
+ align-items: center;
453
+ position: relative;
454
+ padding-inline: var(--m3e-nav-menu-item-padding, 1.5rem);
455
+ height: calc(var(--m3e-nav-menu-item-height, 3.5rem) + ${DesignToken.density.calc(-3)});
456
+ column-gap: var(--m3e-nav-menu-item-spacing, 0.75rem);
457
+ transition: ${unsafeCSS(`color ${DesignToken.motion.duration.short4} ${DesignToken.motion.easing.standard},
458
+ background-color ${DesignToken.motion.duration.short4} ${DesignToken.motion.easing.standard}`)};
389
459
  }
390
- `;
391
- /** @private */ M3eNavMenuElement.__nextId = 0;
392
- M3eNavMenuElement = M3eNavMenuElement_1 = __decorate([
393
- t$2("m3e-nav-menu")
394
- ], M3eNavMenuElement);
395
-
396
- /**
397
- * @license
398
- * Copyright 2017 Google LLC
399
- * SPDX-License-Identifier: BSD-3-Clause
400
- */
401
- const t=globalThis,i=t.trustedTypes,s=i?i.createPolicy("lit-html",{createHTML:t=>t}):void 0,e="$lit$",h=`lit$${Math.random().toFixed(9).slice(2)}$`,o$1="?"+h,n=`<${o$1}>`,r=document,l=()=>r.createComment(""),c=t=>null===t||"object"!=typeof t&&"function"!=typeof t,a=Array.isArray,u=t=>a(t)||"function"==typeof t?.[Symbol.iterator],d="[ \t\n\f\r]",f=/<(?:(!--|\/[^a-zA-Z])|(\/?[a-zA-Z][^>\s]*)|(\/?$))/g,v=/-->/g,_=/>/g,m=RegExp(`>|${d}(?:([^\\s"'>=/]+)(${d}*=${d}*(?:[^ \t\n\f\r"'\`<>=]|("|')|))|$)`,"g"),p=/'/g,g=/"/g,$=/^(?:script|style|textarea|title)$/i,T=Symbol.for("lit-noChange"),E=Symbol.for("lit-nothing"),A=new WeakMap,C=r.createTreeWalker(r,129);function P(t,i){if(!a(t)||!t.hasOwnProperty("raw"))throw Error("invalid template strings array");return void 0!==s?s.createHTML(i):i}const V=(t,i)=>{const s=t.length-1,o=[];let r,l=2===i?"<svg>":3===i?"<math>":"",c=f;for(let i=0;i<s;i++){const s=t[i];let a,u,d=-1,y=0;for(;y<s.length&&(c.lastIndex=y,u=c.exec(s),null!==u);)y=c.lastIndex,c===f?"!--"===u[1]?c=v:void 0!==u[1]?c=_:void 0!==u[2]?($.test(u[2])&&(r=RegExp("</"+u[2],"g")),c=m):void 0!==u[3]&&(c=m):c===m?">"===u[0]?(c=r??f,d=-1):void 0===u[1]?d=-2:(d=c.lastIndex-u[2].length,a=u[1],c=void 0===u[3]?m:'"'===u[3]?g:p):c===g||c===p?c=m:c===v||c===_?c=f:(c=m,r=void 0);const x=c===m&&t[i+1].startsWith("/>")?" ":"";l+=c===f?s+n:d>=0?(o.push(a),s.slice(0,d)+e+s.slice(d)+h+x):s+h+(-2===d?i:x);}return [P(t,l+(t[s]||"<?>")+(2===i?"</svg>":3===i?"</math>":"")),o]};class N{constructor({strings:t,_$litType$:s},n){let r;this.parts=[];let c=0,a=0;const u=t.length-1,d=this.parts,[f,v]=V(t,s);if(this.el=N.createElement(f,n),C.currentNode=this.el.content,2===s||3===s){const t=this.el.content.firstChild;t.replaceWith(...t.childNodes);}for(;null!==(r=C.nextNode())&&d.length<u;){if(1===r.nodeType){if(r.hasAttributes())for(const t of r.getAttributeNames())if(t.endsWith(e)){const i=v[a++],s=r.getAttribute(t).split(h),e=/([.?@])?(.*)/.exec(i);d.push({type:1,index:c,name:e[2],strings:s,ctor:"."===e[1]?H:"?"===e[1]?I:"@"===e[1]?L:k}),r.removeAttribute(t);}else t.startsWith(h)&&(d.push({type:6,index:c}),r.removeAttribute(t));if($.test(r.tagName)){const t=r.textContent.split(h),s=t.length-1;if(s>0){r.textContent=i?i.emptyScript:"";for(let i=0;i<s;i++)r.append(t[i],l()),C.nextNode(),d.push({type:2,index:++c});r.append(t[s],l());}}}else if(8===r.nodeType)if(r.data===o$1)d.push({type:2,index:c});else {let t=-1;for(;-1!==(t=r.data.indexOf(h,t+1));)d.push({type:7,index:c}),t+=h.length-1;}c++;}}static createElement(t,i){const s=r.createElement("template");return s.innerHTML=t,s}}function S(t,i,s=t,e){if(i===T)return i;let h=void 0!==e?s._$Co?.[e]:s._$Cl;const o=c(i)?void 0:i._$litDirective$;return h?.constructor!==o&&(h?._$AO?.(false),void 0===o?h=void 0:(h=new o(t),h._$AT(t,s,e)),void 0!==e?(s._$Co??=[])[e]=h:s._$Cl=h),void 0!==h&&(i=S(t,h._$AS(t,i.values),h,e)),i}class M{constructor(t,i){this._$AV=[],this._$AN=void 0,this._$AD=t,this._$AM=i;}get parentNode(){return this._$AM.parentNode}get _$AU(){return this._$AM._$AU}u(t){const{el:{content:i},parts:s}=this._$AD,e=(t?.creationScope??r).importNode(i,true);C.currentNode=e;let h=C.nextNode(),o=0,n=0,l=s[0];for(;void 0!==l;){if(o===l.index){let i;2===l.type?i=new R(h,h.nextSibling,this,t):1===l.type?i=new l.ctor(h,l.name,l.strings,this,t):6===l.type&&(i=new z(h,this,t)),this._$AV.push(i),l=s[++n];}o!==l?.index&&(h=C.nextNode(),o++);}return C.currentNode=r,e}p(t){let i=0;for(const s of this._$AV) void 0!==s&&(void 0!==s.strings?(s._$AI(t,s,i),i+=s.strings.length-2):s._$AI(t[i])),i++;}}class R{get _$AU(){return this._$AM?._$AU??this._$Cv}constructor(t,i,s,e){this.type=2,this._$AH=E,this._$AN=void 0,this._$AA=t,this._$AB=i,this._$AM=s,this.options=e,this._$Cv=e?.isConnected??true;}get parentNode(){let t=this._$AA.parentNode;const i=this._$AM;return void 0!==i&&11===t?.nodeType&&(t=i.parentNode),t}get startNode(){return this._$AA}get endNode(){return this._$AB}_$AI(t,i=this){t=S(this,t,i),c(t)?t===E||null==t||""===t?(this._$AH!==E&&this._$AR(),this._$AH=E):t!==this._$AH&&t!==T&&this._(t):void 0!==t._$litType$?this.$(t):void 0!==t.nodeType?this.T(t):u(t)?this.k(t):this._(t);}O(t){return this._$AA.parentNode.insertBefore(t,this._$AB)}T(t){this._$AH!==t&&(this._$AR(),this._$AH=this.O(t));}_(t){this._$AH!==E&&c(this._$AH)?this._$AA.nextSibling.data=t:this.T(r.createTextNode(t)),this._$AH=t;}$(t){const{values:i,_$litType$:s}=t,e="number"==typeof s?this._$AC(t):(void 0===s.el&&(s.el=N.createElement(P(s.h,s.h[0]),this.options)),s);if(this._$AH?._$AD===e)this._$AH.p(i);else {const t=new M(e,this),s=t.u(this.options);t.p(i),this.T(s),this._$AH=t;}}_$AC(t){let i=A.get(t.strings);return void 0===i&&A.set(t.strings,i=new N(t)),i}k(t){a(this._$AH)||(this._$AH=[],this._$AR());const i=this._$AH;let s,e=0;for(const h of t)e===i.length?i.push(s=new R(this.O(l()),this.O(l()),this,this.options)):s=i[e],s._$AI(h),e++;e<i.length&&(this._$AR(s&&s._$AB.nextSibling,e),i.length=e);}_$AR(t=this._$AA.nextSibling,i){for(this._$AP?.(false,true,i);t!==this._$AB;){const i=t.nextSibling;t.remove(),t=i;}}setConnected(t){ void 0===this._$AM&&(this._$Cv=t,this._$AP?.(t));}}class k{get tagName(){return this.element.tagName}get _$AU(){return this._$AM._$AU}constructor(t,i,s,e,h){this.type=1,this._$AH=E,this._$AN=void 0,this.element=t,this.name=i,this._$AM=e,this.options=h,s.length>2||""!==s[0]||""!==s[1]?(this._$AH=Array(s.length-1).fill(new String),this.strings=s):this._$AH=E;}_$AI(t,i=this,s,e){const h=this.strings;let o=false;if(void 0===h)t=S(this,t,i,0),o=!c(t)||t!==this._$AH&&t!==T,o&&(this._$AH=t);else {const e=t;let n,r;for(t=h[0],n=0;n<h.length-1;n++)r=S(this,e[s+n],i,n),r===T&&(r=this._$AH[n]),o||=!c(r)||r!==this._$AH[n],r===E?t=E:t!==E&&(t+=(r??"")+h[n+1]),this._$AH[n]=r;}o&&!e&&this.j(t);}j(t){t===E?this.element.removeAttribute(this.name):this.element.setAttribute(this.name,t??"");}}class H extends k{constructor(){super(...arguments),this.type=3;}j(t){this.element[this.name]=t===E?void 0:t;}}class I extends k{constructor(){super(...arguments),this.type=4;}j(t){this.element.toggleAttribute(this.name,!!t&&t!==E);}}class L extends k{constructor(t,i,s,e,h){super(t,i,s,e,h),this.type=5;}_$AI(t,i=this){if((t=S(this,t,i,0)??E)===T)return;const s=this._$AH,e=t===E&&s!==E||t.capture!==s.capture||t.once!==s.once||t.passive!==s.passive,h=t!==E&&(s===E||e);e&&this.element.removeEventListener(this.name,this,s),h&&this.element.addEventListener(this.name,this,t),this._$AH=t;}handleEvent(t){"function"==typeof this._$AH?this._$AH.call(this.options?.host??this.element,t):this._$AH.handleEvent(t);}}class z{constructor(t,i,s){this.element=t,this.type=6,this._$AN=void 0,this._$AM=i,this.options=s;}get _$AU(){return this._$AM._$AU}_$AI(t){S(this,t);}}const j=t.litHtmlPolyfillSupport;j?.(N,R),(t.litHtmlVersions??=[]).push("3.3.1");
402
-
403
- /**
404
- * @license
405
- * Copyright 2018 Google LLC
406
- * SPDX-License-Identifier: BSD-3-Clause
407
- */const o=o=>o??E;
408
-
409
- var _M3eNavMenuItemElement_instances, _M3eNavMenuItemElement_items, _M3eNavMenuItemElement_menu, _M3eNavMenuItemElement_path, _M3eNavMenuItemElement_link, _M3eNavMenuItemElement_renderIcon, _M3eNavMenuItemElement_handleIconSlotChange, _M3eNavMenuItemElement_handleSlotChange, _M3eNavMenuItemElement_handleItemSlotChange, _M3eNavMenuItemElement_handleClick, _M3eNavMenuItemElement_handleCollapsibleEvent;
410
- var M3eNavMenuItemElement_1;
411
- /**
412
- * An expandable item in a navigation menu.
413
- *
414
- * @description
415
- * The `m3e-nav-menu-item` component represents an expandable, selectable item within a navigation menu.
416
- * It supports nested child items, selection, disabled and indeterminate states, and emits events for
417
- * open/close transitions. The component is highly customizable via slots and CSS custom properties, and
418
- * is designed for accessible, keyboard-navigable menu structures.
460
+ .base,
461
+ .focus-ring {
462
+ border-radius: var(--m3e-nav-menu-item-shape, ${DesignToken.shape.corner.full});
463
+ }
464
+ .label {
465
+ flex: 1 1 auto;
466
+ display: flex;
467
+ align-items: center;
468
+ position: relative;
469
+ overflow: hidden;
470
+ vertical-align: middle;
471
+ }
472
+ .icon,
473
+ .toggle {
474
+ flex: none;
475
+ display: flex;
476
+ align-items: center;
477
+ justify-content: center;
478
+ position: relative;
479
+ vertical-align: middle;
480
+ }
481
+ ::slotted([slot="badge"]) {
482
+ flex: none;
483
+ position: relative;
484
+ font-size: var(--m3e-nav-menu-item-badge-font-size, ${DesignToken.typescale.standard.label.large.fontSize});
485
+ font-weight: var(--m3e-nav-menu-item-badge-font-weight, ${DesignToken.typescale.standard.label.large.fontWeight});
486
+ line-height: var(--m3e-nav-menu-item-badge-line-height, ${DesignToken.typescale.standard.label.large.lineHeight});
487
+ letter-spacing: var(--m3e-nav-menu-badge-item-tracking, ${DesignToken.typescale.standard.label.large.tracking});
488
+ }
489
+ .toggle {
490
+ transition: ${unsafeCSS(`transform var(--m3e-collapsible-animation-duration, ${DesignToken.motion.duration.medium1})
491
+ ${DesignToken.motion.easing.standard}`)};
492
+ }
493
+ :host(:not(.-with-icon)) .icon {
494
+ display: none;
495
+ }
496
+ .icon {
497
+ margin-inline-start: -0.5rem;
498
+ }
499
+ .toggle {
500
+ margin-inline-end: -0.5rem;
501
+ }
502
+ .group {
503
+ padding-inline-start: var(--m3e-nav-menu-item-inset, 1rem);
504
+ }
505
+ :host([open]) .toggle {
506
+ transform: rotate(180deg);
507
+ }
508
+ :host(:not(.-has-items)) .toggle,
509
+ :host(:not(.-has-items)) .group {
510
+ display: none;
511
+ }
512
+ ::slotted([slot="selected-icon"]),
513
+ ::slotted([slot="icon"]),
514
+ ::slotted([slot="toggle-icon"]),
515
+ .toggle-icon {
516
+ vertical-align: middle;
517
+ width: 1em;
518
+ height: 1em;
519
+ font-size: var(--m3e-nav-menu-item-icon-size, 1.5rem);
520
+ }
521
+ :host(:not(:disabled)) .base {
522
+ cursor: pointer;
523
+ }
524
+ :host(:not(:disabled)) .base {
525
+ color: var(--m3e-nav-menu-item-label-color, ${DesignToken.color.onSurfaceVariant});
526
+ }
527
+ :host(:disabled) .base {
528
+ color: color-mix(
529
+ in srgb,
530
+ var(--m3e-nav-menu-item-disabled-color, ${DesignToken.color.onSurface})
531
+ var(--m3e-nav-menu-item-disabled-color-opacity, 38%),
532
+ transparent
533
+ );
534
+ }
535
+ :host([selected]:not(.-has-items):not(:disabled)) .base {
536
+ color: var(--m3e-nav-menu-item-selected-label-color, ${DesignToken.color.onSecondaryContainer});
537
+ background-color: var(--m3e-nav-menu-item-selected-container-color, ${DesignToken.color.secondaryContainer});
538
+ --m3e-state-layer-focus-color: var(
539
+ --m3e-nav-menu-item-selected-container-focus-color,
540
+ ${DesignToken.color.onSecondaryContainer}
541
+ );
542
+ --m3e-state-layer-hover-color: var(
543
+ --m3e-nav-menu-item-selected-container-hover-color,
544
+ ${DesignToken.color.onSecondaryContainer}
545
+ );
546
+ --m3e-ripple-color: var(--m3e-nav-menu-item-selected-ripple-color, ${DesignToken.color.onSecondaryContainer});
547
+ }
548
+ :host(:not([selected]):not(.-has-items):not(:disabled)) .base {
549
+ --m3e-state-layer-focus-color: var(
550
+ --m3e-nav-menu-item-unselected-container-focus-color,
551
+ ${DesignToken.color.onSurface}
552
+ );
553
+ --m3e-state-layer-hover-color: var(
554
+ --m3e-nav-menu-item-unselected-container-hover-color,
555
+ ${DesignToken.color.onSurface}
556
+ );
557
+ --m3e-ripple-color: var(--m3e-nav-menu-item-unselected-ripple-color, ${DesignToken.color.onSurface});
558
+ }
559
+ .state-layer {
560
+ margin-inline: auto;
561
+ }
562
+ :host([selected].-has-items:not(:disabled)) .base {
563
+ background-color: var(--m3e-nav-menu-item-open-container-color, ${DesignToken.color.surfaceContainerHighest});
564
+ --m3e-state-layer-focus-color: var(
565
+ --m3e-nav-menu-item-open-container-focus-color,
566
+ ${DesignToken.color.onSurface}
567
+ );
568
+ --m3e-state-layer-hover-color: var(
569
+ --m3e-nav-menu-item-open-container-hover-color,
570
+ ${DesignToken.color.onSurface}
571
+ );
572
+ --m3e-ripple-color: var(--m3e-nav-menu-item-open-ripple-color, ${DesignToken.color.onSurface});
573
+ }
574
+ ::slotted(a[slot="label"]) {
575
+ all: unset;
576
+ }
577
+ ::slotted(m3e-divider) {
578
+ margin-block: var(--m3e-nav-menu-divider-margin, 0.25rem);
579
+ }
580
+ ::slotted(m3e-nav-menu-item:first-of-type) {
581
+ margin-block-start: var(--m3e-nav-menu-item-vertical-inset, 0.25rem);
582
+ }
583
+ ::slotted(m3e-nav-menu-item:last-of-type) {
584
+ margin-block-end: var(--m3e-nav-menu-item-vertical-inset, 0.25rem);
585
+ }
586
+ @media (prefers-reduced-motion) {
587
+ .base,
588
+ .toggle,
589
+ .state-layer {
590
+ transition: none !important;
591
+ }
592
+ }
593
+ @media (forced-colors: active) {
594
+ .base,
595
+ .state-layer {
596
+ transition: none !important;
597
+ }
598
+
599
+ :host(:disabled) .base {
600
+ color: GrayText;
601
+ }
602
+ :host(:not([selected]):not(:disabled)) .base {
603
+ color: ButtonText;
604
+ }
605
+ :host([selected]:not(.-has-items):not(:disabled)) .base {
606
+ forced-color-adjust: none;
607
+ color: ButtonFace;
608
+ background-color: ButtonText;
609
+ }
610
+ :host([selected].-has-items:not(:disabled)) .base {
611
+ background-color: unset;
612
+ color: ButtonText;
613
+ }
614
+ }
615
+ `;
616
+ __decorate([
617
+ e$1(".state-layer")
618
+ ], M3eNavMenuItemElement.prototype, "stateLayer", void 0);
619
+ __decorate([
620
+ e$1(".focus-ring")
621
+ ], M3eNavMenuItemElement.prototype, "focusRing", void 0);
622
+ __decorate([
623
+ e$1(".ripple")
624
+ ], M3eNavMenuItemElement.prototype, "ripple", void 0);
625
+ __decorate([
626
+ e$1(".base")
627
+ ], M3eNavMenuItemElement.prototype, "_base", void 0);
628
+ __decorate([
629
+ r$1()
630
+ ], M3eNavMenuItemElement.prototype, "_hasChildItems", void 0);
631
+ __decorate([
632
+ n$1({ type: Boolean, reflect: true })
633
+ ], M3eNavMenuItemElement.prototype, "open", void 0);
634
+ M3eNavMenuItemElement = M3eNavMenuItemElement_1 = __decorate([
635
+ t$2("m3e-nav-menu-item")
636
+ ], M3eNavMenuItemElement);
637
+
638
+ var _M3eNavMenuElement_instances, _M3eNavMenuElement_ignoreFocusVisible, _M3eNavMenuElement_ignoreFocus, _M3eNavMenuElement_keyDownHandler, _M3eNavMenuElement_keyUpHandler, _M3eNavMenuElement_pointerDownHandler, _M3eNavMenuElement_handleSlotChange, _M3eNavMenuElement_handleKeyDown, _M3eNavMenuElement_handleKeyUp, _M3eNavMenuElement_handlePointerDown, _M3eNavMenuElement_activateItem, _M3eNavMenuElement_updateFocusVisible, _M3eNavMenuElement_updateItemFocusVisible, _b;
639
+ var M3eNavMenuElement_1;
640
+ /**
641
+ * A hierarchical menu, typically used on larger devices, that allows a user to switch between views.
642
+ *
643
+ * @description
644
+ * The `m3e-nav-menu` component provides a hierarchical, accessible navigation menu supporting
645
+ * nested expandable items, keyboard navigation, and focus management. It is highly customizable
646
+ * via slots and CSS custom properties, and is designed for use in sidebars, navigation drawers,
647
+ * and complex menu structures.
648
+ *
649
+ * @example
650
+ * The following example illustrates a navigation menu with a top-level group of menu items.
651
+ * ```html
652
+ * <m3e-nav-menu>
653
+ * <m3e-nav-menu-item-group>
654
+ * <m3e-heading slot="label" variant="label" size="large">Mail</m3e-heading>
655
+ * <m3e-nav-menu-item>
656
+ * <m3e-icon slot="icon" name="mail"></m3e-icon>
657
+ * <span slot="label">Inbox</span>
658
+ * <span slot="badge">24</span>
659
+ * </m3e-nav-menu-item>
660
+ * <m3e-nav-menu-item>
661
+ * <m3e-icon slot="icon" name="send"></m3e-icon>
662
+ * <span slot="label">Outbox</span>
663
+ * </m3e-nav-menu-item>
664
+ * <m3e-nav-menu-item>
665
+ * <m3e-icon slot="icon" name="favorite"></m3e-icon>
666
+ * <span slot="label">Favorites</span>
667
+ * </m3e-nav-menu-item>
668
+ * <m3e-nav-menu-item>
669
+ * <m3e-icon slot="icon" name="delete"></m3e-icon>
670
+ * <span slot="label">Trash</span>
671
+ * </m3e-nav-menu-item>
672
+ * </m3e-nav-menu-item-group>
673
+ * </m3e-nav-menu>
674
+ * ```
419
675
  *
420
676
  * @example
421
- * The following example illustrates a multilevel navigation menu.
677
+ * The next example illustrates a multilevel navigation menu.
422
678
  * ```html
423
679
  * <m3e-nav-menu>
424
680
  * <m3e-nav-menu-item open>
@@ -442,460 +698,388 @@ var M3eNavMenuItemElement_1;
442
698
  * </m3e-nav-menu>
443
699
  * ```
444
700
  *
445
- * @tag m3e-nav-menu-item
446
- *
447
- * @slot - Renders the nested child items.
448
- * @slot label - Renders the label of the item.
449
- * @slot icon - Renders the icon of the item.
450
- * @slot selected-icon - Renders the icon of the item when selected.
451
- * @slot toggle-icon - Renders the toggle icon.
452
- *
453
- * @attr disabled - Whether the element is disabled.
454
- * @attr indeterminate - Whether the element's selected / checked state is indeterminate.
455
- * @attr open - Whether the item is expanded.
456
- * @attr selected - Whether the item is selected.
701
+ * @tag m3e-nav-menu
457
702
  *
458
- * @fires opening - Emitted when the item begins to open.
459
- * @fires opened - Emitted when the item has opened.
460
- * @fires closing - Emitted when the item begins to close.
461
- * @fires closed - Emitted when the item has closed.
462
- * @fires click - Emitted when the element is clicked.
703
+ * @slot - Renders the items of the menu.
463
704
  *
464
- * @cssprop --m3e-nav-menu-item-font-size - Font size for the item label.
465
- * @cssprop --m3e-nav-menu-item-font-weight - Font weight for the item label.
466
- * @cssprop --m3e-nav-menu-item-line-height - Line height for the item label.
467
- * @cssprop --m3e-nav-menu-item-tracking - Letter spacing for the item label.
468
- * @cssprop --m3e-nav-menu-item-padding - Inline padding for the item.
469
- * @cssprop --m3e-nav-menu-item-height - Height of the item.
470
- * @cssprop --m3e-nav-menu-item-spacing - Spacing between icon and label.
471
- * @cssprop --m3e-nav-menu-item-shape - Border radius of the item and focus ring.
472
- * @cssprop --m3e-nav-menu-item-icon-size - Size of the icon.
473
- * @cssprop --m3e-nav-menu-item-inset - Indentation for nested items.
474
- * @cssprop --m3e-nav-menu-item-label-color - Text color for the item label.
475
- * @cssprop --m3e-nav-menu-item-selected-label-color - Text color for selected item label.
476
- * @cssprop --m3e-nav-menu-item-selected-container-color - Background color for selected item.
477
- * @cssprop --m3e-nav-menu-item-selected-container-focus-color - Focus color for selected item container.
478
- * @cssprop --m3e-nav-menu-item-selected-container-hover-color - Hover color for selected item container.
479
- * @cssprop --m3e-nav-menu-item-selected-ripple-color - Ripple color for selected item.
480
- * @cssprop --m3e-nav-menu-item-unselected-container-focus-color - Focus color for unselected item container.
481
- * @cssprop --m3e-nav-menu-item-unselected-container-hover-color - Hover color for unselected item container.
482
- * @cssprop --m3e-nav-menu-item-unselected-ripple-color - Ripple color for unselected item.
483
- * @cssprop --m3e-nav-menu-item-open-container-color - Background color for open item with children.
484
- * @cssprop --m3e-nav-menu-item-open-container-focus-color - Focus color for open item container.
485
- * @cssprop --m3e-nav-menu-item-open-container-hover-color - Hover color for open item container.
486
- * @cssprop --m3e-nav-menu-item-open-ripple-color - Ripple color for open item.
487
- * @cssprop --m3e-nav-menu-item-disabled-color - Text color for disabled item.
488
- * @cssprop --m3e-nav-menu-item-disabled-color-opacity - Opacity for disabled item text color.
489
- * @cssprop --m3e-nav-menu-item-badge-font-size - Font size for badge slot.
490
- * @cssprop --m3e-nav-menu-item-badge-font-weight - Font weight for badge slot.
491
- * @cssprop --m3e-nav-menu-item-badge-line-height - Line height for badge slot.
492
- * @cssprop --m3e-nav-menu-badge-item-tracking - Letter spacing for badge slot.
493
- * @cssprop --m3e-nav-menu-divider-margin - Margin for divider elements.
494
- * @cssprop --m3e-nav-menu-item-vertical-inset - Vertical margin for first/last child items.
495
- */
496
- let M3eNavMenuItemElement = M3eNavMenuItemElement_1 = class M3eNavMenuItemElement extends Selected(Disabled(EventAttribute(AttachInternals(Role(LitElement, "treeitem"), true), "opening", "opened", "closing", "closed"))) {
705
+ * @cssprop --m3e-nav-menu-padding-top - Top padding for the menu.
706
+ * @cssprop --m3e-nav-menu-padding-bottom - Bottom padding for the menu.
707
+ * @cssprop --m3e-nav-menu-padding-left - Left padding for the menu.
708
+ * @cssprop --m3e-nav-menu-padding-right - Right padding for the menu.
709
+ * @cssprop --m3e-nav-menu-divider-margin - Margin for divider elements in the menu.
710
+ * @cssprop --m3e-nav-menu-scrollbar-width - Width of the menu scrollbar.
711
+ * @cssprop --m3e-nav-menu-scrollbar-color - Color of the menu scrollbar.
712
+ */
713
+ let M3eNavMenuElement = M3eNavMenuElement_1 = class M3eNavMenuElement extends Role(LitElement, "tree") {
497
714
  constructor() {
498
- super(...arguments);
499
- _M3eNavMenuItemElement_instances.add(this);
500
- /** @private */ this._hasChildItems = false;
501
- /** @private */ _M3eNavMenuItemElement_items.set(this, []);
502
- /** @private */ _M3eNavMenuItemElement_menu.set(this, null);
503
- /** @private */ _M3eNavMenuItemElement_path.set(this, new Array());
504
- /** @private */ _M3eNavMenuItemElement_link.set(this, null);
505
- /**
506
- * Whether the item is expanded.
507
- * @default false
508
- */
509
- this.open = false;
510
- }
511
- /** A reference to the nested `HTMLAnchorElement`. */
512
- get link() {
513
- return __classPrivateFieldGet(this, _M3eNavMenuItemElement_link, "f");
514
- }
515
- /** A reference to the element used to present the label of the item. */
516
- get label() {
517
- return this._base ?? null;
518
- }
519
- /** Whether the item is visible. */
520
- get visible() {
521
- return !__classPrivateFieldGet(this, _M3eNavMenuItemElement_path, "f").some((x) => !x.open);
522
- }
523
- /** The full path of the item, starting with the top-most ancestor, including this item. */
524
- get path() {
525
- return [...__classPrivateFieldGet(this, _M3eNavMenuItemElement_path, "f"), this];
526
- }
527
- /** Whether the item has child items. */
528
- get hasChildItems() {
529
- return this._hasChildItems;
530
- }
531
- /** The parenting item. */
532
- get parentItem() {
533
- return __classPrivateFieldGet(this, _M3eNavMenuItemElement_path, "f")[__classPrivateFieldGet(this, _M3eNavMenuItemElement_path, "f").length - 1] ?? null;
715
+ super();
716
+ _M3eNavMenuElement_instances.add(this);
717
+ /** @private */ _M3eNavMenuElement_ignoreFocusVisible.set(this, false);
718
+ /** @private */ _M3eNavMenuElement_ignoreFocus.set(this, false);
719
+ /** @private */
720
+ this[_b] = new SelectionManager()
721
+ .withVerticalOrientation()
722
+ .withHomeAndEnd()
723
+ .withTypeahead()
724
+ .withSkipPredicate((x) => x.disabled || !x.visible)
725
+ .disableRovingTabIndex()
726
+ .onActiveItemChange(() => {
727
+ if (this[selectionManager].activeItem) {
728
+ __classPrivateFieldGet(this, _M3eNavMenuElement_instances, "m", _M3eNavMenuElement_activateItem).call(this, this[selectionManager].activeItem);
729
+ }
730
+ })
731
+ .onSelectedItemsChange(() => {
732
+ const selected = this.selected;
733
+ for (const item of this.items) {
734
+ if (item !== selected) {
735
+ __classPrivateFieldGet(this, _M3eNavMenuElement_instances, "m", _M3eNavMenuElement_updateItemFocusVisible).call(this, item, false, false);
736
+ }
737
+ }
738
+ if (selected?.label) {
739
+ scrollIntoViewIfNeeded(selected.label, this, { block: "start", behavior: "smooth" });
740
+ }
741
+ });
742
+ /** @private */ _M3eNavMenuElement_keyDownHandler.set(this, (e) => __classPrivateFieldGet(this, _M3eNavMenuElement_instances, "m", _M3eNavMenuElement_handleKeyDown).call(this, e));
743
+ /** @private */ _M3eNavMenuElement_keyUpHandler.set(this, (e) => __classPrivateFieldGet(this, _M3eNavMenuElement_instances, "m", _M3eNavMenuElement_handleKeyUp).call(this, e));
744
+ /** @private */ _M3eNavMenuElement_pointerDownHandler.set(this, (e) => __classPrivateFieldGet(this, _M3eNavMenuElement_instances, "m", _M3eNavMenuElement_handlePointerDown).call(this, e));
745
+ new PressedController(this, { callback: (pressed) => (__classPrivateFieldSet(this, _M3eNavMenuElement_ignoreFocus, pressed, "f")) });
746
+ new FocusController(this, {
747
+ callback: () => {
748
+ if (!__classPrivateFieldGet(this, _M3eNavMenuElement_ignoreFocus, "f")) {
749
+ __classPrivateFieldGet(this, _M3eNavMenuElement_instances, "m", _M3eNavMenuElement_updateFocusVisible).call(this);
750
+ }
751
+ },
752
+ });
534
753
  }
535
- /** The items that immediately descend from this item. */
536
- get childItems() {
537
- return __classPrivateFieldGet(this, _M3eNavMenuItemElement_items, "f");
754
+ /** The selected item of the menu. */
755
+ get selected() {
756
+ return this[selectionManager].selectedItems[0] ?? null;
538
757
  }
539
- /** The one-based level of the item. */
540
- get level() {
541
- return __classPrivateFieldGet(this, _M3eNavMenuItemElement_path, "f").length + 1;
758
+ /** All the items of the menu. */
759
+ get items() {
760
+ return this[selectionManager].items;
542
761
  }
543
762
  /**
544
- * Expands this item, and optionally, all descendants.
545
- * @param {boolean} [descendants=false] Whether to expand all descendants.
763
+ * Expands the specified items, or all items if no items are provided.
764
+ * @param {M3eNavMenuItemElement | undefined} items The items to expand.
546
765
  */
547
- expand(descendants = false) {
548
- if (this.hasChildItems) {
549
- this.open = true;
550
- if (descendants) {
551
- this.childItems.forEach((x) => x.expand(true));
552
- }
553
- }
766
+ expand(items) {
767
+ (items ?? this[selectionManager].items).forEach((x) => x.expand());
554
768
  }
555
769
  /**
556
- * Collapses this item, and optionally, all descendants.
557
- * @param {boolean} [descendants=false] Whether to expand all descendants.
770
+ * Collapses the specified items, or all items if no items are provided.
771
+ * @param {M3eNavMenuItemElement | undefined} items The items to collapse.
558
772
  */
559
- collapse(descendants = false) {
560
- if (this.hasChildItems) {
561
- this.open = false;
562
- if (descendants) {
563
- this.childItems.forEach((x) => x.collapse(true));
773
+ collapse(items) {
774
+ (items ?? this[selectionManager].items).forEach((x) => x.collapse());
775
+ const activeItem = this[selectionManager].activeItem;
776
+ if (activeItem && !activeItem.visible) {
777
+ for (let parent = activeItem.parentItem; parent; parent = parent.parentItem) {
778
+ if (parent.visible) {
779
+ this[selectionManager].setActiveItem(parent);
780
+ break;
781
+ }
564
782
  }
565
783
  }
566
784
  }
567
- /** Toggles the expanded state of the item. */
568
- toggle() {
569
- if (this.hasChildItems) {
570
- this.open = !this.open;
571
- }
572
- }
573
785
  /** @inheritdoc */
574
786
  connectedCallback() {
575
787
  super.connectedCallback();
576
- __classPrivateFieldGet(this, _M3eNavMenuItemElement_path, "f").length = 0;
577
- for (let item = this.parentElement?.closest("m3e-nav-menu-item"); item; item = item.parentElement?.closest("m3e-nav-menu-item")) {
578
- __classPrivateFieldGet(this, _M3eNavMenuItemElement_path, "f").push(item);
579
- }
580
- __classPrivateFieldGet(this, _M3eNavMenuItemElement_path, "f").reverse();
581
- this.style.setProperty("--_nav-menu-item-level", `${this.level}`);
582
- __classPrivateFieldSet(this, _M3eNavMenuItemElement_menu, this.closest("m3e-nav-menu"), "f");
788
+ this.setAttribute("tabindex", "0");
789
+ this.addEventListener("keydown", __classPrivateFieldGet(this, _M3eNavMenuElement_keyDownHandler, "f"));
790
+ this.addEventListener("keyup", __classPrivateFieldGet(this, _M3eNavMenuElement_keyUpHandler, "f"));
791
+ this.addEventListener("pointerdown", __classPrivateFieldGet(this, _M3eNavMenuElement_pointerDownHandler, "f"));
583
792
  }
584
793
  /** @inheritdoc */
585
794
  disconnectedCallback() {
586
795
  super.disconnectedCallback();
587
- __classPrivateFieldGet(this, _M3eNavMenuItemElement_path, "f").length = 0;
588
- }
589
- /** @inheritdoc */
590
- update(changedProperties) {
591
- super.update(changedProperties);
592
- if (changedProperties.has("selected")) {
593
- this.ariaCurrent = this.hasChildItems ? null : `${this.selected}`;
594
- for (const icon of this.querySelectorAll(":scope > m3e-icon[slot]")) {
595
- icon.toggleAttribute("filled", this.selected);
596
- }
597
- __classPrivateFieldGet(this, _M3eNavMenuItemElement_path, "f").forEach((x) => (x.selected = this.selected));
598
- if (this.selected && !this.hasChildItems) {
599
- this.closest("m3e-nav-menu")?.[selectionManager].notifySelectionChange(this);
600
- }
601
- }
602
- }
603
- /** @inheritdoc */
604
- firstUpdated(_changedProperties) {
605
- super.firstUpdated(_changedProperties);
606
- const base = this._base;
607
- if (base) {
608
- [this.focusRing, this.stateLayer, this.ripple].forEach((x) => x?.attach(base));
609
- }
796
+ this.removeEventListener("keydown", __classPrivateFieldGet(this, _M3eNavMenuElement_keyDownHandler, "f"));
797
+ this.removeEventListener("keyup", __classPrivateFieldGet(this, _M3eNavMenuElement_keyUpHandler, "f"));
798
+ this.removeEventListener("pointerdown", __classPrivateFieldGet(this, _M3eNavMenuElement_pointerDownHandler, "f"));
610
799
  }
611
800
  /** @inheritdoc */
612
801
  render() {
613
- return html `<div class="base" @click="${__classPrivateFieldGet(this, _M3eNavMenuItemElement_instances, "m", _M3eNavMenuItemElement_handleClick)}">
614
- <m3e-state-layer class="state-layer" ?disabled="${this.disabled}"></m3e-state-layer>
615
- <m3e-focus-ring class="focus-ring" inward ?disabled="${this.disabled}"></m3e-focus-ring>
616
- <m3e-ripple class="ripple" centered ?disabled="${this.disabled}"></m3e-ripple>
617
- <div class="icon">${__classPrivateFieldGet(this, _M3eNavMenuItemElement_instances, "m", _M3eNavMenuItemElement_renderIcon).call(this)}</div>
618
- <div class="label">
619
- <slot name="label" @slotchange="${__classPrivateFieldGet(this, _M3eNavMenuItemElement_instances, "m", _M3eNavMenuItemElement_handleSlotChange)}"></slot>
620
- </div>
621
- <slot name="badge"></slot>
622
- <div aria-hidden="true" class="toggle">
623
- <slot name="toggle-icon">
624
- <svg class="toggle-icon" viewBox="0 -960 960 960" fill="currentColor">
625
- <path d="M480-360 280-560h400L480-360Z" />
626
- </svg>
627
- </slot>
628
- </div>
629
- </div>
630
- <m3e-collapsible
631
- class="group"
632
- role="group"
633
- aria-hidden="${o(this._hasChildItems ? undefined : "true")}"
634
- ?open="${this._hasChildItems && this.open}"
635
- @opening="${__classPrivateFieldGet(this, _M3eNavMenuItemElement_instances, "m", _M3eNavMenuItemElement_handleCollapsibleEvent)}"
636
- @opened="${__classPrivateFieldGet(this, _M3eNavMenuItemElement_instances, "m", _M3eNavMenuItemElement_handleCollapsibleEvent)}"
637
- @closing="${__classPrivateFieldGet(this, _M3eNavMenuItemElement_instances, "m", _M3eNavMenuItemElement_handleCollapsibleEvent)}"
638
- @closed="${__classPrivateFieldGet(this, _M3eNavMenuItemElement_instances, "m", _M3eNavMenuItemElement_handleCollapsibleEvent)}"
639
- >
640
- <slot @slotchange="${__classPrivateFieldGet(this, _M3eNavMenuItemElement_instances, "m", _M3eNavMenuItemElement_handleItemSlotChange)}"></slot>
641
- </m3e-collapsible>`;
802
+ return html `<slot @slotchange="${__classPrivateFieldGet(this, _M3eNavMenuElement_instances, "m", _M3eNavMenuElement_handleSlotChange)}"></slot>`;
642
803
  }
643
804
  };
644
- _M3eNavMenuItemElement_items = new WeakMap();
645
- _M3eNavMenuItemElement_menu = new WeakMap();
646
- _M3eNavMenuItemElement_path = new WeakMap();
647
- _M3eNavMenuItemElement_link = new WeakMap();
648
- _M3eNavMenuItemElement_instances = new WeakSet();
649
- _M3eNavMenuItemElement_renderIcon = function _M3eNavMenuItemElement_renderIcon() {
650
- const icon = html `<slot name="icon" @slotchange="${__classPrivateFieldGet(this, _M3eNavMenuItemElement_instances, "m", _M3eNavMenuItemElement_handleIconSlotChange)}"></slot>`;
651
- return this.selected && !this.hasChildItems
652
- ? html `<slot name="selected-icon" @slotchange="${__classPrivateFieldGet(this, _M3eNavMenuItemElement_instances, "m", _M3eNavMenuItemElement_handleIconSlotChange)}">${icon}</slot>`
653
- : icon;
654
- };
655
- _M3eNavMenuItemElement_handleIconSlotChange = function _M3eNavMenuItemElement_handleIconSlotChange(e) {
656
- this.classList.toggle("-with-icon", hasAssignedNodes(e.target));
657
- };
658
- _M3eNavMenuItemElement_handleSlotChange = function _M3eNavMenuItemElement_handleSlotChange(e) {
659
- __classPrivateFieldSet(this, _M3eNavMenuItemElement_link, e.target.assignedElements({ flatten: true }).find((x) => x instanceof HTMLAnchorElement) ??
660
- null, "f");
661
- __classPrivateFieldGet(this, _M3eNavMenuItemElement_link, "f")?.setAttribute("tabindex", "-1");
662
- };
663
- _M3eNavMenuItemElement_handleItemSlotChange = function _M3eNavMenuItemElement_handleItemSlotChange(e) {
664
- __classPrivateFieldSet(this, _M3eNavMenuItemElement_items, e.target
665
- .assignedElements({ flatten: true })
666
- .filter((x) => x instanceof M3eNavMenuItemElement_1), "f");
667
- const hadChildItems = this._hasChildItems;
668
- this._hasChildItems = __classPrivateFieldGet(this, _M3eNavMenuItemElement_items, "f").length > 0;
669
- this.classList.toggle("-has-items", this._hasChildItems);
670
- if (hadChildItems || this._hasChildItems) {
671
- this.selected = __classPrivateFieldGet(this, _M3eNavMenuItemElement_items, "f").some((x) => x.selected);
805
+ _M3eNavMenuElement_ignoreFocusVisible = new WeakMap();
806
+ _M3eNavMenuElement_ignoreFocus = new WeakMap();
807
+ _M3eNavMenuElement_keyDownHandler = new WeakMap();
808
+ _M3eNavMenuElement_keyUpHandler = new WeakMap();
809
+ _M3eNavMenuElement_pointerDownHandler = new WeakMap();
810
+ _M3eNavMenuElement_instances = new WeakSet();
811
+ _b = selectionManager;
812
+ _M3eNavMenuElement_handleSlotChange = function _M3eNavMenuElement_handleSlotChange() {
813
+ for (const divider of this.querySelectorAll("m3e-divider")) {
814
+ divider.ariaHidden = "true";
815
+ }
816
+ const { added } = this[selectionManager].setItems([...this.querySelectorAll("m3e-nav-menu-item")]);
817
+ for (const item of added) {
818
+ item.id = item.id || `m3e-nav-menu-item-${M3eNavMenuElement_1.__nextId++}`;
819
+ }
820
+ if (this[selectionManager].activeItem) {
821
+ this.setAttribute("aria-activedescendant", this[selectionManager].activeItem.id);
822
+ __classPrivateFieldGet(this, _M3eNavMenuElement_instances, "m", _M3eNavMenuElement_updateFocusVisible).call(this);
823
+ }
824
+ else {
825
+ this.removeAttribute("aria-activedescendant");
672
826
  }
673
827
  };
674
- _M3eNavMenuItemElement_handleClick = function _M3eNavMenuItemElement_handleClick() {
675
- if (this.disabled)
828
+ _M3eNavMenuElement_handleKeyDown = function _M3eNavMenuElement_handleKeyDown(e) {
829
+ __classPrivateFieldSet(this, _M3eNavMenuElement_ignoreFocusVisible, false, "f");
830
+ __classPrivateFieldGet(this, _M3eNavMenuElement_instances, "m", _M3eNavMenuElement_updateFocusVisible).call(this);
831
+ const item = this[selectionManager].activeItem;
832
+ if (e.defaultPrevented || !item || item.disabled)
676
833
  return;
677
- __classPrivateFieldGet(this, _M3eNavMenuItemElement_menu, "f")?.[selectionManager].setActiveItem(this);
678
- if (!this._hasChildItems) {
679
- __classPrivateFieldGet(this, _M3eNavMenuItemElement_menu, "f")?.[selectionManager].select(this);
680
- __classPrivateFieldGet(this, _M3eNavMenuItemElement_path, "f").forEach((x) => (x.selected = this.selected));
681
- __classPrivateFieldGet(this, _M3eNavMenuItemElement_link, "f")?.click();
682
- const drawerContainer = this.closest("m3e-drawer-container");
683
- if (drawerContainer) {
684
- const drawer = this.closest("[slot='start']") ?? this.closest("[slot='end')");
685
- if (drawer &&
686
- (drawerContainer.classList.contains(`-${drawer.slot}-push`) ||
687
- drawerContainer.classList.contains(`-${drawer.slot}-over`))) {
688
- setTimeout(() => drawerContainer.removeAttribute(drawer.slot), 300);
834
+ switch (e.key) {
835
+ case "Enter":
836
+ case " ":
837
+ e.preventDefault();
838
+ if (item.ripple && !item.ripple.visible) {
839
+ item.ripple.show(0, 0, true);
840
+ }
841
+ if (item.hasChildItems) {
842
+ item.toggle();
843
+ }
844
+ else if (!item.selected) {
845
+ this[selectionManager].select(item);
846
+ item.link?.click();
847
+ }
848
+ break;
849
+ case "*":
850
+ e.preventDefault();
851
+ item.expand(true);
852
+ break;
853
+ case "Left":
854
+ case "ArrowLeft":
855
+ e.preventDefault();
856
+ if (item.hasChildItems && item.open) {
857
+ item.collapse();
689
858
  }
859
+ else {
860
+ const parent = item.parentItem;
861
+ if (parent) {
862
+ parent.collapse();
863
+ this[selectionManager].setActiveItem(parent);
864
+ }
865
+ }
866
+ break;
867
+ case "Right":
868
+ case "ArrowRight":
869
+ if (item.hasChildItems) {
870
+ if (!item.open) {
871
+ e.preventDefault();
872
+ item.expand();
873
+ }
874
+ else {
875
+ try {
876
+ this[selectionManager].vertical = false;
877
+ this[selectionManager].onKeyDown(e);
878
+ }
879
+ finally {
880
+ this[selectionManager].vertical = true;
881
+ }
882
+ }
883
+ }
884
+ else {
885
+ e.preventDefault();
886
+ }
887
+ break;
888
+ default:
889
+ this[selectionManager].onKeyDown(e);
890
+ break;
891
+ }
892
+ };
893
+ _M3eNavMenuElement_handleKeyUp = function _M3eNavMenuElement_handleKeyUp(e) {
894
+ const item = this[selectionManager].activeItem;
895
+ if (e.defaultPrevented || !item || item.disabled)
896
+ return;
897
+ switch (e.key) {
898
+ case "Enter":
899
+ case " ":
900
+ item.ripple?.hide();
901
+ break;
902
+ }
903
+ };
904
+ _M3eNavMenuElement_handlePointerDown = function _M3eNavMenuElement_handlePointerDown(e) {
905
+ if (!e.defaultPrevented && !__classPrivateFieldGet(this, _M3eNavMenuElement_ignoreFocusVisible, "f")) {
906
+ __classPrivateFieldSet(this, _M3eNavMenuElement_ignoreFocusVisible, true, "f");
907
+ const item = e
908
+ .composedPath()
909
+ .reverse()
910
+ .find((x) => x instanceof M3eNavMenuItemElement);
911
+ if (item && !item.disabled) {
912
+ __classPrivateFieldGet(this, _M3eNavMenuElement_instances, "m", _M3eNavMenuElement_updateItemFocusVisible).call(this, item, true, false);
690
913
  }
691
914
  }
692
- else {
693
- this.toggle();
915
+ };
916
+ _M3eNavMenuElement_activateItem = function _M3eNavMenuElement_activateItem(item) {
917
+ this.setAttribute("aria-activedescendant", item.id);
918
+ if (item.label) {
919
+ scrollIntoViewIfNeeded(item.label, this, { block: "nearest", behavior: "smooth" });
694
920
  }
921
+ __classPrivateFieldGet(this, _M3eNavMenuElement_instances, "m", _M3eNavMenuElement_updateFocusVisible).call(this);
695
922
  };
696
- _M3eNavMenuItemElement_handleCollapsibleEvent = function _M3eNavMenuItemElement_handleCollapsibleEvent(e) {
697
- e.stopPropagation();
698
- this.dispatchEvent(new Event(e.type, { bubbles: true }));
923
+ _M3eNavMenuElement_updateFocusVisible = function _M3eNavMenuElement_updateFocusVisible() {
924
+ const focused = this.matches(":focus") || this.matches(":focus-within");
925
+ const focusVisible = !__classPrivateFieldGet(this, _M3eNavMenuElement_ignoreFocusVisible, "f") && this.matches(":focus-visible");
926
+ this[selectionManager].items.forEach((x) => {
927
+ const active = x === this[selectionManager].activeItem;
928
+ __classPrivateFieldGet(this, _M3eNavMenuElement_instances, "m", _M3eNavMenuElement_updateItemFocusVisible).call(this, x, active && focused, active && focusVisible);
929
+ });
930
+ };
931
+ _M3eNavMenuElement_updateItemFocusVisible = function _M3eNavMenuElement_updateItemFocusVisible(item, focused, focusVisible) {
932
+ if (focused) {
933
+ item.stateLayer?.show("focused");
934
+ }
935
+ else {
936
+ item.stateLayer?.hide("focused");
937
+ }
938
+ if (focusVisible) {
939
+ item.focusRing?.show();
940
+ }
941
+ else {
942
+ item.focusRing?.hide();
943
+ }
699
944
  };
700
945
  /** The styles of the element. */
701
- M3eNavMenuItemElement.styles = css `
946
+ M3eNavMenuElement.styles = css `
702
947
  :host {
703
- display: block;
704
- flex: none;
705
- outline: none;
706
- position: relative;
707
- font-size: var(--m3e-nav-menu-item-font-size, ${DesignToken.typescale.standard.label.large.fontSize});
708
- font-weight: var(--m3e-nav-menu-item-font-weight, ${DesignToken.typescale.standard.label.large.fontWeight});
709
- line-height: var(--m3e-nav-menu-item-line-height, ${DesignToken.typescale.standard.label.large.lineHeight});
710
- letter-spacing: var(--m3e-nav-menu-item-tracking, ${DesignToken.typescale.standard.label.large.tracking});
711
- }
712
- .base {
713
- display: flex;
714
- align-items: center;
715
- position: relative;
716
- padding-inline: var(--m3e-nav-menu-item-padding, 1.5rem);
717
- height: calc(var(--m3e-nav-menu-item-height, 3.5rem) + ${DesignToken.density.calc(-3)});
718
- column-gap: var(--m3e-nav-menu-item-spacing, 0.75rem);
719
- transition: ${unsafeCSS(`color ${DesignToken.motion.duration.short4} ${DesignToken.motion.easing.standard},
720
- background-color ${DesignToken.motion.duration.short4} ${DesignToken.motion.easing.standard}`)};
721
- }
722
- .base,
723
- .focus-ring {
724
- border-radius: var(--m3e-nav-menu-item-shape, ${DesignToken.shape.corner.full});
725
- }
726
- .label {
727
- flex: 1 1 auto;
728
- display: flex;
729
- align-items: center;
730
- position: relative;
731
- overflow: hidden;
732
- vertical-align: middle;
733
- }
734
- .icon,
735
- .toggle {
736
- flex: none;
737
948
  display: flex;
738
- align-items: center;
739
- justify-content: center;
740
- position: relative;
741
- vertical-align: middle;
742
- }
743
- ::slotted([slot="badge"]) {
744
- flex: none;
949
+ flex-direction: column;
950
+ outline: none;
951
+ overflow-y: auto;
952
+ overflow-x: hidden;
745
953
  position: relative;
746
- font-size: var(--m3e-nav-menu-item-badge-font-size, ${DesignToken.typescale.standard.label.large.fontSize});
747
- font-weight: var(--m3e-nav-menu-item-badge-font-weight, ${DesignToken.typescale.standard.label.large.fontWeight});
748
- line-height: var(--m3e-nav-menu-item-badge-line-height, ${DesignToken.typescale.standard.label.large.lineHeight});
749
- letter-spacing: var(--m3e-nav-menu-badge-item-tracking, ${DesignToken.typescale.standard.label.large.tracking});
750
- }
751
- .toggle {
752
- transition: ${unsafeCSS(`transform var(--m3e-collapsible-animation-duration, ${DesignToken.motion.duration.medium1})
753
- ${DesignToken.motion.easing.standard}`)};
754
- }
755
- :host(:not(.-with-icon)) .icon {
756
- display: none;
757
- }
758
- .icon {
759
- margin-inline-start: -0.5rem;
760
- }
761
- .toggle {
762
- margin-inline-end: -0.5rem;
763
- }
764
- .group {
765
- padding-inline-start: var(--m3e-nav-menu-item-inset, 1rem);
766
- }
767
- :host([open]) .toggle {
768
- transform: rotate(180deg);
769
- }
770
- :host(:not(.-has-items)) .toggle,
771
- :host(:not(.-has-items)) .group {
772
- display: none;
773
- }
774
- ::slotted([slot="selected-icon"]),
775
- ::slotted([slot="icon"]),
776
- ::slotted([slot="toggle-icon"]),
777
- .toggle-icon {
778
- vertical-align: middle;
779
- width: 1em;
780
- height: 1em;
781
- font-size: var(--m3e-nav-menu-item-icon-size, 1.5rem);
782
- }
783
- :host(:not(:disabled)) .base {
784
- cursor: pointer;
785
- }
786
- :host(:not(:disabled)) .base {
787
- color: var(--m3e-nav-menu-item-label-color, ${DesignToken.color.onSurfaceVariant});
788
- }
789
- :host(:disabled) .base {
790
- color: color-mix(
791
- in srgb,
792
- var(--m3e-nav-menu-item-disabled-color, ${DesignToken.color.onSurface})
793
- var(--m3e-nav-menu-item-disabled-color-opacity, 38%),
794
- transparent
795
- );
796
- }
797
- :host([selected]:not(.-has-items):not(:disabled)) .base {
798
- color: var(--m3e-nav-menu-item-selected-label-color, ${DesignToken.color.onSecondaryContainer});
799
- background-color: var(--m3e-nav-menu-item-selected-container-color, ${DesignToken.color.secondaryContainer});
800
- --m3e-state-layer-focus-color: var(
801
- --m3e-nav-menu-item-selected-container-focus-color,
802
- ${DesignToken.color.onSecondaryContainer}
803
- );
804
- --m3e-state-layer-hover-color: var(
805
- --m3e-nav-menu-item-selected-container-hover-color,
806
- ${DesignToken.color.onSecondaryContainer}
807
- );
808
- --m3e-ripple-color: var(--m3e-nav-menu-item-selected-ripple-color, ${DesignToken.color.onSecondaryContainer});
809
- }
810
- :host(:not([selected]):not(.-has-items):not(:disabled)) .base {
811
- --m3e-state-layer-focus-color: var(
812
- --m3e-nav-menu-item-unselected-container-focus-color,
813
- ${DesignToken.color.onSurface}
814
- );
815
- --m3e-state-layer-hover-color: var(
816
- --m3e-nav-menu-item-unselected-container-hover-color,
817
- ${DesignToken.color.onSurface}
818
- );
819
- --m3e-ripple-color: var(--m3e-nav-menu-item-unselected-ripple-color, ${DesignToken.color.onSurface});
820
- }
821
- .state-layer {
822
- margin-inline: auto;
823
- }
824
- :host([selected].-has-items:not(:disabled)) .base {
825
- background-color: var(--m3e-nav-menu-item-open-container-color, ${DesignToken.color.surfaceContainerHighest});
826
- --m3e-state-layer-focus-color: var(
827
- --m3e-nav-menu-item-open-container-focus-color,
828
- ${DesignToken.color.onSurface}
829
- );
830
- --m3e-state-layer-hover-color: var(
831
- --m3e-nav-menu-item-open-container-hover-color,
832
- ${DesignToken.color.onSurface}
833
- );
834
- --m3e-ripple-color: var(--m3e-nav-menu-item-open-ripple-color, ${DesignToken.color.onSurface});
835
- }
836
- ::slotted(a[slot="label"]) {
837
- all: unset;
954
+ min-height: 0;
955
+ padding-block-start: var(--m3e-nav-menu-padding-top, 0.5rem);
956
+ padding-block-end: var(--m3e-nav-menu-padding-bottom, 0.5rem);
957
+ padding-inline-start: var(--m3e-nav-menu-padding-left, 0.75rem);
958
+ padding-inline-end: var(--m3e-nav-menu-padding-right, 0.75rem);
959
+ scrollbar-width: ${DesignToken.scrollbar.width};
960
+ scrollbar-color: ${DesignToken.scrollbar.color};
838
961
  }
839
962
  ::slotted(m3e-divider) {
840
963
  margin-block: var(--m3e-nav-menu-divider-margin, 0.25rem);
964
+ flex: none;
841
965
  }
842
- ::slotted(m3e-nav-menu-item:first-of-type) {
843
- margin-block-start: var(--m3e-nav-menu-item-vertical-inset, 0.25rem);
966
+ `;
967
+ /** @private */ M3eNavMenuElement.__nextId = 0;
968
+ M3eNavMenuElement = M3eNavMenuElement_1 = __decorate([
969
+ t$2("m3e-nav-menu")
970
+ ], M3eNavMenuElement);
971
+
972
+ var _M3eNavMenuItemGroupElement_instances, _M3eNavMenuItemGroupElement_labelId, _M3eNavMenuItemGroupElement_label, _M3eNavMenuItemGroupElement_handleLabelSlotChange;
973
+ var M3eNavMenuItemGroupElement_1;
974
+ /**
975
+ * A top-level semantic grouping of items in a navigation menu.
976
+ *
977
+ * @description
978
+ * The `m3e-nav-menu-item-group` is a top-level semantic grouping of items in a navigation menu.
979
+ * It encapsulates related items under a shared heading or label, supporting visual hierarchy and accessibility.
980
+ *
981
+ * @example
982
+ * The following example illustrates a navigation menu with a top-level group of menu items.
983
+ * ```html
984
+ * <m3e-nav-menu>
985
+ * <m3e-nav-menu-item-group>
986
+ * <m3e-heading slot="label" variant="label" size="large">Mail</m3e-heading>
987
+ * <m3e-nav-menu-item>
988
+ * <m3e-icon slot="icon" name="mail"></m3e-icon>
989
+ * <span slot="label">Inbox</span>
990
+ * <span slot="badge">24</span>
991
+ * </m3e-nav-menu-item>
992
+ * <m3e-nav-menu-item>
993
+ * <m3e-icon slot="icon" name="send"></m3e-icon>
994
+ * <span slot="label">Outbox</span>
995
+ * </m3e-nav-menu-item>
996
+ * <m3e-nav-menu-item>
997
+ * <m3e-icon slot="icon" name="favorite"></m3e-icon>
998
+ * <span slot="label">Favorites</span>
999
+ * </m3e-nav-menu-item>
1000
+ * <m3e-nav-menu-item>
1001
+ * <m3e-icon slot="icon" name="delete"></m3e-icon>
1002
+ * <span slot="label">Trash</span>
1003
+ * </m3e-nav-menu-item>
1004
+ * </m3e-nav-menu-item-group>
1005
+ * </m3e-nav-menu>
1006
+ * ```
1007
+ *
1008
+ * @tag m3e-nav-menu-item-group
1009
+ *
1010
+ * @slot - Renders the items of the group.
1011
+ * @slot label - Renders the label of the group.
1012
+ *
1013
+ * @cssprop --m3e-nav-menu-item-group-label-inset - Insets the label from the start edge of the group.
1014
+ * @cssprop --m3e-nav-menu-item-group-label-space - Vertical spacing around the group's label.
1015
+ */
1016
+ let M3eNavMenuItemGroupElement = M3eNavMenuItemGroupElement_1 = class M3eNavMenuItemGroupElement extends Role(LitElement, "group") {
1017
+ constructor() {
1018
+ super(...arguments);
1019
+ _M3eNavMenuItemGroupElement_instances.add(this);
1020
+ /** @private */ _M3eNavMenuItemGroupElement_labelId.set(this, `m3e-nav-menu-item-group-label-${M3eNavMenuItemGroupElement_1.__nextId++}`);
1021
+ /** @private */ _M3eNavMenuItemGroupElement_label.set(this, void 0);
1022
+ }
1023
+ /** @inheritdoc */
1024
+ connectedCallback() {
1025
+ super.connectedCallback();
1026
+ this.classList.toggle("-divided", this.previousElementSibling?.tagName === "M3E-DIVIDER");
1027
+ }
1028
+ /** @inheritdoc */
1029
+ disconnectedCallback() {
1030
+ super.disconnectedCallback();
1031
+ this.classList.remove("-divided");
1032
+ }
1033
+ /** @inheritdoc */
1034
+ render() {
1035
+ return html `<slot name="label" @slotchange="${__classPrivateFieldGet(this, _M3eNavMenuItemGroupElement_instances, "m", _M3eNavMenuItemGroupElement_handleLabelSlotChange)}"></slot><slot></slot>`;
1036
+ }
1037
+ };
1038
+ _M3eNavMenuItemGroupElement_labelId = new WeakMap();
1039
+ _M3eNavMenuItemGroupElement_label = new WeakMap();
1040
+ _M3eNavMenuItemGroupElement_instances = new WeakSet();
1041
+ _M3eNavMenuItemGroupElement_handleLabelSlotChange = function _M3eNavMenuItemGroupElement_handleLabelSlotChange(e) {
1042
+ const label = e.target.assignedElements({ flatten: true })[0];
1043
+ if (label !== __classPrivateFieldGet(this, _M3eNavMenuItemGroupElement_label, "f")) {
1044
+ // If the label is changed and its id matched the reversed id,
1045
+ // clear the id in the event the element is moved elsewhere in the DOM.
1046
+ if (__classPrivateFieldGet(this, _M3eNavMenuItemGroupElement_label, "f")?.id === __classPrivateFieldGet(this, _M3eNavMenuItemGroupElement_labelId, "f")) {
1047
+ __classPrivateFieldGet(this, _M3eNavMenuItemGroupElement_label, "f").id = "";
1048
+ }
1049
+ __classPrivateFieldSet(this, _M3eNavMenuItemGroupElement_label, label, "f");
1050
+ if (__classPrivateFieldGet(this, _M3eNavMenuItemGroupElement_label, "f")) {
1051
+ __classPrivateFieldGet(this, _M3eNavMenuItemGroupElement_label, "f").role = "none";
1052
+ __classPrivateFieldGet(this, _M3eNavMenuItemGroupElement_label, "f").id = __classPrivateFieldGet(this, _M3eNavMenuItemGroupElement_label, "f").id || __classPrivateFieldGet(this, _M3eNavMenuItemGroupElement_labelId, "f");
1053
+ this.setAttribute("aria-labelledby", __classPrivateFieldGet(this, _M3eNavMenuItemGroupElement_label, "f").id);
1054
+ }
1055
+ else {
1056
+ this.removeAttribute("aria-labelledby");
1057
+ }
1058
+ }
1059
+ };
1060
+ /** The styles of the element. */
1061
+ M3eNavMenuItemGroupElement.styles = css `
1062
+ :host {
1063
+ display: contents;
844
1064
  }
845
- ::slotted(m3e-nav-menu-item:last-of-type) {
846
- margin-block-end: var(--m3e-nav-menu-item-vertical-inset, 0.25rem);
1065
+ ::slotted([slot="label"]) {
1066
+ margin-inline-start: var(--m3e-nav-menu-item-group-label-inset, 1rem);
1067
+ margin-block-end: var(--m3e-nav-menu-item-group-label-space, 1rem);
1068
+ flex: none;
847
1069
  }
848
- @media (prefers-reduced-motion) {
849
- .base,
850
- .toggle,
851
- .state-layer {
852
- transition: none !important;
853
- }
1070
+ :host(.-divided) ::slotted([slot="label"]) {
1071
+ margin-block-start: calc(
1072
+ var(--m3e-nav-menu-item-group-label-space, 1rem) - var(--m3e-nav-menu-divider-margin, 0.25rem)
1073
+ );
854
1074
  }
855
- @media (forced-colors: active) {
856
- .base,
857
- .state-layer {
858
- transition: none !important;
859
- }
860
-
861
- :host(:disabled) .base {
862
- color: GrayText;
863
- }
864
- :host(:not([selected]):not(:disabled)) .base {
865
- color: ButtonText;
866
- }
867
- :host([selected]:not(.-has-items):not(:disabled)) .base {
868
- forced-color-adjust: none;
869
- color: ButtonFace;
870
- background-color: ButtonText;
871
- }
872
- :host([selected].-has-items:not(:disabled)) .base {
873
- background-color: unset;
874
- color: ButtonText;
875
- }
1075
+ :host(:not(.-divided)) ::slotted([slot="label"]) {
1076
+ margin-block-start: var(--m3e-nav-menu-item-group-label-space, 1rem);
876
1077
  }
877
1078
  `;
878
- __decorate([
879
- e$1(".state-layer")
880
- ], M3eNavMenuItemElement.prototype, "stateLayer", void 0);
881
- __decorate([
882
- e$1(".focus-ring")
883
- ], M3eNavMenuItemElement.prototype, "focusRing", void 0);
884
- __decorate([
885
- e$1(".ripple")
886
- ], M3eNavMenuItemElement.prototype, "ripple", void 0);
887
- __decorate([
888
- e$1(".base")
889
- ], M3eNavMenuItemElement.prototype, "_base", void 0);
890
- __decorate([
891
- r$1()
892
- ], M3eNavMenuItemElement.prototype, "_hasChildItems", void 0);
893
- __decorate([
894
- n$1({ type: Boolean, reflect: true })
895
- ], M3eNavMenuItemElement.prototype, "open", void 0);
896
- M3eNavMenuItemElement = M3eNavMenuItemElement_1 = __decorate([
897
- t$2("m3e-nav-menu-item")
898
- ], M3eNavMenuItemElement);
1079
+ /** @private */ M3eNavMenuItemGroupElement.__nextId = 0;
1080
+ M3eNavMenuItemGroupElement = M3eNavMenuItemGroupElement_1 = __decorate([
1081
+ t$2("m3e-nav-menu-item-group")
1082
+ ], M3eNavMenuItemGroupElement);
899
1083
 
900
- export { M3eNavMenuElement, M3eNavMenuItemElement };
1084
+ export { M3eNavMenuElement, M3eNavMenuItemElement, M3eNavMenuItemGroupElement };
901
1085
  //# sourceMappingURL=index.js.map