@m3e/nav-bar 1.0.0-rc.1

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 ADDED
@@ -0,0 +1,630 @@
1
+ /**
2
+ * @license MIT
3
+ * Copyright (c) 2025 matraic
4
+ * See LICENSE file in the project root for full license text.
5
+ */
6
+ import { LitElement, html, css, nothing } from 'lit';
7
+ import { Role, DesignToken, LinkButton, Selected, KeyboardClick, Focusable, DisabledInteractive, Disabled, AttachInternals, renderPseudoLink } from '@m3e/core';
8
+ import { SelectionManager, selectionManager } from '@m3e/core/a11y';
9
+ import { M3eBreakpointObserver, Breakpoint } from '@m3e/core/layout';
10
+
11
+ /******************************************************************************
12
+ Copyright (c) Microsoft Corporation.
13
+
14
+ Permission to use, copy, modify, and/or distribute this software for any
15
+ purpose with or without fee is hereby granted.
16
+
17
+ THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
18
+ REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
19
+ AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
20
+ INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
21
+ LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
22
+ OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
23
+ PERFORMANCE OF THIS SOFTWARE.
24
+ ***************************************************************************** */
25
+ /* global Reflect, Promise, SuppressedError, Symbol, Iterator */
26
+
27
+
28
+ function __decorate(decorators, target, key, desc) {
29
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
30
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
31
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
32
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
33
+ }
34
+
35
+ function __classPrivateFieldGet(receiver, state, kind, f) {
36
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a getter");
37
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot read private member from an object whose class did not declare it");
38
+ return kind === "m" ? f : kind === "a" ? f.call(receiver) : f ? f.value : state.get(receiver);
39
+ }
40
+
41
+ function __classPrivateFieldSet(receiver, state, value, kind, f) {
42
+ if (kind === "m") throw new TypeError("Private method is not writable");
43
+ if (kind === "a" && !f) throw new TypeError("Private accessor was defined without a setter");
44
+ if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
45
+ return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
46
+ }
47
+
48
+ typeof SuppressedError === "function" ? SuppressedError : function (error, suppressed, message) {
49
+ var e = new Error(message);
50
+ return e.name = "SuppressedError", e.error = error, e.suppressed = suppressed, e;
51
+ };
52
+
53
+ /**
54
+ * @license
55
+ * Copyright 2017 Google LLC
56
+ * SPDX-License-Identifier: BSD-3-Clause
57
+ */
58
+ const t$1=t=>(e,o)=>{ void 0!==o?o.addInitializer((()=>{customElements.define(t,e);})):customElements.define(t,e);};
59
+
60
+ /**
61
+ * @license
62
+ * Copyright 2019 Google LLC
63
+ * SPDX-License-Identifier: BSD-3-Clause
64
+ */
65
+ const t=globalThis,e$3=t.ShadowRoot&&(void 0===t.ShadyCSS||t.ShadyCSS.nativeShadow)&&"adoptedStyleSheets"in Document.prototype&&"replace"in CSSStyleSheet.prototype,s=Symbol(),o$2=new WeakMap;let n$2 = class n{constructor(t,e,o){if(this._$cssResult$=true,o!==s)throw Error("CSSResult is not constructable. Use `unsafeCSS` or `css` instead.");this.cssText=t,this.t=e;}get styleSheet(){let t=this.o;const s=this.t;if(e$3&&void 0===t){const e=void 0!==s&&1===s.length;e&&(t=o$2.get(s)),void 0===t&&((this.o=t=new CSSStyleSheet).replaceSync(this.cssText),e&&o$2.set(s,t));}return t}toString(){return this.cssText}};const r$3=t=>new n$2("string"==typeof t?t:t+"",void 0,s),S=(s,o)=>{if(e$3)s.adoptedStyleSheets=o.map((t=>t instanceof CSSStyleSheet?t:t.styleSheet));else for(const e of o){const o=document.createElement("style"),n=t.litNonce;void 0!==n&&o.setAttribute("nonce",n),o.textContent=e.cssText,s.appendChild(o);}},c$1=e$3?t=>t:t=>t instanceof CSSStyleSheet?(t=>{let e="";for(const s of t.cssRules)e+=s.cssText;return r$3(e)})(t):t;
66
+
67
+ /**
68
+ * @license
69
+ * Copyright 2017 Google LLC
70
+ * SPDX-License-Identifier: BSD-3-Clause
71
+ */const{is:i,defineProperty:e$2,getOwnPropertyDescriptor:h,getOwnPropertyNames:r$2,getOwnPropertySymbols:o$1,getPrototypeOf:n$1}=Object,a=globalThis,c=a.trustedTypes,l=c?c.emptyScript:"",p=a.reactiveElementPolyfillSupport,d=(t,s)=>t,u={toAttribute(t,s){switch(s){case Boolean:t=t?l:null;break;case Object:case Array:t=null==t?t:JSON.stringify(t);}return t},fromAttribute(t,s){let i=t;switch(s){case Boolean:i=null!==t;break;case Number:i=null===t?null:Number(t);break;case Object:case Array:try{i=JSON.parse(t);}catch(t){i=null;}}return i}},f=(t,s)=>!i(t,s),b={attribute:true,type:String,converter:u,reflect:false,useDefault:false,hasChanged:f};Symbol.metadata??=Symbol("metadata"),a.litPropertyMetadata??=new WeakMap;class y extends HTMLElement{static addInitializer(t){this._$Ei(),(this.l??=[]).push(t);}static get observedAttributes(){return this.finalize(),this._$Eh&&[...this._$Eh.keys()]}static createProperty(t,s=b){if(s.state&&(s.attribute=false),this._$Ei(),this.prototype.hasOwnProperty(t)&&((s=Object.create(s)).wrapped=true),this.elementProperties.set(t,s),!s.noAccessor){const i=Symbol(),h=this.getPropertyDescriptor(t,i,s);void 0!==h&&e$2(this.prototype,t,h);}}static getPropertyDescriptor(t,s,i){const{get:e,set:r}=h(this.prototype,t)??{get(){return this[s]},set(t){this[s]=t;}};return {get:e,set(s){const h=e?.call(this);r?.call(this,s),this.requestUpdate(t,h,i);},configurable:true,enumerable:true}}static getPropertyOptions(t){return this.elementProperties.get(t)??b}static _$Ei(){if(this.hasOwnProperty(d("elementProperties")))return;const t=n$1(this);t.finalize(),void 0!==t.l&&(this.l=[...t.l]),this.elementProperties=new Map(t.elementProperties);}static finalize(){if(this.hasOwnProperty(d("finalized")))return;if(this.finalized=true,this._$Ei(),this.hasOwnProperty(d("properties"))){const t=this.properties,s=[...r$2(t),...o$1(t)];for(const i of s)this.createProperty(i,t[i]);}const t=this[Symbol.metadata];if(null!==t){const s=litPropertyMetadata.get(t);if(void 0!==s)for(const[t,i]of s)this.elementProperties.set(t,i);}this._$Eh=new Map;for(const[t,s]of this.elementProperties){const i=this._$Eu(t,s);void 0!==i&&this._$Eh.set(i,t);}this.elementStyles=this.finalizeStyles(this.styles);}static finalizeStyles(s){const i=[];if(Array.isArray(s)){const e=new Set(s.flat(1/0).reverse());for(const s of e)i.unshift(c$1(s));}else void 0!==s&&i.push(c$1(s));return i}static _$Eu(t,s){const i=s.attribute;return false===i?void 0:"string"==typeof i?i:"string"==typeof t?t.toLowerCase():void 0}constructor(){super(),this._$Ep=void 0,this.isUpdatePending=false,this.hasUpdated=false,this._$Em=null,this._$Ev();}_$Ev(){this._$ES=new Promise((t=>this.enableUpdating=t)),this._$AL=new Map,this._$E_(),this.requestUpdate(),this.constructor.l?.forEach((t=>t(this)));}addController(t){(this._$EO??=new Set).add(t),void 0!==this.renderRoot&&this.isConnected&&t.hostConnected?.();}removeController(t){this._$EO?.delete(t);}_$E_(){const t=new Map,s=this.constructor.elementProperties;for(const i of s.keys())this.hasOwnProperty(i)&&(t.set(i,this[i]),delete this[i]);t.size>0&&(this._$Ep=t);}createRenderRoot(){const t=this.shadowRoot??this.attachShadow(this.constructor.shadowRootOptions);return S(t,this.constructor.elementStyles),t}connectedCallback(){this.renderRoot??=this.createRenderRoot(),this.enableUpdating(true),this._$EO?.forEach((t=>t.hostConnected?.()));}enableUpdating(t){}disconnectedCallback(){this._$EO?.forEach((t=>t.hostDisconnected?.()));}attributeChangedCallback(t,s,i){this._$AK(t,i);}_$ET(t,s){const i=this.constructor.elementProperties.get(t),e=this.constructor._$Eu(t,i);if(void 0!==e&&true===i.reflect){const h=(void 0!==i.converter?.toAttribute?i.converter:u).toAttribute(s,i.type);this._$Em=t,null==h?this.removeAttribute(e):this.setAttribute(e,h),this._$Em=null;}}_$AK(t,s){const i=this.constructor,e=i._$Eh.get(t);if(void 0!==e&&this._$Em!==e){const t=i.getPropertyOptions(e),h="function"==typeof t.converter?{fromAttribute:t.converter}:void 0!==t.converter?.fromAttribute?t.converter:u;this._$Em=e;const r=h.fromAttribute(s,t.type);this[e]=r??this._$Ej?.get(e)??r,this._$Em=null;}}requestUpdate(t,s,i){if(void 0!==t){const e=this.constructor,h=this[t];if(i??=e.getPropertyOptions(t),!((i.hasChanged??f)(h,s)||i.useDefault&&i.reflect&&h===this._$Ej?.get(t)&&!this.hasAttribute(e._$Eu(t,i))))return;this.C(t,s,i);} false===this.isUpdatePending&&(this._$ES=this._$EP());}C(t,s,{useDefault:i,reflect:e,wrapped:h},r){i&&!(this._$Ej??=new Map).has(t)&&(this._$Ej.set(t,r??s??this[t]),true!==h||void 0!==r)||(this._$AL.has(t)||(this.hasUpdated||i||(s=void 0),this._$AL.set(t,s)),true===e&&this._$Em!==t&&(this._$Eq??=new Set).add(t));}async _$EP(){this.isUpdatePending=true;try{await this._$ES;}catch(t){Promise.reject(t);}const t=this.scheduleUpdate();return null!=t&&await t,!this.isUpdatePending}scheduleUpdate(){return this.performUpdate()}performUpdate(){if(!this.isUpdatePending)return;if(!this.hasUpdated){if(this.renderRoot??=this.createRenderRoot(),this._$Ep){for(const[t,s]of this._$Ep)this[t]=s;this._$Ep=void 0;}const t=this.constructor.elementProperties;if(t.size>0)for(const[s,i]of t){const{wrapped:t}=i,e=this[s];true!==t||this._$AL.has(s)||void 0===e||this.C(s,void 0,i,e);}}let t=false;const s=this._$AL;try{t=this.shouldUpdate(s),t?(this.willUpdate(s),this._$EO?.forEach((t=>t.hostUpdate?.())),this.update(s)):this._$EM();}catch(s){throw t=false,this._$EM(),s}t&&this._$AE(s);}willUpdate(t){}_$AE(t){this._$EO?.forEach((t=>t.hostUpdated?.())),this.hasUpdated||(this.hasUpdated=true,this.firstUpdated(t)),this.updated(t);}_$EM(){this._$AL=new Map,this.isUpdatePending=false;}get updateComplete(){return this.getUpdateComplete()}getUpdateComplete(){return this._$ES}shouldUpdate(t){return true}update(t){this._$Eq&&=this._$Eq.forEach((t=>this._$ET(t,this[t]))),this._$EM();}updated(t){}firstUpdated(t){}}y.elementStyles=[],y.shadowRootOptions={mode:"open"},y[d("elementProperties")]=new Map,y[d("finalized")]=new Map,p?.({ReactiveElement:y}),(a.reactiveElementVersions??=[]).push("2.1.1");
72
+
73
+ /**
74
+ * @license
75
+ * Copyright 2017 Google LLC
76
+ * SPDX-License-Identifier: BSD-3-Clause
77
+ */const o={attribute:true,type:String,converter:u,reflect:false,hasChanged:f},r$1=(t=o,e,r)=>{const{kind:n,metadata:i}=r;let s=globalThis.litPropertyMetadata.get(i);if(void 0===s&&globalThis.litPropertyMetadata.set(i,s=new Map),"setter"===n&&((t=Object.create(t)).wrapped=true),s.set(r.name,t),"accessor"===n){const{name:o}=r;return {set(r){const n=e.get.call(this);e.set.call(this,r),this.requestUpdate(o,n,t);},init(e){return void 0!==e&&this.C(o,void 0,t,e),e}}}if("setter"===n){const{name:o}=r;return function(r){const n=this[o];e.call(this,r),this.requestUpdate(o,n,t);}}throw Error("Unsupported decorator location: "+n)};function n(t){return (e,o)=>"object"==typeof o?r$1(t,e,o):((t,e,o)=>{const r=e.hasOwnProperty(o);return e.constructor.createProperty(o,t),r?Object.getOwnPropertyDescriptor(e,o):void 0})(t,e,o)}
78
+
79
+ /**
80
+ * @license
81
+ * Copyright 2017 Google LLC
82
+ * SPDX-License-Identifier: BSD-3-Clause
83
+ */function r(r){return n({...r,state:true,attribute:false})}
84
+
85
+ /**
86
+ * @license
87
+ * Copyright 2017 Google LLC
88
+ * SPDX-License-Identifier: BSD-3-Clause
89
+ */
90
+ const e$1=(e,t,c)=>(c.configurable=true,c.enumerable=true,Reflect.decorate&&"object"!=typeof t&&Object.defineProperty(e,t,c),c);
91
+
92
+ /**
93
+ * @license
94
+ * Copyright 2017 Google LLC
95
+ * SPDX-License-Identifier: BSD-3-Clause
96
+ */function e(e,r){return (n,s,i)=>{const o=t=>t.renderRoot?.querySelector(e)??null;return e$1(n,s,{get(){return o(this)}})}}
97
+
98
+ var _M3eNavBarElement_instances, _M3eNavBarElement_breakpointUnobserve, _M3eNavBarElement_handleSlotChange, _M3eNavBarElement_handleChange, _a;
99
+ /**
100
+ * @summary
101
+ * A horizontal bar, typically used on smaller devices, that allows a user to switch between 3-5 views.
102
+ *
103
+ * @description
104
+ * The `m3e-nav-bar` component provides a horizontal navigation bar for switching between primary destinations in
105
+ * an application. Designed for smaller devices, it supports 3-5 interactive items, orientation, and theming
106
+ * via CSS custom properties.
107
+ *
108
+ * @example
109
+ * The following example illustrates a nav bar with vertically oriented items.
110
+ * ```html
111
+ * <m3e-nav-bar>
112
+ * <m3e-nav-item><m3e-icon slot="icon" name="news"></m3e-icon>News</m3e-nav-item>
113
+ * <m3e-nav-item><m3e-icon slot="icon" name="globe"></m3e-icon>Global</m3e-nav-item>
114
+ * <m3e-nav-item><m3e-icon slot="icon" name="star"></m3e-icon>For you</m3e-nav-item>
115
+ * <m3e-nav-item><m3e-icon slot="icon" name="newsstand"></m3e-icon>Trending</m3e-nav-item>
116
+ * </m3e-nav-bar>
117
+ * ```
118
+ *
119
+ * @tag m3e-nav-bar
120
+ *
121
+ * @slot - Renders the items of the bar.
122
+ *
123
+ * @attr mode - The mode in which items in the bar are presented.
124
+ *
125
+ * @fires change - Emitted when the selected state of an item changes.
126
+ *
127
+ * @cssprop --m3e-nav-bar-height - Height of the navigation bar.
128
+ * @cssprop --m3e-nav-bar-container-color - Background color of the navigation bar container.
129
+ * @cssprop --m3e-nav-bar-vertical-item-width - Minimum width of vertical nav items.
130
+ */
131
+ let M3eNavBarElement = class M3eNavBarElement extends Role(LitElement, "navigation") {
132
+ constructor() {
133
+ super(...arguments);
134
+ _M3eNavBarElement_instances.add(this);
135
+ /** @internal */ this[_a] = new SelectionManager().disableRovingTabIndex();
136
+ /** @internal */ _M3eNavBarElement_breakpointUnobserve.set(this, void 0);
137
+ /**
138
+ * The mode in which items in the bar are presented.
139
+ * @default "compact"
140
+ */
141
+ this.mode = "compact";
142
+ }
143
+ /** The items of the bar. */
144
+ get items() {
145
+ return this[selectionManager].items;
146
+ }
147
+ /** The selected item. */
148
+ get selected() {
149
+ return this[selectionManager].selectedItems[0] ?? null;
150
+ }
151
+ /** The current mode applied to the bar. */
152
+ get currentMode() {
153
+ return this._mode ?? (this.mode !== "compact" ? "expanded" : "compact");
154
+ }
155
+ set currentMode(value) {
156
+ this._mode = value;
157
+ }
158
+ /** @inheritdoc */
159
+ disconnectedCallback() {
160
+ super.disconnectedCallback();
161
+ this._mode = undefined;
162
+ __classPrivateFieldGet(this, _M3eNavBarElement_breakpointUnobserve, "f")?.call(this);
163
+ }
164
+ /** @inheritdoc */
165
+ update(changedProperties) {
166
+ super.update(changedProperties);
167
+ if (changedProperties.has("mode")) {
168
+ __classPrivateFieldGet(this, _M3eNavBarElement_breakpointUnobserve, "f")?.call(this);
169
+ if (this.mode === "auto") {
170
+ __classPrivateFieldSet(this, _M3eNavBarElement_breakpointUnobserve, M3eBreakpointObserver.observe([Breakpoint.XSmall, Breakpoint.Small], (matches) => {
171
+ this._mode = matches.get(Breakpoint.XSmall) || matches.get(Breakpoint.Small) ? "compact" : "expanded";
172
+ this._updateItems();
173
+ }), "f");
174
+ }
175
+ else {
176
+ this._updateItems();
177
+ }
178
+ }
179
+ if (changedProperties.has("_mode")) {
180
+ this._updateItems();
181
+ }
182
+ }
183
+ /** @inheritdoc */
184
+ render() {
185
+ return html `<slot @change="${__classPrivateFieldGet(this, _M3eNavBarElement_instances, "m", _M3eNavBarElement_handleChange)}" @slotchange="${__classPrivateFieldGet(this, _M3eNavBarElement_instances, "m", _M3eNavBarElement_handleSlotChange)}"></slot>`;
186
+ }
187
+ /** @internal */
188
+ _updateItems() {
189
+ const orientation = this.currentMode === "compact" ? "vertical" : "horizontal";
190
+ this._updateOrientation(orientation);
191
+ this.classList.toggle("-compact", orientation === "vertical");
192
+ }
193
+ /** @internal */
194
+ _updateOrientation(orientation) {
195
+ this[selectionManager].items.forEach((x) => (x.orientation = orientation));
196
+ }
197
+ };
198
+ _M3eNavBarElement_breakpointUnobserve = new WeakMap();
199
+ _M3eNavBarElement_instances = new WeakSet();
200
+ _a = selectionManager;
201
+ _M3eNavBarElement_handleSlotChange = function _M3eNavBarElement_handleSlotChange() {
202
+ this[selectionManager].setItems([...this.querySelectorAll("m3e-nav-item")]);
203
+ this._updateItems();
204
+ };
205
+ _M3eNavBarElement_handleChange = function _M3eNavBarElement_handleChange(e) {
206
+ e.stopPropagation();
207
+ this.dispatchEvent(new Event("change", { bubbles: true }));
208
+ };
209
+ /** The styles of the element. */
210
+ M3eNavBarElement.styles = css `
211
+ :host {
212
+ display: flex;
213
+ overflow-x: auto;
214
+ align-items: stretch;
215
+ scrollbar-width: ${DesignToken.scrollbar.thinWidth};
216
+ scrollbar-color: ${DesignToken.scrollbar.color};
217
+ min-height: var(--m3e-nav-bar-height, 4rem);
218
+ background-color: var(--m3e-nav-bar-container-color, ${DesignToken.color.surfaceContainer});
219
+ justify-content: center;
220
+ --_nav-item-min-width: var(--m3e-nav-bar-vertical-item-width, 7rem);
221
+ }
222
+ `;
223
+ __decorate([
224
+ r()
225
+ ], M3eNavBarElement.prototype, "_mode", void 0);
226
+ __decorate([
227
+ n({ reflect: true })
228
+ ], M3eNavBarElement.prototype, "mode", void 0);
229
+ M3eNavBarElement = __decorate([
230
+ t$1("m3e-nav-bar")
231
+ ], M3eNavBarElement);
232
+
233
+ var _M3eNavItemElement_instances, _M3eNavItemElement_clickHandler, _M3eNavItemElement_handleClick;
234
+ /**
235
+ * @summary
236
+ * An item, placed in a navigation bar or rail, used to navigate to destinations in an application.
237
+ *
238
+ * @description
239
+ * The `m3e-nav-item` component represents an interactive navigation item for use in navigation bars
240
+ * or rails. Designed according to Material 3 principles, it supports icon and label slots, selection state,
241
+ * orientation, and extensive theming via CSS custom properties.
242
+ *
243
+ * @example
244
+ * The following example illustrates a nav bar with vertically oriented items.
245
+ * ```html
246
+ * <m3e-nav-bar>
247
+ * <m3e-nav-item><m3e-icon slot="icon" name="news"></m3e-icon>News</m3e-nav-item>
248
+ * <m3e-nav-item><m3e-icon slot="icon" name="globe"></m3e-icon>Global</m3e-nav-item>
249
+ * <m3e-nav-item><m3e-icon slot="icon" name="star"></m3e-icon>For you</m3e-nav-item>
250
+ * <m3e-nav-item><m3e-icon slot="icon" name="newsstand"></m3e-icon>Trending</m3e-nav-item>
251
+ * </m3e-nav-bar>
252
+ * ```
253
+ *
254
+ * @tag m3e-nav-item
255
+ *
256
+ * @slot - Renders the label of the item.
257
+ * @slot icon - Renders the icon of the item.
258
+ * @slot selected-icon - Renders the icon of the item when selected.
259
+ *
260
+ * @attr disabled - A value indicating whether the element is disabled.
261
+ * @attr disabled-interactive - A value indicating whether the element is disabled and interactive.
262
+ * @attr download - A value indicating whether the `target` of the link button will be downloaded, optionally specifying the new name of the file.
263
+ * @attr href - The URL to which the link button points.
264
+ * @attr orientation - The layout orientation of the item.
265
+ * @attr rel - The relationship between the `target` of the link button and the document.
266
+ * @attr selected - A value indicating whether the element is selected.
267
+ * @attr target - The target of the link button.
268
+ *
269
+ * @fires input - Emitted when the selected state changes.
270
+ * @fires change - Emitted when the selected state changes.
271
+ *
272
+ * @cssprop --m3e-nav-item-label-text-font-size - Font size for the label text.
273
+ * @cssprop --m3e-nav-item-label-text-font-weight - Font weight for the label text.
274
+ * @cssprop --m3e-nav-item-label-text-line-height - Line height for the label text.
275
+ * @cssprop --m3e-nav-item-label-text-tracking - Letter spacing for the label text.
276
+ * @cssprop --m3e-nav-item-shape - Border radius of the nav item.
277
+ * @cssprop --m3e-nav-item-icon-size - Size of the icon.
278
+ * @cssprop --m3e-nav-item-spacing - Spacing between icon and label.
279
+ * @cssprop --m3e-nav-item-inactive-label-text-color - Color of the label text when inactive.
280
+ * @cssprop --m3e-nav-item-inactive-icon-color - Color of the icon when inactive.
281
+ * @cssprop --m3e-nav-item-inactive-hover-state-layer-color - State layer color on hover when inactive.
282
+ * @cssprop --m3e-nav-item-inactive-focus-state-layer-color - State layer color on focus when inactive.
283
+ * @cssprop --m3e-nav-item-inactive-pressed-state-layer-color - State layer color on press when inactive.
284
+ * @cssprop --m3e-nav-item-active-label-text-color - Color of the label text when active/selected.
285
+ * @cssprop --m3e-nav-item-active-icon-color - Color of the icon when active/selected.
286
+ * @cssprop --m3e-nav-item-active-container-color - Container color when active/selected.
287
+ * @cssprop --m3e-nav-item-active-hover-state-layer-color - State layer color on hover when active.
288
+ * @cssprop --m3e-nav-item-active-focus-state-layer-color - State layer color on focus when active.
289
+ * @cssprop --m3e-nav-item-active-pressed-state-layer-color - State layer color on press when active.
290
+ * @cssprop --m3e-nav-item-focus-ring-shape - Border radius for the focus ring.
291
+ * @cssprop --m3e-nav-item-disabled-label-text-color - Color of the label text when disabled.
292
+ * @cssprop --m3e-nav-item-disabled-label-text-opacity - Opacity of the label text when disabled.
293
+ * @cssprop --m3e-nav-item-disabled-icon-color - Color of the icon when disabled.
294
+ * @cssprop --m3e-nav-item-disabled-icon-opacity - Opacity of the icon when disabled.
295
+ * @cssprop --m3e-horizontal-nav-item-padding - Padding for horizontal orientation.
296
+ * @cssprop --m3e-horizontal-nav-item-active-indicator-height - Height of the active indicator in horizontal orientation.
297
+ * @cssprop --m3e-vertical-nav-item-active-indicator-width - Width of the active indicator in vertical orientation.
298
+ * @cssprop --m3e-vertical-nav-item-active-indicator-height - Height of the active indicator in vertical orientation.
299
+ * @cssprop --m3e-vertical-nav-item-active-indicator-margin - Margin for the active indicator in vertical orientation.
300
+ */
301
+ let M3eNavItemElement = class M3eNavItemElement extends LinkButton(Selected(KeyboardClick(Focusable(DisabledInteractive(Disabled(AttachInternals(Role(LitElement, "button"), true))))))) {
302
+ constructor() {
303
+ super(...arguments);
304
+ _M3eNavItemElement_instances.add(this);
305
+ /** @private */ _M3eNavItemElement_clickHandler.set(this, (e) => __classPrivateFieldGet(this, _M3eNavItemElement_instances, "m", _M3eNavItemElement_handleClick).call(this, e));
306
+ /**
307
+ * The layout orientation of the item.
308
+ * @default "vertical"
309
+ */
310
+ this.orientation = "vertical";
311
+ }
312
+ /** The navigation bar to which this item belongs. */
313
+ get navBar() {
314
+ return this.closest("m3e-nav-bar") ?? this.closest("m3e-nav-rail") ?? null;
315
+ }
316
+ /** @inheritdoc */
317
+ connectedCallback() {
318
+ super.connectedCallback();
319
+ this.addEventListener("click", __classPrivateFieldGet(this, _M3eNavItemElement_clickHandler, "f"));
320
+ }
321
+ /** @inheritdoc */
322
+ disconnectedCallback() {
323
+ super.disconnectedCallback();
324
+ this.removeEventListener("click", __classPrivateFieldGet(this, _M3eNavItemElement_clickHandler, "f"));
325
+ }
326
+ /** @inheritdoc */
327
+ update(changedProperties) {
328
+ super.update(changedProperties);
329
+ if (changedProperties.has("selected")) {
330
+ this.ariaSelected = null;
331
+ this.ariaPressed = null;
332
+ this.ariaCurrent = `${this.selected}`;
333
+ for (const icon of this.querySelectorAll("m3e-icon")) {
334
+ icon.toggleAttribute("filled", this.selected);
335
+ }
336
+ this.navBar?.[selectionManager].notifySelectionChange(this);
337
+ }
338
+ }
339
+ /** @inheritdoc */
340
+ updated(_changedProperties) {
341
+ super.updated(_changedProperties);
342
+ if (_changedProperties.has("orientation")) {
343
+ this._focusRing?.attach(this);
344
+ }
345
+ }
346
+ /** @inheritdoc */
347
+ firstUpdated(_changedProperties) {
348
+ super.firstUpdated(_changedProperties);
349
+ [this._focusRing, this._stateLayer, this._ripple].forEach((x) => x?.attach(this));
350
+ }
351
+ /** @inheritdoc */
352
+ render() {
353
+ const disabled = this.disabled || this.disabledInteractive;
354
+ return html `${this.orientation === "vertical"
355
+ ? html `<m3e-focus-ring class="focus-ring" inward></m3e-focus-ring>`
356
+ : nothing}
357
+ <div class="outer">
358
+ ${this[renderPseudoLink]()}
359
+ <div class="inner">
360
+ ${this.orientation === "horizontal" ? html `<m3e-focus-ring class="focus-ring"></m3e-focus-ring>` : nothing}
361
+ <m3e-state-layer class="state-layer" ?disabled="${disabled}"></m3e-state-layer>
362
+ <m3e-ripple class="ripple" centered ?disabled="${disabled}"></m3e-ripple>
363
+ <div class="touch" aria-hidden="true"></div>
364
+ <div class="base">
365
+ <div class="icon-wrapper" aria-hidden="true">
366
+ <div class="icon">
367
+ <slot name="icon" aria-hidden="true"></slot>
368
+ </div>
369
+ </div>
370
+ <div class="label">
371
+ <slot></slot>
372
+ </div>
373
+ </div>
374
+ </div>
375
+ </div>`;
376
+ }
377
+ };
378
+ _M3eNavItemElement_clickHandler = new WeakMap();
379
+ _M3eNavItemElement_instances = new WeakSet();
380
+ _M3eNavItemElement_handleClick = function _M3eNavItemElement_handleClick(e) {
381
+ if (e.defaultPrevented)
382
+ return;
383
+ this.selected = true;
384
+ if (this.dispatchEvent(new Event("input", { bubbles: true, composed: true, cancelable: true }))) {
385
+ this.navBar?.[selectionManager].notifySelectionChange(this);
386
+ this.dispatchEvent(new Event("change", { bubbles: true }));
387
+ }
388
+ else {
389
+ this.selected = false;
390
+ }
391
+ };
392
+ /** The styles of the element. */
393
+ M3eNavItemElement.styles = css `
394
+ :host {
395
+ display: inline-block;
396
+ vertical-align: middle;
397
+ position: relative;
398
+ outline: none;
399
+ user-select: none;
400
+ flex: 1;
401
+ font-size: var(--m3e-nav-item-label-text-font-size, ${DesignToken.typescale.standard.label.medium.fontSize});
402
+ font-weight: var(
403
+ --m3e-nav-item-label-text-font-weight,
404
+ ${DesignToken.typescale.standard.label.medium.fontWeight}
405
+ );
406
+ line-height: var(
407
+ --m3e-nav-item-label-text-line-height,
408
+ ${DesignToken.typescale.standard.label.medium.lineHeight}
409
+ );
410
+ letter-spacing: var(--m3e-nav-item-label-text-tracking, ${DesignToken.typescale.standard.label.medium.tracking});
411
+ border-radius: var(--m3e-nav-item-shape, ${DesignToken.shape.corner.full});
412
+ min-width: var(--_nav-item-min-width);
413
+ align-self: var(--_nav-item-align-self);
414
+ }
415
+ :host([orientation="horizontal"]) {
416
+ max-width: fit-content;
417
+ }
418
+ :host(:not(:disabled):not([disabled-interactive])) {
419
+ cursor: pointer;
420
+ }
421
+ :host([disabled-interactive]) {
422
+ cursor: not-allowed;
423
+ }
424
+ .outer {
425
+ height: 100%;
426
+ }
427
+ .outer,
428
+ .inner {
429
+ display: flex;
430
+ align-items: center;
431
+ justify-content: var(--_nav-item-justify-content, center);
432
+ position: relative;
433
+ border-radius: inherit;
434
+ }
435
+ .icon-wrapper {
436
+ position: relative;
437
+ flex: none;
438
+ }
439
+ .base {
440
+ justify-content: unset;
441
+ box-sizing: border-box;
442
+ vertical-align: middle;
443
+ display: inline-flex;
444
+ align-items: center;
445
+ justify-content: center;
446
+ position: relative;
447
+ width: 100%;
448
+ }
449
+ .icon {
450
+ position: absolute;
451
+ }
452
+ .label {
453
+ vertical-align: middle;
454
+ }
455
+ ::slotted([slot="icon"]),
456
+ ::slotted([slot="selected-icon"]) {
457
+ width: 1em;
458
+ font-size: var(--m3e-nav-item-icon-size, 1.5rem) !important;
459
+ }
460
+ :host(:not([selected]):not(:disabled):not([disabled-interactive])) .outer {
461
+ --m3e-state-layer-hover-color: var(
462
+ --m3e-nav-item-inactive-hover-state-layer-color,
463
+ ${DesignToken.color.onSecondaryContainer}
464
+ );
465
+ --m3e-state-layer-focus-color: var(
466
+ --m3e-nav-item-inactive-focus-state-layer-color,
467
+ ${DesignToken.color.onSecondaryContainer}
468
+ );
469
+ --m3e-ripple-color: var(
470
+ --m3e-nav-item-inactive-pressed-state-layer-color,
471
+ ${DesignToken.color.onSecondaryContainer}
472
+ );
473
+ }
474
+ :host(:not([selected]):not(:disabled):not([disabled-interactive])) .label {
475
+ color: var(--m3e-nav-item-inactive-label-text-color, ${DesignToken.color.onSurfaceVariant});
476
+ }
477
+ :host(:not([selected]):not(:disabled):not([disabled-interactive])) .icon {
478
+ color: var(--m3e-nav-item-inactive-icon-color, ${DesignToken.color.onSecondaryContainer});
479
+ }
480
+ :host([selected]:not(:disabled):not([disabled-interactive])) .outer {
481
+ --m3e-state-layer-hover-color: var(
482
+ --m3e-nav-item-active-hover-state-layer-color,
483
+ ${DesignToken.color.onSecondaryContainer}
484
+ );
485
+ --m3e-state-layer-focus-color: var(
486
+ --m3e-nav-item-active-focus-state-layer-color,
487
+ ${DesignToken.color.onSecondaryContainer}
488
+ );
489
+ --m3e-ripple-color: var(
490
+ --m3e-nav-item-active-pressed-state-layer-color,
491
+ ${DesignToken.color.onSecondaryContainer}
492
+ );
493
+ }
494
+ :host([selected]:not(:disabled):not([disabled-interactive])) .label {
495
+ color: var(--m3e-nav-item-active-label-text-color, ${DesignToken.color.secondary});
496
+ }
497
+ :host([selected]:not(:disabled):not([disabled-interactive])) .state-layer {
498
+ background-color: var(--m3e-nav-item-active-container-color, ${DesignToken.color.secondaryContainer});
499
+ }
500
+ :host([selected]:not(:disabled):not([disabled-interactive])) .icon {
501
+ color: var(--m3e-nav-item-active-icon-color, ${DesignToken.color.onSecondaryContainer});
502
+ }
503
+ :host([orientation="vertical"]) .outer {
504
+ align-self: stretch;
505
+ align-items: flex-start;
506
+ }
507
+ :host([orientation="vertical"]) .label {
508
+ text-align: center;
509
+ display: -webkit-box;
510
+ -webkit-line-clamp: 2;
511
+ -webkit-box-orient: vertical;
512
+ overflow: hidden;
513
+ line-clamp: 2;
514
+ }
515
+ :host([orientation="vertical"]) .base {
516
+ flex-direction: column;
517
+ row-gap: var(--m3e-nav-item-spacing, 0.25rem);
518
+ }
519
+ :host([orientation="vertical"]) .base {
520
+ margin-block: var(--m3e-vertical-nav-item-active-indicator-margin, 0.375rem);
521
+ }
522
+ :host([orientation="vertical"]) .state-layer,
523
+ :host([orientation="vertical"]) .ripple {
524
+ top: var(--m3e-vertical-nav-item-active-indicator-margin, 0.375rem);
525
+ bottom: unset;
526
+ }
527
+ :host([orientation="vertical"]) .state-layer,
528
+ :host([orientation="vertical"]) .ripple,
529
+ :host([orientation="vertical"]) .icon-wrapper {
530
+ width: var(--m3e-vertical-nav-item-active-indicator-width, 3.5rem);
531
+ }
532
+ :host([orientation="vertical"]) .state-layer,
533
+ :host([orientation="vertical"]) .ripple,
534
+ :host([orientation="vertical"]) .icon-wrapper {
535
+ height: var(--m3e-vertical-nav-item-active-indicator-height, 2rem);
536
+ }
537
+ :host([orientation="vertical"]) .icon {
538
+ top: calc(
539
+ calc(var(--m3e-vertical-nav-item-active-indicator-height, 2rem) / 2) -
540
+ calc(var(--m3e-nav-item-icon-size, 1.5rem) / 2)
541
+ );
542
+ left: calc(
543
+ calc(var(--m3e-vertical-nav-item-active-indicator-width, 3.5rem) / 2) -
544
+ calc(var(--m3e-nav-item-icon-size, 1.5rem) / 2)
545
+ );
546
+ }
547
+ :host([orientation="vertical"]) .focus-ring {
548
+ border-radius: var(--m3e-nav-item-focus-ring-shape, ${DesignToken.shape.corner.extraSmall});
549
+ }
550
+ :host([orientation="horizontal"]) .icon-wrapper {
551
+ width: var(--m3e-nav-item-icon-size, 1.5rem);
552
+ height: var(--m3e-nav-item-icon-size, 1.5rem);
553
+ }
554
+ :host([orientation="horizontal"]) .base {
555
+ padding: var(--m3e-horizontal-nav-item-padding, 1rem);
556
+ }
557
+ :host([orientation="horizontal"]) .label {
558
+ flex: 1 1 auto;
559
+ }
560
+ :host([orientation="horizontal"]) .base {
561
+ column-gap: var(--m3e-nav-item-spacing, 0.25rem);
562
+ }
563
+ :host([orientation="horizontal"]) .inner {
564
+ height: var(--m3e-horizontal-nav-item-active-indicator-height, 2.5rem);
565
+ width: fit-content;
566
+ }
567
+ .state-layer,
568
+ .ripple {
569
+ margin-inline: auto;
570
+ }
571
+ :host(:disabled) .label,
572
+ :host([disabled-interactive]) .label {
573
+ color: color-mix(
574
+ in srgb,
575
+ var(--m3e-nav-item-disabled-label-text-color, ${DesignToken.color.onSurface})
576
+ var(--m3e-nav-item-disabled-label-text-opacity, 38%),
577
+ transparent
578
+ );
579
+ }
580
+ :host(:disabled) .icon,
581
+ :host([disabled-interactive]) .icon {
582
+ color: color-mix(
583
+ in srgb,
584
+ var(--m3e-nav-item-disabled-icon-color, ${DesignToken.color.onSurface})
585
+ var(--m3e-nav-item-disabled-icon-opacity, 38%),
586
+ transparent
587
+ );
588
+ }
589
+ @media (forced-colors: active) {
590
+ :host(:disabled) .label,
591
+ :host([disabled-interactive]) .label,
592
+ :host(:disabled) .icon,
593
+ :host([disabled-interactive]) .icon {
594
+ color: GrayText;
595
+ }
596
+ :host(:not([selected]):not(:disabled):not([disabled-interactive])) .label,
597
+ :host(:not([selected]):not(:disabled):not([disabled-interactive])) .icon {
598
+ color: ButtonText;
599
+ }
600
+ :host([selected]:not(:disabled):not([disabled-interactive])) .state-layer {
601
+ background-color: ButtonText;
602
+ }
603
+ :host([orientation="vertical"][selected]:not(:disabled):not([disabled-interactive])) .label {
604
+ color: ButtonText;
605
+ }
606
+ :host([orientation="horizontal"][selected]:not(:disabled):not([disabled-interactive])) .label,
607
+ :host([selected]:not(:disabled):not([disabled-interactive])) .icon {
608
+ forced-color-adjust: none;
609
+ color: ButtonFace;
610
+ }
611
+ }
612
+ `;
613
+ __decorate([
614
+ e(".focus-ring")
615
+ ], M3eNavItemElement.prototype, "_focusRing", void 0);
616
+ __decorate([
617
+ e(".state-layer")
618
+ ], M3eNavItemElement.prototype, "_stateLayer", void 0);
619
+ __decorate([
620
+ e(".ripple")
621
+ ], M3eNavItemElement.prototype, "_ripple", void 0);
622
+ __decorate([
623
+ n({ reflect: true })
624
+ ], M3eNavItemElement.prototype, "orientation", void 0);
625
+ M3eNavItemElement = __decorate([
626
+ t$1("m3e-nav-item")
627
+ ], M3eNavItemElement);
628
+
629
+ export { M3eNavBarElement, M3eNavItemElement };
630
+ //# sourceMappingURL=index.js.map