@lit-material/navigation 0.0.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.
Files changed (39) hide show
  1. package/LICENSE +21 -0
  2. package/README.md +127 -0
  3. package/dist/index.d.ts +7 -0
  4. package/dist/index.d.ts.map +1 -0
  5. package/dist/index.js +5 -0
  6. package/dist/index.js.map +1 -0
  7. package/dist/navigation-drawer-item-styles.d.ts +2 -0
  8. package/dist/navigation-drawer-item-styles.d.ts.map +1 -0
  9. package/dist/navigation-drawer-item-styles.js +108 -0
  10. package/dist/navigation-drawer-item-styles.js.map +1 -0
  11. package/dist/navigation-drawer-item.d.ts +44 -0
  12. package/dist/navigation-drawer-item.d.ts.map +1 -0
  13. package/dist/navigation-drawer-item.js +124 -0
  14. package/dist/navigation-drawer-item.js.map +1 -0
  15. package/dist/navigation-drawer-styles.d.ts +2 -0
  16. package/dist/navigation-drawer-styles.d.ts.map +1 -0
  17. package/dist/navigation-drawer-styles.js +75 -0
  18. package/dist/navigation-drawer-styles.js.map +1 -0
  19. package/dist/navigation-drawer.d.ts +68 -0
  20. package/dist/navigation-drawer.d.ts.map +1 -0
  21. package/dist/navigation-drawer.js +187 -0
  22. package/dist/navigation-drawer.js.map +1 -0
  23. package/dist/navigation-rail-item-styles.d.ts +2 -0
  24. package/dist/navigation-rail-item-styles.d.ts.map +1 -0
  25. package/dist/navigation-rail-item-styles.js +122 -0
  26. package/dist/navigation-rail-item-styles.js.map +1 -0
  27. package/dist/navigation-rail-item.d.ts +46 -0
  28. package/dist/navigation-rail-item.d.ts.map +1 -0
  29. package/dist/navigation-rail-item.js +128 -0
  30. package/dist/navigation-rail-item.js.map +1 -0
  31. package/dist/navigation-rail-styles.d.ts +2 -0
  32. package/dist/navigation-rail-styles.d.ts.map +1 -0
  33. package/dist/navigation-rail-styles.js +51 -0
  34. package/dist/navigation-rail-styles.js.map +1 -0
  35. package/dist/navigation-rail.d.ts +44 -0
  36. package/dist/navigation-rail.d.ts.map +1 -0
  37. package/dist/navigation-rail.js +93 -0
  38. package/dist/navigation-rail.js.map +1 -0
  39. package/package.json +62 -0
@@ -0,0 +1,187 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ 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;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { html, LitElement, nothing } from "lit";
8
+ import { customElement, property, query } from "lit/decorators.js";
9
+ import { styles } from "./navigation-drawer-styles.js";
10
+ /**
11
+ * Material Design 3 navigation drawer — a vertical panel of primary
12
+ * destinations (`lit-material-navigation-drawer-item` elements).
13
+ *
14
+ * `standard` renders as a plain, always-in-flow `<nav>` (a persistent side
15
+ * panel you place in your own layout). `modal` wraps the same content in a
16
+ * native `<dialog>`, the same foundation `lit-material-dialog` uses — so the
17
+ * scrim, Escape-to-close, and focus trap all come from the browser. `position`
18
+ * picks which edge a `modal` drawer slides in from.
19
+ *
20
+ * Selection is index-based and managed here (like `lit-material-tabs`): set
21
+ * `selected` to reflect your current route/section, and each item's own
22
+ * `selected` is kept in sync automatically. Clicking an item updates
23
+ * `selected` and fires `change` — items themselves don't manage selection.
24
+ *
25
+ * @element lit-material-navigation-drawer
26
+ *
27
+ * @slot - `lit-material-navigation-drawer-item` elements.
28
+ * @slot header - Optional header content (a title, a close button…).
29
+ *
30
+ * @csspart dialog - The native `<dialog>` element. Only rendered for `modal`.
31
+ * @csspart drawer - The visible panel (background, width, padding).
32
+ * @csspart header - The header slot's container.
33
+ * @csspart content - The items slot's container.
34
+ *
35
+ * @fires change - Fires when `selected` changes via an item click.
36
+ * @fires cancel - `modal` only: re-dispatched from the native `cancel` event.
37
+ * Cancelable: calling `preventDefault()` stops the drawer from closing.
38
+ * @fires close - `modal` only: re-dispatched from the native `close` event.
39
+ */
40
+ let LitMaterialNavigationDrawer = class LitMaterialNavigationDrawer extends LitElement {
41
+ static { this.styles = styles; }
42
+ constructor() {
43
+ super();
44
+ this.variant = "standard";
45
+ this.position = "start";
46
+ /** Index of the selected item. `-1` means no selection. */
47
+ this.selected = -1;
48
+ /** Whether a `modal` drawer is open. Ignored for `standard`. */
49
+ this.open = false;
50
+ /** If set, clicking the backdrop does not close a `modal` drawer. */
51
+ this.disableBackdropClose = false;
52
+ this.reopenOnClose = false;
53
+ this.handleSlotChange = () => this.syncSelected();
54
+ this.handleClick = (event) => {
55
+ const path = event.composedPath();
56
+ const items = this.items;
57
+ const item = items.find((candidate) => path.includes(candidate));
58
+ if (!item || item.disabled)
59
+ return;
60
+ const index = items.indexOf(item);
61
+ const isChange = index !== this.selected;
62
+ this.selected = index;
63
+ if (isChange)
64
+ this.dispatchEvent(new Event("change", { bubbles: true }));
65
+ };
66
+ this.addEventListener("click", this.handleClick);
67
+ }
68
+ connectedCallback() {
69
+ super.connectedCallback();
70
+ this.syncSelected();
71
+ }
72
+ updated(changed) {
73
+ if (changed.has("selected"))
74
+ this.syncSelected();
75
+ if (changed.has("open") && this.variant === "modal" && this.dialogElement) {
76
+ if (this.open && !this.dialogElement.open) {
77
+ this.dialogElement.showModal();
78
+ }
79
+ else if (!this.open && this.dialogElement.open) {
80
+ this.dialogElement.close();
81
+ }
82
+ }
83
+ }
84
+ /** Opens a `modal` drawer. Equivalent to setting `.open = true`. */
85
+ show() {
86
+ this.open = true;
87
+ }
88
+ /** Closes a `modal` drawer. Equivalent to setting `.open = false`. */
89
+ close() {
90
+ this.open = false;
91
+ }
92
+ get items() {
93
+ // @lit-labs/ssr's light-DOM shim doesn't implement querySelectorAll on
94
+ // the host during connectedCallback — degrade to no items rather than
95
+ // throwing.
96
+ if (typeof this.querySelectorAll !== "function")
97
+ return [];
98
+ return Array.from(this.querySelectorAll("lit-material-navigation-drawer-item"));
99
+ }
100
+ syncSelected() {
101
+ this.items.forEach((item, index) => {
102
+ item.selected = index === this.selected;
103
+ });
104
+ }
105
+ renderNav() {
106
+ // For `modal`, showModal() auto-focuses the first focusable descendant
107
+ // when nothing has autofocus — without this, that's the first item's
108
+ // button, showing its focus ring on every open even though the user
109
+ // never interacted with it (same fix as lit-material-dialog's
110
+ // `container`). Harmless to skip for `standard`, since it's never the
111
+ // target of showModal() in the first place.
112
+ const isModal = this.variant === "modal";
113
+ return html `
114
+ <nav
115
+ class="drawer ${this.variant}"
116
+ part="drawer"
117
+ tabindex=${isModal ? "-1" : nothing}
118
+ ?autofocus=${isModal}
119
+ >
120
+ <div class="header" part="header"><slot name="header"></slot></div>
121
+ <div class="content" part="content"><slot @slotchange=${this.handleSlotChange}></slot></div>
122
+ </nav>
123
+ `;
124
+ }
125
+ render() {
126
+ if (this.variant !== "modal")
127
+ return this.renderNav();
128
+ return html `
129
+ <dialog
130
+ class="dialog"
131
+ part="dialog"
132
+ @close=${this.handleClose}
133
+ @cancel=${this.handleCancel}
134
+ @click=${this.handleBackdropClick}
135
+ >
136
+ ${this.renderNav()}
137
+ </dialog>
138
+ `;
139
+ }
140
+ handleClose() {
141
+ if (this.reopenOnClose) {
142
+ // Some browsers don't honor preventDefault() on the native `cancel`
143
+ // event despite documenting it as cancelable — see lit-material-dialog
144
+ // for the same workaround.
145
+ this.reopenOnClose = false;
146
+ this.dialogElement?.showModal();
147
+ return;
148
+ }
149
+ this.open = false;
150
+ this.dispatchEvent(new Event("close", { bubbles: true, composed: true }));
151
+ }
152
+ handleCancel(event) {
153
+ const proceed = this.dispatchEvent(new Event("cancel", { bubbles: true, cancelable: true, composed: true }));
154
+ if (!proceed) {
155
+ event.preventDefault();
156
+ this.reopenOnClose = true;
157
+ }
158
+ }
159
+ handleBackdropClick(event) {
160
+ if (!this.disableBackdropClose && event.target === this.dialogElement) {
161
+ this.dialogElement?.close();
162
+ }
163
+ }
164
+ };
165
+ __decorate([
166
+ property()
167
+ ], LitMaterialNavigationDrawer.prototype, "variant", void 0);
168
+ __decorate([
169
+ property({ reflect: true })
170
+ ], LitMaterialNavigationDrawer.prototype, "position", void 0);
171
+ __decorate([
172
+ property({ type: Number })
173
+ ], LitMaterialNavigationDrawer.prototype, "selected", void 0);
174
+ __decorate([
175
+ property({ type: Boolean, reflect: true })
176
+ ], LitMaterialNavigationDrawer.prototype, "open", void 0);
177
+ __decorate([
178
+ property({ type: Boolean, attribute: "disable-backdrop-close" })
179
+ ], LitMaterialNavigationDrawer.prototype, "disableBackdropClose", void 0);
180
+ __decorate([
181
+ query("dialog")
182
+ ], LitMaterialNavigationDrawer.prototype, "dialogElement", void 0);
183
+ LitMaterialNavigationDrawer = __decorate([
184
+ customElement("lit-material-navigation-drawer")
185
+ ], LitMaterialNavigationDrawer);
186
+ export { LitMaterialNavigationDrawer };
187
+ //# sourceMappingURL=navigation-drawer.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"navigation-drawer.js","sourceRoot":"","sources":["../src/navigation-drawer.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare const styles: import("lit").CSSResult;
2
+ //# sourceMappingURL=navigation-rail-item-styles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"navigation-rail-item-styles.d.ts","sourceRoot":"","sources":["../src/navigation-rail-item-styles.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,MAAM,yBAuHlB,CAAC"}
@@ -0,0 +1,122 @@
1
+ import { css } from "lit";
2
+ export const styles = css `
3
+ :host {
4
+ display: block;
5
+ outline: none;
6
+ -webkit-tap-highlight-color: transparent;
7
+ }
8
+
9
+ :host([disabled]) {
10
+ pointer-events: none;
11
+ }
12
+
13
+ .item {
14
+ position: relative;
15
+ display: flex;
16
+ flex-direction: column;
17
+ align-items: center;
18
+ gap: 4px;
19
+ box-sizing: border-box;
20
+ width: 100%;
21
+ min-height: 56px;
22
+ padding-block: 4px;
23
+ border: none;
24
+ margin: 0;
25
+ background-color: transparent;
26
+ color: var(--md-sys-color-on-surface-variant, #49454f);
27
+ cursor: pointer;
28
+ text-decoration: none;
29
+ font-family: var(--md-sys-typescale-label-medium-font, Roboto, system-ui, sans-serif);
30
+ font-size: var(--md-sys-typescale-label-medium-size, 0.75rem);
31
+ font-weight: var(--md-sys-typescale-label-medium-weight, 500);
32
+ -webkit-appearance: none;
33
+ appearance: none;
34
+ }
35
+
36
+ .item:disabled,
37
+ .item[aria-disabled="true"] {
38
+ cursor: default;
39
+ }
40
+
41
+ :host([selected]) .item {
42
+ color: var(--md-sys-color-on-surface, #1c1b1f);
43
+ }
44
+
45
+ .icon-container {
46
+ position: relative;
47
+ display: flex;
48
+ align-items: center;
49
+ justify-content: center;
50
+ width: 56px;
51
+ height: 32px;
52
+ border-radius: var(--md-sys-shape-corner-full, 16px);
53
+ transition: background-color 150ms var(--md-sys-motion-easing-standard, cubic-bezier(0.2, 0, 0, 1));
54
+ }
55
+
56
+ :host([selected]) .icon-container {
57
+ background-color: var(--md-sys-color-secondary-container, #e8def8);
58
+ }
59
+
60
+ .icon ::slotted(*) {
61
+ display: block;
62
+ width: 24px;
63
+ height: 24px;
64
+ }
65
+
66
+ .badge ::slotted(*) {
67
+ position: absolute;
68
+ top: -4px;
69
+ right: 8px;
70
+ }
71
+
72
+ .label {
73
+ max-width: 100%;
74
+ overflow: hidden;
75
+ text-align: center;
76
+ text-overflow: ellipsis;
77
+ white-space: nowrap;
78
+ }
79
+
80
+ .state-layer {
81
+ position: absolute;
82
+ inset: 0;
83
+ border-radius: inherit;
84
+ background-color: currentColor;
85
+ opacity: 0;
86
+ pointer-events: none;
87
+ transition: opacity 100ms linear;
88
+ }
89
+
90
+ .item:hover .state-layer {
91
+ opacity: var(--md-sys-state-hover-state-layer-opacity, 0.08);
92
+ }
93
+
94
+ .state-layer[data-pressed] {
95
+ opacity: var(--md-sys-state-pressed-state-layer-opacity, 0.1);
96
+ }
97
+
98
+ .focus-ring {
99
+ position: absolute;
100
+ inset: -2px;
101
+ border-radius: inherit;
102
+ outline: 3px solid var(--md-sys-color-secondary, #625b71);
103
+ outline-offset: 2px;
104
+ pointer-events: none;
105
+ }
106
+
107
+ .focus-ring[hidden] {
108
+ display: none;
109
+ }
110
+
111
+ :host([disabled]) .item {
112
+ color: color-mix(in srgb, var(--md-sys-color-on-surface, #1c1b1f) 38%, transparent);
113
+ }
114
+
115
+ @media (prefers-reduced-motion: reduce) {
116
+ .icon-container,
117
+ .state-layer {
118
+ transition: none;
119
+ }
120
+ }
121
+ `;
122
+ //# sourceMappingURL=navigation-rail-item-styles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"navigation-rail-item-styles.js","sourceRoot":"","sources":["../src/navigation-rail-item-styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAE1B,MAAM,CAAC,MAAM,MAAM,GAAG,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAuHxB,CAAC"}
@@ -0,0 +1,46 @@
1
+ import { LitElement } from "lit";
2
+ /**
3
+ * A single destination inside a `lit-material-navigation-rail` — an icon in
4
+ * a pill-shaped active indicator, with a small label below it, following
5
+ * the MD3 navigation rail item spec.
6
+ *
7
+ * Renders as a real `<button>` by default, or an `<a>` when `href` is set.
8
+ * The ripple/focus-ring are scoped to the icon's indicator pill (not the
9
+ * whole item), matching how the indicator itself is the only part that
10
+ * visibly reacts to press/focus in the spec. `selected` is normally managed
11
+ * by the parent rail (see its docs), not set directly.
12
+ *
13
+ * @element lit-material-navigation-rail-item
14
+ *
15
+ * @slot - The label text.
16
+ * @slot icon - The icon.
17
+ * @slot badge - Optional badge content (a count or dot), positioned over the icon's top-right corner.
18
+ *
19
+ * @csspart item - The `<button>` or `<a>` (layout only, no background of its own).
20
+ * @csspart icon-container - The pill-shaped active indicator behind the icon.
21
+ * @csspart ripple - The state-layer element the hover/press feedback is drawn on.
22
+ * @csspart focus-ring - The focus indicator element.
23
+ */
24
+ export declare class LitMaterialNavigationRailItem extends LitElement {
25
+ static styles: import("lit").CSSResult;
26
+ static shadowRootOptions: ShadowRootInit;
27
+ selected: boolean;
28
+ disabled: boolean;
29
+ /** If set, renders the item as a link (`<a>`) instead of a `<button>`. */
30
+ href: string;
31
+ target: string;
32
+ private readonly stateLayerElement?;
33
+ private readonly ripple;
34
+ private readonly focusRing;
35
+ protected updated(): void;
36
+ private get content();
37
+ render(): import("lit").TemplateResult<1>;
38
+ private handleClick;
39
+ private handleLinkClick;
40
+ }
41
+ declare global {
42
+ interface HTMLElementTagNameMap {
43
+ "lit-material-navigation-rail-item": LitMaterialNavigationRailItem;
44
+ }
45
+ }
46
+ //# sourceMappingURL=navigation-rail-item.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"navigation-rail-item.d.ts","sourceRoot":"","sources":["../src/navigation-rail-item.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,UAAU,EAAW,MAAM,KAAK,CAAC;AAKhD;;;;;;;;;;;;;;;;;;;;;GAqBG;AACH,qBACa,6BAA8B,SAAQ,UAAU;IAC3D,OAAgB,MAAM,0BAAU;IAEhC,OAAgB,iBAAiB,EAAE,cAAc,CAG/C;IAE0C,QAAQ,UAAS;IACjB,QAAQ,UAAS;IAE7D,0EAA0E;IAC9D,IAAI,SAAM;IACV,MAAM,SAAM;IAED,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAc;IAExE,OAAO,CAAC,QAAQ,CAAC,MAAM,CAA8B;IACrD,OAAO,CAAC,QAAQ,CAAC,SAAS,CAAiC;cAExC,OAAO,IAAI,IAAI;IAIlC,OAAO,KAAK,OAAO,GAUlB;IAEQ,MAAM;IAmCf,OAAO,CAAC,WAAW;IAOnB,OAAO,CAAC,eAAe;CAMxB;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,mCAAmC,EAAE,6BAA6B,CAAC;KACpE;CACF"}
@@ -0,0 +1,128 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ 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;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ import { html, LitElement, nothing } from "lit";
8
+ import { customElement, property, query } from "lit/decorators.js";
9
+ import { FocusRingController, RippleController } from "@lit-material/core";
10
+ import { styles } from "./navigation-rail-item-styles.js";
11
+ /**
12
+ * A single destination inside a `lit-material-navigation-rail` — an icon in
13
+ * a pill-shaped active indicator, with a small label below it, following
14
+ * the MD3 navigation rail item spec.
15
+ *
16
+ * Renders as a real `<button>` by default, or an `<a>` when `href` is set.
17
+ * The ripple/focus-ring are scoped to the icon's indicator pill (not the
18
+ * whole item), matching how the indicator itself is the only part that
19
+ * visibly reacts to press/focus in the spec. `selected` is normally managed
20
+ * by the parent rail (see its docs), not set directly.
21
+ *
22
+ * @element lit-material-navigation-rail-item
23
+ *
24
+ * @slot - The label text.
25
+ * @slot icon - The icon.
26
+ * @slot badge - Optional badge content (a count or dot), positioned over the icon's top-right corner.
27
+ *
28
+ * @csspart item - The `<button>` or `<a>` (layout only, no background of its own).
29
+ * @csspart icon-container - The pill-shaped active indicator behind the icon.
30
+ * @csspart ripple - The state-layer element the hover/press feedback is drawn on.
31
+ * @csspart focus-ring - The focus indicator element.
32
+ */
33
+ let LitMaterialNavigationRailItem = class LitMaterialNavigationRailItem extends LitElement {
34
+ constructor() {
35
+ super(...arguments);
36
+ this.selected = false;
37
+ this.disabled = false;
38
+ /** If set, renders the item as a link (`<a>`) instead of a `<button>`. */
39
+ this.href = "";
40
+ this.target = "";
41
+ this.ripple = new RippleController(this);
42
+ this.focusRing = new FocusRingController(this);
43
+ }
44
+ static { this.styles = styles; }
45
+ static { this.shadowRootOptions = {
46
+ ...LitElement.shadowRootOptions,
47
+ delegatesFocus: true,
48
+ }; }
49
+ updated() {
50
+ if (this.stateLayerElement)
51
+ this.ripple.attach(this.stateLayerElement);
52
+ }
53
+ get content() {
54
+ return html `
55
+ <span class="icon-container" part="icon-container">
56
+ <div class="focus-ring" part="focus-ring" ?hidden=${!this.focusRing.visible}></div>
57
+ <div class="state-layer" part="ripple"></div>
58
+ <slot name="icon" class="icon"></slot>
59
+ <slot name="badge" class="badge"></slot>
60
+ </span>
61
+ <span class="label"><slot></slot></span>
62
+ `;
63
+ }
64
+ render() {
65
+ const ariaCurrent = this.selected ? "page" : nothing;
66
+ if (this.href) {
67
+ return html `
68
+ <a
69
+ class="item"
70
+ part="item"
71
+ href=${this.disabled ? nothing : this.href}
72
+ target=${this.target || nothing}
73
+ rel=${this.target === "_blank" ? "noopener noreferrer" : nothing}
74
+ aria-current=${ariaCurrent}
75
+ aria-disabled=${this.disabled ? "true" : nothing}
76
+ tabindex=${this.disabled ? "-1" : "0"}
77
+ @click=${this.handleLinkClick}
78
+ >
79
+ ${this.content}
80
+ </a>
81
+ `;
82
+ }
83
+ return html `
84
+ <button
85
+ class="item"
86
+ part="item"
87
+ type="button"
88
+ ?disabled=${this.disabled}
89
+ aria-current=${ariaCurrent}
90
+ @click=${this.handleClick}
91
+ >
92
+ ${this.content}
93
+ </button>
94
+ `;
95
+ }
96
+ handleClick(event) {
97
+ if (this.disabled) {
98
+ event.preventDefault();
99
+ event.stopImmediatePropagation();
100
+ }
101
+ }
102
+ handleLinkClick(event) {
103
+ if (this.disabled) {
104
+ event.preventDefault();
105
+ event.stopImmediatePropagation();
106
+ }
107
+ }
108
+ };
109
+ __decorate([
110
+ property({ type: Boolean, reflect: true })
111
+ ], LitMaterialNavigationRailItem.prototype, "selected", void 0);
112
+ __decorate([
113
+ property({ type: Boolean, reflect: true })
114
+ ], LitMaterialNavigationRailItem.prototype, "disabled", void 0);
115
+ __decorate([
116
+ property()
117
+ ], LitMaterialNavigationRailItem.prototype, "href", void 0);
118
+ __decorate([
119
+ property()
120
+ ], LitMaterialNavigationRailItem.prototype, "target", void 0);
121
+ __decorate([
122
+ query(".state-layer")
123
+ ], LitMaterialNavigationRailItem.prototype, "stateLayerElement", void 0);
124
+ LitMaterialNavigationRailItem = __decorate([
125
+ customElement("lit-material-navigation-rail-item")
126
+ ], LitMaterialNavigationRailItem);
127
+ export { LitMaterialNavigationRailItem };
128
+ //# sourceMappingURL=navigation-rail-item.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"navigation-rail-item.js","sourceRoot":"","sources":["../src/navigation-rail-item.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,2 @@
1
+ export declare const styles: import("lit").CSSResult;
2
+ //# sourceMappingURL=navigation-rail-styles.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"navigation-rail-styles.d.ts","sourceRoot":"","sources":["../src/navigation-rail-styles.ts"],"names":[],"mappings":"AAEA,eAAO,MAAM,MAAM,yBAgDlB,CAAC"}
@@ -0,0 +1,51 @@
1
+ import { css } from "lit";
2
+ export const styles = css `
3
+ :host {
4
+ display: block;
5
+ box-sizing: border-box;
6
+ }
7
+
8
+ .rail {
9
+ display: flex;
10
+ flex-direction: column;
11
+ align-items: center;
12
+ box-sizing: border-box;
13
+ width: 80px;
14
+ height: 100%;
15
+ padding-block: 12px;
16
+ background-color: var(--md-sys-color-surface, #fffbfe);
17
+ color: var(--md-sys-color-on-surface, #1c1b1f);
18
+ }
19
+
20
+ .fab {
21
+ flex: none;
22
+ margin-block-end: 12px;
23
+ }
24
+
25
+ .fab:empty {
26
+ display: none;
27
+ }
28
+
29
+ .items {
30
+ display: flex;
31
+ flex: 1;
32
+ flex-direction: column;
33
+ gap: 4px;
34
+ width: 100%;
35
+ min-height: 0;
36
+ overflow-y: auto;
37
+ }
38
+
39
+ .items.top {
40
+ justify-content: flex-start;
41
+ }
42
+
43
+ .items.center {
44
+ justify-content: center;
45
+ }
46
+
47
+ .items.bottom {
48
+ justify-content: flex-end;
49
+ }
50
+ `;
51
+ //# sourceMappingURL=navigation-rail-styles.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"navigation-rail-styles.js","sourceRoot":"","sources":["../src/navigation-rail-styles.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,GAAG,EAAE,MAAM,KAAK,CAAC;AAE1B,MAAM,CAAC,MAAM,MAAM,GAAG,GAAG,CAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;CAgDxB,CAAC"}
@@ -0,0 +1,44 @@
1
+ import { LitElement } from "lit";
2
+ export type NavigationRailAlignment = "top" | "center" | "bottom";
3
+ /**
4
+ * Material Design 3 navigation rail — a narrow, always-visible vertical bar
5
+ * of primary destinations (`lit-material-navigation-rail-item` elements),
6
+ * typically docked to one edge for medium/large window sizes.
7
+ *
8
+ * Selection is index-based and managed here (like `lit-material-tabs`): set
9
+ * `selected` to reflect your current route/section, and each item's own
10
+ * `selected` is kept in sync automatically. Clicking an item updates
11
+ * `selected` and fires `change` — items themselves don't manage selection.
12
+ *
13
+ * @element lit-material-navigation-rail
14
+ *
15
+ * @slot - `lit-material-navigation-rail-item` elements.
16
+ * @slot fab - An optional FAB shown above the items.
17
+ *
18
+ * @csspart rail - The bar (background, width, padding).
19
+ * @csspart fab - The fab slot's container.
20
+ * @csspart items - The items slot's container.
21
+ *
22
+ * @fires change - Fires when `selected` changes via an item click.
23
+ */
24
+ export declare class LitMaterialNavigationRail extends LitElement {
25
+ static styles: import("lit").CSSResult;
26
+ /** Where the item group sits within the rail's height. */
27
+ alignment: NavigationRailAlignment;
28
+ /** Index of the selected item. `-1` means no selection. */
29
+ selected: number;
30
+ constructor();
31
+ connectedCallback(): void;
32
+ protected updated(changed: Map<string, unknown>): void;
33
+ private get items();
34
+ private syncSelected;
35
+ private readonly handleSlotChange;
36
+ private readonly handleClick;
37
+ render(): import("lit").TemplateResult<1>;
38
+ }
39
+ declare global {
40
+ interface HTMLElementTagNameMap {
41
+ "lit-material-navigation-rail": LitMaterialNavigationRail;
42
+ }
43
+ }
44
+ //# sourceMappingURL=navigation-rail.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"navigation-rail.d.ts","sourceRoot":"","sources":["../src/navigation-rail.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,UAAU,EAAE,MAAM,KAAK,CAAC;AAKvC,MAAM,MAAM,uBAAuB,GAAG,KAAK,GAAG,QAAQ,GAAG,QAAQ,CAAC;AAElE;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,qBACa,yBAA0B,SAAQ,UAAU;IACvD,OAAgB,MAAM,0BAAU;IAEhC,0DAA0D;IAC9C,SAAS,EAAE,uBAAuB,CAAS;IAEvD,2DAA2D;IAC/B,QAAQ,SAAM;;IAOjC,iBAAiB,IAAI,IAAI;cAKf,OAAO,CAAC,OAAO,EAAE,GAAG,CAAC,MAAM,EAAE,OAAO,CAAC,GAAG,IAAI;IAI/D,OAAO,KAAK,KAAK,GAGhB;IAED,OAAO,CAAC,YAAY;IAMpB,OAAO,CAAC,QAAQ,CAAC,gBAAgB,CAAmC;IAEpE,OAAO,CAAC,QAAQ,CAAC,WAAW,CAS1B;IAEO,MAAM;CAUhB;AAED,OAAO,CAAC,MAAM,CAAC;IACb,UAAU,qBAAqB;QAC7B,8BAA8B,EAAE,yBAAyB,CAAC;KAC3D;CACF"}