@3mo/navigation 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/dist/INavigation.d.ts +35 -0
  2. package/dist/INavigation.d.ts.map +1 -0
  3. package/dist/INavigation.js +2 -0
  4. package/dist/Navigation.d.ts +75 -0
  5. package/dist/Navigation.d.ts.map +1 -0
  6. package/dist/Navigation.js +304 -0
  7. package/dist/NavigationBar.d.ts +32 -0
  8. package/dist/NavigationBar.d.ts.map +1 -0
  9. package/dist/NavigationBar.js +90 -0
  10. package/dist/NavigationBarItem.d.ts +30 -0
  11. package/dist/NavigationBarItem.d.ts.map +1 -0
  12. package/dist/NavigationBarItem.js +108 -0
  13. package/dist/NavigationDrawer.d.ts +38 -0
  14. package/dist/NavigationDrawer.d.ts.map +1 -0
  15. package/dist/NavigationDrawer.js +89 -0
  16. package/dist/NavigationGroup.d.ts +22 -0
  17. package/dist/NavigationGroup.d.ts.map +1 -0
  18. package/dist/NavigationGroup.js +17 -0
  19. package/dist/NavigationLink.d.ts +24 -0
  20. package/dist/NavigationLink.d.ts.map +1 -0
  21. package/dist/NavigationLink.js +33 -0
  22. package/dist/NavigationPresentation.d.ts +8 -0
  23. package/dist/NavigationPresentation.d.ts.map +1 -0
  24. package/dist/NavigationPresentation.js +1 -0
  25. package/dist/NavigationRail.d.ts +52 -0
  26. package/dist/NavigationRail.d.ts.map +1 -0
  27. package/dist/NavigationRail.js +213 -0
  28. package/dist/NavigationRailItem.d.ts +28 -0
  29. package/dist/NavigationRailItem.d.ts.map +1 -0
  30. package/dist/NavigationRailItem.js +103 -0
  31. package/dist/NavigationTree.d.ts +33 -0
  32. package/dist/NavigationTree.d.ts.map +1 -0
  33. package/dist/NavigationTree.js +87 -0
  34. package/dist/NavigationTreeItem.d.ts +19 -0
  35. package/dist/NavigationTreeItem.d.ts.map +1 -0
  36. package/dist/NavigationTreeItem.js +115 -0
  37. package/dist/custom-elements.json +1208 -0
  38. package/dist/index.d.ts +21 -0
  39. package/dist/index.d.ts.map +1 -0
  40. package/dist/index.js +20 -0
  41. package/dist/tsconfig.tsbuildinfo +1 -0
  42. package/package.json +49 -0
@@ -0,0 +1,35 @@
1
+ import type { DirectiveResult, HTMLTemplateResult } from '@a11d/lit';
2
+ import type { MaterialIcon } from '@3mo/icon';
3
+ /** What an implementation of @see INavigation is given, beyond whatever it derives itself. */
4
+ export type NavigationOptions = {
5
+ readonly label?: string | HTMLTemplateResult;
6
+ readonly icon?: MaterialIcon;
7
+ readonly hidden?: boolean;
8
+ readonly hasSeparator?: boolean;
9
+ };
10
+ export type NavigationInvocationOptions = {
11
+ /** Called after the navigation has been invoked, e.g. to close whatever presented it. */
12
+ readonly invocationHandler?: () => void;
13
+ };
14
+ /**
15
+ * A destination, or a group of destinations, as the navigation components present it.
16
+ *
17
+ * It carries no routing of its own — an application implements `link` with whatever makes an element
18
+ * navigate, and reports through `current` which navigation the page being shown belongs to.
19
+ */
20
+ export interface INavigation {
21
+ readonly label: string | HTMLTemplateResult;
22
+ readonly icon?: MaterialIcon;
23
+ /** Whether the navigation shall not be presented at all, e.g. because the user may not reach it. */
24
+ readonly hidden?: boolean;
25
+ /** Whether a divider parts this navigation from the one before it. */
26
+ readonly hasSeparator?: boolean;
27
+ readonly children?: ReadonlyArray<INavigation>;
28
+ /** Whether this navigation, or any of its descendants, is the page being shown. */
29
+ readonly current?: boolean;
30
+ /** Applied to the element which invokes this navigation, making it navigate there. */
31
+ link?(options?: NavigationInvocationOptions): DirectiveResult;
32
+ }
33
+ /** The navigations which shall be presented, in the order they were given. */
34
+ export declare const visibleNavigations: (navigations: ReadonlyArray<INavigation> | undefined) => INavigation[];
35
+ //# sourceMappingURL=INavigation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"INavigation.d.ts","sourceRoot":"","sources":["../INavigation.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,kBAAkB,EAAE,MAAM,WAAW,CAAA;AACpE,OAAO,KAAK,EAAE,YAAY,EAAE,MAAM,WAAW,CAAA;AAE7C,8FAA8F;AAC9F,MAAM,MAAM,iBAAiB,GAAG;IAC/B,QAAQ,CAAC,KAAK,CAAC,EAAE,MAAM,GAAG,kBAAkB,CAAA;IAC5C,QAAQ,CAAC,IAAI,CAAC,EAAE,YAAY,CAAA;IAC5B,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAA;IACzB,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAA;CAC/B,CAAA;AAED,MAAM,MAAM,2BAA2B,GAAG;IACzC,yFAAyF;IACzF,QAAQ,CAAC,iBAAiB,CAAC,EAAE,MAAM,IAAI,CAAA;CACvC,CAAA;AAED;;;;;GAKG;AACH,MAAM,WAAW,WAAW;IAC3B,QAAQ,CAAC,KAAK,EAAE,MAAM,GAAG,kBAAkB,CAAA;IAC3C,QAAQ,CAAC,IAAI,CAAC,EAAE,YAAY,CAAA;IAC5B,oGAAoG;IACpG,QAAQ,CAAC,MAAM,CAAC,EAAE,OAAO,CAAA;IACzB,sEAAsE;IACtE,QAAQ,CAAC,YAAY,CAAC,EAAE,OAAO,CAAA;IAC/B,QAAQ,CAAC,QAAQ,CAAC,EAAE,aAAa,CAAC,WAAW,CAAC,CAAA;IAC9C,mFAAmF;IACnF,QAAQ,CAAC,OAAO,CAAC,EAAE,OAAO,CAAA;IAC1B,sFAAsF;IACtF,IAAI,CAAC,CAAC,OAAO,CAAC,EAAE,2BAA2B,GAAG,eAAe,CAAA;CAC7D;AAED,8EAA8E;AAC9E,eAAO,MAAM,kBAAkB,GAAI,aAAa,aAAa,CAAC,WAAW,CAAC,GAAG,SAAS,kBAAsD,CAAA"}
@@ -0,0 +1,2 @@
1
+ /** The navigations which shall be presented, in the order they were given. */
2
+ export const visibleNavigations = (navigations) => navigations?.filter(n => n.hidden !== true) ?? [];
@@ -0,0 +1,75 @@
1
+ import { Component, type HTMLTemplateResult, type PropertyValues } from '@a11d/lit';
2
+ import { type INavigation } from './INavigation.js';
3
+ import { type NavigationPresentation } from './NavigationPresentation.js';
4
+ import './NavigationBar.js';
5
+ import './NavigationRail.js';
6
+ import './NavigationDrawer.js';
7
+ /**
8
+ * The application's shell: a header, the page beside or beneath it, and the navigations presented as
9
+ * whichever of `bar`, `rail` and `drawer` fits.
10
+ *
11
+ * `presentations` is the order they are preferred in, and the first one which fits is the one shown —
12
+ * the bar as long as its navigations fit its row, the rail as long as the page keeps
13
+ * `--mo-navigation-min-content-size` beside it, and the drawer, which always fits. Demoting the bar is
14
+ * therefore a matter of leaving it out of the order rather than of replacing the shell.
15
+ *
16
+ * @element mo-navigation
17
+ *
18
+ * @attr navigations - The navigations to present.
19
+ * @attr presentations - The presentations to choose from, most preferred first. Defaults to `bar` then `drawer`.
20
+ * @attr presentation - The presentation being shown. Derived, and reflected for styling.
21
+ * @attr heading - The application's heading, shown in the header and above the drawer's navigations.
22
+ * @attr drawerOpen - Whether the drawer is open. Only of consequence while the drawer is the presentation.
23
+ *
24
+ * @slot - The page.
25
+ * @slot logo - Placed at the start of the header, and at the top of the rail.
26
+ * @slot end - Placed at the end of the header.
27
+ *
28
+ * @csspart app-bar - The header above the page.
29
+ * @csspart content - What the page is placed in.
30
+ *
31
+ * @cssprop --mo-navigation-min-content-size - How much room the page keeps beside the rail. Defaults to `32rem`, which puts the rail's threshold at Material's medium window.
32
+ * @cssprop --mo-navigation-rail-size - How wide the rail's strip is. Defaults to `5.5rem`.
33
+ * @cssprop --mo-navigation-rail-panel-size - How wide the rail's panel is. Defaults to `17rem`.
34
+ *
35
+ * @i18n "Navigation"
36
+ */
37
+ export declare class Navigation extends Component {
38
+ navigations: INavigation[];
39
+ presentations: NavigationPresentation[];
40
+ heading?: string | HTMLTemplateResult;
41
+ presentation: NavigationPresentation;
42
+ drawerOpen: boolean;
43
+ private railDocked;
44
+ get navigationBar(): import("./NavigationBar.js").NavigationBar | null;
45
+ get navigationRail(): import("./NavigationRail.js").NavigationRail | null;
46
+ get menuButton(): HTMLElement | null;
47
+ private readonly railMetrics?;
48
+ private readonly railDockedMetrics?;
49
+ private readonly resizeObserver;
50
+ connectedCallback(): void;
51
+ disconnectedCallback(): void;
52
+ protected handleKeyDown(event: KeyboardEvent): void;
53
+ focus(options?: FocusOptions): void;
54
+ protected update(props: PropertyValues<this>): void;
55
+ private drawerWasOpen;
56
+ protected updated(props: PropertyValues<this>): void;
57
+ private resolvePresentation;
58
+ private fits;
59
+ /**
60
+ * Whether the shell is at least as wide as the probe, which is what resolves the rail's sizes
61
+ * without the rail having to be there. Unknown until both have been laid out.
62
+ */
63
+ private hasRoomFor;
64
+ static get styles(): import("@a11d/lit").CSSResult;
65
+ protected get template(): HTMLTemplateResult;
66
+ private get barTemplate();
67
+ private get railTemplate();
68
+ private get drawerTemplate();
69
+ }
70
+ declare global {
71
+ interface HTMLElementTagNameMap {
72
+ 'mo-navigation': Navigation;
73
+ }
74
+ }
75
+ //# sourceMappingURL=Navigation.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"Navigation.d.ts","sourceRoot":"","sources":["../Navigation.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,SAAS,EAAoF,KAAK,kBAAkB,EAAE,KAAK,cAAc,EAAE,MAAM,WAAW,CAAA;AAC3K,OAAO,EAAE,KAAK,WAAW,EAAE,MAAM,kBAAkB,CAAA;AACnD,OAAO,EAAE,KAAK,sBAAsB,EAAE,MAAM,6BAA6B,CAAA;AACzE,OAAO,oBAAoB,CAAA;AAC3B,OAAO,qBAAqB,CAAA;AAC5B,OAAO,uBAAuB,CAAA;AAE9B;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GA6BG;AACH,qBACa,UAAW,SAAQ,SAAS;IACb,WAAW,gBAA2B;IACtC,aAAa,2BAAqD;IACjF,OAAO,CAAC,EAAE,MAAM,GAAG,kBAAkB,CAAA;IACpB,YAAY,EAAE,sBAAsB,CAAQ;IAE5C,UAAU,UAAQ;IAEtC,OAAO,CAAC,UAAU,CAAQ;IAEnC,IAAI,aAAa,sDAAyE;IAC1F,IAAI,cAAc,wDAA0E;IAC5F,IAAI,UAAU,uBAA8F;IAEpF,OAAO,CAAC,QAAQ,CAAC,WAAW,CAAC,CAAa;IACnC,OAAO,CAAC,QAAQ,CAAC,iBAAiB,CAAC,CAAa;IAE/E,OAAO,CAAC,QAAQ,CAAC,cAAc,CAAwE;IAE9F,iBAAiB;IAKjB,oBAAoB;IAM7B,SAAS,CAAC,aAAa,CAAC,KAAK,EAAE,aAAa;IAOnC,KAAK,CAAC,OAAO,CAAC,EAAE,YAAY;cAclB,MAAM,CAAC,KAAK,EAAE,cAAc,CAAC,IAAI,CAAC;IAOrD,OAAO,CAAC,aAAa,CAAQ;cAEV,OAAO,CAAC,KAAK,EAAE,cAAc,CAAC,IAAI,CAAC;IAQtD,OAAO,CAAC,mBAAmB;IAM3B,OAAO,CAAC,IAAI;IAWZ;;;OAGG;IACH,OAAO,CAAC,UAAU;IAKlB,WAAoB,MAAM,kCAqGzB;IAED,cAAuB,QAAQ,uBAiC9B;IAED,OAAO,KAAK,WAAW,GAOtB;IAED,OAAO,KAAK,YAAY,GAMvB;IAED,OAAO,KAAK,cAAc,GAQzB;CACD;AAED,OAAO,CAAC,MAAM,CAAC;IACd,UAAU,qBAAqB;QAC9B,eAAe,EAAE,UAAU,CAAA;KAC3B;CACD"}
@@ -0,0 +1,304 @@
1
+ import { __decorate } from "tslib";
2
+ import { bind, Component, component, css, eventListener, html, ifDefined, isServer, property, query, state } from '@a11d/lit';
3
+ import './NavigationBar.js';
4
+ import './NavigationRail.js';
5
+ import './NavigationDrawer.js';
6
+ /**
7
+ * The application's shell: a header, the page beside or beneath it, and the navigations presented as
8
+ * whichever of `bar`, `rail` and `drawer` fits.
9
+ *
10
+ * `presentations` is the order they are preferred in, and the first one which fits is the one shown —
11
+ * the bar as long as its navigations fit its row, the rail as long as the page keeps
12
+ * `--mo-navigation-min-content-size` beside it, and the drawer, which always fits. Demoting the bar is
13
+ * therefore a matter of leaving it out of the order rather than of replacing the shell.
14
+ *
15
+ * @element mo-navigation
16
+ *
17
+ * @attr navigations - The navigations to present.
18
+ * @attr presentations - The presentations to choose from, most preferred first. Defaults to `bar` then `drawer`.
19
+ * @attr presentation - The presentation being shown. Derived, and reflected for styling.
20
+ * @attr heading - The application's heading, shown in the header and above the drawer's navigations.
21
+ * @attr drawerOpen - Whether the drawer is open. Only of consequence while the drawer is the presentation.
22
+ *
23
+ * @slot - The page.
24
+ * @slot logo - Placed at the start of the header, and at the top of the rail.
25
+ * @slot end - Placed at the end of the header.
26
+ *
27
+ * @csspart app-bar - The header above the page.
28
+ * @csspart content - What the page is placed in.
29
+ *
30
+ * @cssprop --mo-navigation-min-content-size - How much room the page keeps beside the rail. Defaults to `32rem`, which puts the rail's threshold at Material's medium window.
31
+ * @cssprop --mo-navigation-rail-size - How wide the rail's strip is. Defaults to `5.5rem`.
32
+ * @cssprop --mo-navigation-rail-panel-size - How wide the rail's panel is. Defaults to `17rem`.
33
+ *
34
+ * @i18n "Navigation"
35
+ */
36
+ let Navigation = class Navigation extends Component {
37
+ constructor() {
38
+ super(...arguments);
39
+ this.navigations = new Array();
40
+ this.presentations = new Array('bar', 'drawer');
41
+ this.presentation = 'bar';
42
+ this.drawerOpen = false;
43
+ this.railDocked = false;
44
+ this.resizeObserver = isServer ? undefined : new ResizeObserver(() => this.requestUpdate());
45
+ /* The drawer writes its own state back, which can skip a property's update hook altogether. */
46
+ this.drawerWasOpen = false;
47
+ }
48
+ get navigationBar() { return this.renderRoot?.querySelector('mo-navigation-bar') ?? null; }
49
+ get navigationRail() { return this.renderRoot?.querySelector('mo-navigation-rail') ?? null; }
50
+ get menuButton() { return this.renderRoot?.querySelector('mo-icon-button[icon=menu]') ?? null; }
51
+ connectedCallback() {
52
+ super.connectedCallback();
53
+ this.resizeObserver?.observe(this);
54
+ }
55
+ disconnectedCallback() {
56
+ this.resizeObserver?.disconnect();
57
+ super.disconnectedCallback();
58
+ }
59
+ handleKeyDown(event) {
60
+ if (event.key === 'Alt' && event.composedPath().filter(e => e instanceof Element).every(e => e.tagName.toLowerCase() !== 'input')) {
61
+ event.preventDefault();
62
+ this.focus();
63
+ }
64
+ }
65
+ focus(options) {
66
+ switch (this.presentation) {
67
+ case 'bar':
68
+ this.navigationBar?.focus(options);
69
+ break;
70
+ case 'rail':
71
+ this.navigationRail?.focus(options);
72
+ break;
73
+ default:
74
+ this.menuButton?.focus(options);
75
+ break;
76
+ }
77
+ }
78
+ update(props) {
79
+ this.presentation = this.resolvePresentation();
80
+ this.railDocked = this.hasRoomFor(this.railDockedMetrics) ?? false;
81
+ super.update(props);
82
+ }
83
+ updated(props) {
84
+ super.updated(props);
85
+ if (this.drawerWasOpen && this.drawerOpen === false) {
86
+ this.menuButton?.focus();
87
+ }
88
+ this.drawerWasOpen = this.drawerOpen;
89
+ }
90
+ resolvePresentation() {
91
+ return this.presentations.find(presentation => this.fits(presentation))
92
+ ?? this.presentations[this.presentations.length - 1]
93
+ ?? 'drawer';
94
+ }
95
+ fits(presentation) {
96
+ switch (presentation) {
97
+ case 'bar':
98
+ return this.navigationBar?.hasOverflow !== true;
99
+ case 'rail':
100
+ return this.hasRoomFor(this.railMetrics) ?? true;
101
+ default:
102
+ return true;
103
+ }
104
+ }
105
+ /**
106
+ * Whether the shell is at least as wide as the probe, which is what resolves the rail's sizes
107
+ * without the rail having to be there. Unknown until both have been laid out.
108
+ */
109
+ hasRoomFor(probe) {
110
+ const required = probe?.offsetWidth;
111
+ return !required || !this.clientWidth ? undefined : this.clientWidth >= required;
112
+ }
113
+ static get styles() {
114
+ return css `
115
+ :host {
116
+ display: grid;
117
+ grid-template-columns: auto minmax(0, 1fr);
118
+ flex: 1;
119
+ min-block-size: 0;
120
+ }
121
+
122
+ #metrics {
123
+ position: absolute;
124
+ visibility: hidden;
125
+ pointer-events: none;
126
+ inline-size: 0;
127
+ block-size: 0;
128
+ overflow: hidden;
129
+
130
+ #metrics-rail {
131
+ inline-size: calc(var(--mo-navigation-rail-size, 5.5rem) + var(--mo-navigation-min-content-size, 32rem));
132
+ }
133
+
134
+ #metrics-rail-docked {
135
+ inline-size: calc(var(--mo-navigation-rail-size, 5.5rem) + var(--mo-navigation-rail-panel-size, 17rem) + var(--mo-navigation-min-content-size, 32rem));
136
+ }
137
+ }
138
+
139
+ mo-navigation-rail {
140
+ grid-column: 1;
141
+ }
142
+
143
+ #main {
144
+ grid-column: 2;
145
+ display: flex;
146
+ flex-direction: column;
147
+ min-inline-size: 0;
148
+ }
149
+
150
+ [part=app-bar] {
151
+ display: flex;
152
+ flex-direction: row;
153
+ align-items: center;
154
+ gap: 32px;
155
+ flex: 0 0 auto;
156
+ block-size: 48px;
157
+ padding-inline-start: 4px;
158
+ background: var(--mo-color-accent);
159
+ color: var(--mo-color-on-accent);
160
+ overflow: hidden;
161
+ }
162
+
163
+ #brand {
164
+ display: flex;
165
+ flex-direction: row;
166
+ align-items: center;
167
+ white-space: nowrap;
168
+ overflow: hidden;
169
+ text-overflow: ellipsis;
170
+ }
171
+
172
+ slot[name=logo]::slotted(*) {
173
+ block-size: 30px;
174
+ margin-inline-start: 0.875rem;
175
+ }
176
+
177
+ #heading {
178
+ margin: 2px 0 0 8px;
179
+ font-size: 23px;
180
+ white-space: nowrap;
181
+ overflow: hidden;
182
+ text-overflow: ellipsis;
183
+ }
184
+
185
+ mo-navigation-bar {
186
+ flex: 1;
187
+ min-inline-size: 0;
188
+ /* The bar keeps its place even while another presentation is shown, since only a bar which is
189
+ laid out can report that its navigations fit again. */
190
+ &:not([data-presentation=bar]) {
191
+ visibility: hidden;
192
+ }
193
+ }
194
+
195
+ #end {
196
+ display: flex;
197
+ flex-direction: row;
198
+ align-items: center;
199
+ gap: 8px;
200
+ margin-inline-start: auto;
201
+ }
202
+
203
+ mo-icon-button[icon=menu] {
204
+ font-size: 20px;
205
+ }
206
+
207
+ [part=content] {
208
+ display: flex;
209
+ flex-direction: column;
210
+ flex: 1;
211
+ min-block-size: 0;
212
+ }
213
+ `;
214
+ }
215
+ get template() {
216
+ return html `
217
+ <div id='metrics' aria-hidden='true'>
218
+ <div id='metrics-rail'></div>
219
+ <div id='metrics-rail-docked'></div>
220
+ </div>
221
+
222
+ ${this.railTemplate}
223
+
224
+ <div id='main'>
225
+ <header part='app-bar'>
226
+ <div id='brand'>
227
+ ${this.presentation !== 'drawer' ? html.nothing : html `
228
+ <mo-icon-button icon='menu' aria-label=${t('Navigation')} @click=${() => this.drawerOpen = !this.drawerOpen}></mo-icon-button>
229
+ `}
230
+ ${this.presentation === 'rail' ? html.nothing : html `<slot name='logo'></slot>`}
231
+ <div id='heading'>${this.heading}</div>
232
+ </div>
233
+
234
+ ${this.barTemplate}
235
+
236
+ <div id='end'>
237
+ <slot name='end'></slot>
238
+ </div>
239
+ </header>
240
+
241
+ <div part='content'>
242
+ <slot></slot>
243
+ </div>
244
+ </div>
245
+
246
+ ${this.drawerTemplate}
247
+ `;
248
+ }
249
+ get barTemplate() {
250
+ return !this.presentations.includes('bar') ? html.nothing : html `
251
+ <mo-navigation-bar
252
+ .navigations=${this.navigations}
253
+ data-presentation=${this.presentation}
254
+ ></mo-navigation-bar>
255
+ `;
256
+ }
257
+ get railTemplate() {
258
+ return this.presentation !== 'rail' ? html.nothing : html `
259
+ <mo-navigation-rail ?docked=${this.railDocked} .navigations=${this.navigations}>
260
+ <slot name='logo' slot='header'></slot>
261
+ </mo-navigation-rail>
262
+ `;
263
+ }
264
+ get drawerTemplate() {
265
+ return this.presentation !== 'drawer' ? html.nothing : html `
266
+ <mo-navigation-drawer
267
+ ?open=${bind(this, 'drawerOpen')}
268
+ heading=${ifDefined(this.heading)}
269
+ .navigations=${this.navigations}
270
+ ></mo-navigation-drawer>
271
+ `;
272
+ }
273
+ };
274
+ __decorate([
275
+ property({ type: Array })
276
+ ], Navigation.prototype, "navigations", void 0);
277
+ __decorate([
278
+ property({ type: Array })
279
+ ], Navigation.prototype, "presentations", void 0);
280
+ __decorate([
281
+ property()
282
+ ], Navigation.prototype, "heading", void 0);
283
+ __decorate([
284
+ property({ reflect: true })
285
+ ], Navigation.prototype, "presentation", void 0);
286
+ __decorate([
287
+ property({ type: Boolean })
288
+ ], Navigation.prototype, "drawerOpen", void 0);
289
+ __decorate([
290
+ state()
291
+ ], Navigation.prototype, "railDocked", void 0);
292
+ __decorate([
293
+ query('#metrics-rail')
294
+ ], Navigation.prototype, "railMetrics", void 0);
295
+ __decorate([
296
+ query('#metrics-rail-docked')
297
+ ], Navigation.prototype, "railDockedMetrics", void 0);
298
+ __decorate([
299
+ eventListener({ target: window, type: 'keydown' })
300
+ ], Navigation.prototype, "handleKeyDown", null);
301
+ Navigation = __decorate([
302
+ component('mo-navigation')
303
+ ], Navigation);
304
+ export { Navigation };
@@ -0,0 +1,32 @@
1
+ import { Component } from '@a11d/lit';
2
+ import { type INavigation } from './INavigation.js';
3
+ import './NavigationBarItem.js';
4
+ /**
5
+ * The navigations as a horizontal row, each group opening its destinations as a dropdown.
6
+ *
7
+ * It reports through `hasOverflow` whether its navigations still fit, which is what an orchestrating
8
+ * `mo-navigation` decides by whether the bar is the presentation it can afford.
9
+ *
10
+ * @element mo-navigation-bar
11
+ *
12
+ * @attr navigations - The navigations to present.
13
+ * @fires invoke - Dispatched with the navigation which was invoked.
14
+ */
15
+ export declare class NavigationBar extends Component {
16
+ readonly invoke: EventDispatcher<INavigation>;
17
+ navigations: INavigation[];
18
+ readonly role = "navigation";
19
+ private readonly overflowController;
20
+ get items(): readonly import("./NavigationBarItem.js").NavigationBarItem[];
21
+ get hasOverflow(): boolean;
22
+ protected handleLocationChange(): void;
23
+ focus(options?: FocusOptions): void;
24
+ static get styles(): import("@a11d/lit").CSSResult;
25
+ protected get template(): import("lit-html").HTMLTemplateResult;
26
+ }
27
+ declare global {
28
+ interface HTMLElementTagNameMap {
29
+ 'mo-navigation-bar': NavigationBar;
30
+ }
31
+ }
32
+ //# sourceMappingURL=NavigationBar.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NavigationBar.d.ts","sourceRoot":"","sources":["../NavigationBar.ts"],"names":[],"mappings":"AAAA,OAAO,EAAE,SAAS,EAAgE,MAAM,WAAW,CAAA;AAEnG,OAAO,EAAsB,KAAK,WAAW,EAAE,MAAM,kBAAkB,CAAA;AACvE,OAAO,wBAAwB,CAAA;AAE/B;;;;;;;;;;GAUG;AACH,qBACa,aAAc,SAAQ,SAAS;IACD,QAAQ,CAAC,MAAM,EAAG,eAAe,CAAC,WAAW,CAAC,CAAA;IAE7D,WAAW,gBAA2B;IAEjE,SAAkB,IAAI,gBAAe;IAErC,OAAO,CAAC,QAAQ,CAAC,kBAAkB,CAEhC;IAEH,IAAI,KAAK,kEAER;IAED,IAAI,WAAW,YAEd;IAGD,SAAS,CAAC,oBAAoB;IAIrB,KAAK,CAAC,OAAO,CAAC,EAAE,YAAY;IASrC,WAAoB,MAAM,kCAmBzB;IAED,cAAuB,QAAQ,0CAY9B;CACD;AAED,OAAO,CAAC,MAAM,CAAC;IACd,UAAU,qBAAqB;QAC9B,mBAAmB,EAAE,aAAa,CAAA;KAClC;CACD"}
@@ -0,0 +1,90 @@
1
+ import { __decorate } from "tslib";
2
+ import { Component, component, css, event, eventListener, html, property, repeat } from '@a11d/lit';
3
+ import { OverflowController } from '@3mo/overflow-controller';
4
+ import { visibleNavigations } from './INavigation.js';
5
+ import './NavigationBarItem.js';
6
+ /**
7
+ * The navigations as a horizontal row, each group opening its destinations as a dropdown.
8
+ *
9
+ * It reports through `hasOverflow` whether its navigations still fit, which is what an orchestrating
10
+ * `mo-navigation` decides by whether the bar is the presentation it can afford.
11
+ *
12
+ * @element mo-navigation-bar
13
+ *
14
+ * @attr navigations - The navigations to present.
15
+ * @fires invoke - Dispatched with the navigation which was invoked.
16
+ */
17
+ let NavigationBar = class NavigationBar extends Component {
18
+ constructor() {
19
+ super(...arguments);
20
+ this.navigations = new Array();
21
+ this.role = 'navigation';
22
+ this.overflowController = new OverflowController(this, host => ({
23
+ get disabled() { return !host.overflowController.containerElement?.clientWidth; },
24
+ }));
25
+ }
26
+ get items() {
27
+ return this.overflowController.items;
28
+ }
29
+ get hasOverflow() {
30
+ return this.overflowController.hasOverflow;
31
+ }
32
+ handleLocationChange() {
33
+ this.requestUpdate();
34
+ }
35
+ focus(options) {
36
+ const item = this.items[0];
37
+ if (item) {
38
+ item.focus(options);
39
+ }
40
+ else {
41
+ super.focus(options);
42
+ }
43
+ }
44
+ static get styles() {
45
+ return css `
46
+ :host {
47
+ display: block;
48
+ overflow: hidden;
49
+ }
50
+
51
+ #items {
52
+ display: flex;
53
+ flex-direction: row;
54
+ align-items: center;
55
+ gap: 8px;
56
+ overflow: hidden;
57
+ }
58
+
59
+ mo-navigation-bar-item {
60
+ flex: 0 0 auto;
61
+ }
62
+ `;
63
+ }
64
+ get template() {
65
+ return html `
66
+ <div id='items' ${this.overflowController.container()}>
67
+ ${repeat(visibleNavigations(this.navigations), navigation => navigation, navigation => html `
68
+ <mo-navigation-bar-item ${this.overflowController.item()}
69
+ .navigation=${navigation}
70
+ .current=${navigation.current === true}
71
+ ${navigation.link?.({ invocationHandler: () => this.invoke.dispatch(navigation) }) ?? html.nothing}
72
+ ></mo-navigation-bar-item>
73
+ `)}
74
+ </div>
75
+ `;
76
+ }
77
+ };
78
+ __decorate([
79
+ event({ bubbles: true, composed: true })
80
+ ], NavigationBar.prototype, "invoke", void 0);
81
+ __decorate([
82
+ property({ type: Array })
83
+ ], NavigationBar.prototype, "navigations", void 0);
84
+ __decorate([
85
+ eventListener({ target: window, type: 'popstate' })
86
+ ], NavigationBar.prototype, "handleLocationChange", null);
87
+ NavigationBar = __decorate([
88
+ component('mo-navigation-bar')
89
+ ], NavigationBar);
90
+ export { NavigationBar };
@@ -0,0 +1,30 @@
1
+ import { Component } from '@a11d/lit';
2
+ import { type INavigation } from './INavigation.js';
3
+ import '@3mo/menu';
4
+ /**
5
+ * A navigation of a navigation bar: a destination, or a group opening its destinations as a dropdown.
6
+ *
7
+ * @element mo-navigation-bar-item
8
+ *
9
+ * @attr navigation - The navigation this item stands for.
10
+ * @attr open - Whether the group's dropdown is open.
11
+ * @attr data-current - Whether this navigation, or one nested in it, is the page being shown.
12
+ * @fires invoke - Dispatched with the destination which was invoked.
13
+ */
14
+ export declare class NavigationBarItem extends Component {
15
+ readonly invoke: EventDispatcher<INavigation>;
16
+ navigation: INavigation;
17
+ open: boolean;
18
+ current: boolean;
19
+ tabIndex: number;
20
+ private get childNavigations();
21
+ static get styles(): import("@a11d/lit").CSSResult;
22
+ protected get template(): import("lit-html").HTMLTemplateResult;
23
+ private menuItemTemplate;
24
+ }
25
+ declare global {
26
+ interface HTMLElementTagNameMap {
27
+ 'mo-navigation-bar-item': NavigationBarItem;
28
+ }
29
+ }
30
+ //# sourceMappingURL=NavigationBarItem.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"NavigationBarItem.d.ts","sourceRoot":"","sources":["../NavigationBarItem.ts"],"names":[],"mappings":"AAAA,OAAO,EAAQ,SAAS,EAA4D,MAAM,WAAW,CAAA;AACrG,OAAO,EAAsB,KAAK,WAAW,EAAE,MAAM,kBAAkB,CAAA;AACvE,OAAO,WAAW,CAAA;AAElB;;;;;;;;;GASG;AACH,qBACa,iBAAkB,SAAQ,SAAS;IACL,QAAQ,CAAC,MAAM,EAAG,eAAe,CAAC,WAAW,CAAC,CAAA;IAE5D,UAAU,EAAG,WAAW,CAAA;IACR,IAAI,UAAQ;IACe,OAAO,UAAQ;IAC7E,QAAQ,SAAI;IAErB,OAAO,KAAK,gBAAgB,GAE3B;IAED,WAAoB,MAAM,kCAwCzB;IAED,cAAuB,QAAQ,0CAe9B;IAED,OAAO,CAAC,gBAAgB;CAUxB;AAED,OAAO,CAAC,MAAM,CAAC;IACd,UAAU,qBAAqB;QAC9B,wBAAwB,EAAE,iBAAiB,CAAA;KAC3C;CACD"}