@exmg/exm-navigation 1.1.0 → 1.1.1-alpha.9
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/README.md +73 -0
- package/{src → dist}/exm-navigation-base.d.ts +37 -11
- package/{src → dist}/exm-navigation-base.js +161 -85
- package/{src → dist}/exm-navigation-drawer-base.d.ts +1 -4
- package/{src → dist}/exm-navigation-drawer-base.js +10 -7
- package/{src → dist}/exm-navigation-drawer-nav-item-base.js +12 -8
- package/{src → dist}/exm-navigation-icon-button-base.js +2 -0
- package/{src → dist}/exm-navigation-rail-base.js +2 -2
- package/{src → dist}/exm-navigation-sub-menu-base.d.ts +11 -0
- package/dist/exm-navigation-sub-menu-base.js +153 -0
- package/{src → dist}/exm-navigation-topbar-base.js +5 -5
- package/dist/index.d.ts +12 -0
- package/dist/index.js +13 -0
- package/{src → dist}/mixins/media-queries.d.ts +1 -0
- package/{src → dist}/mixins/media-queries.js +16 -4
- package/{src → dist}/styles/exm-navigation-css.d.ts +0 -1
- package/dist/styles/exm-navigation-css.js +72 -0
- package/{src → dist}/styles/exm-navigation-drawer-css.d.ts +0 -1
- package/dist/styles/exm-navigation-drawer-css.js +35 -0
- package/{src → dist}/styles/exm-navigation-drawer-nav-item-css.d.ts +0 -1
- package/dist/styles/exm-navigation-drawer-nav-item-css.js +84 -0
- package/{src → dist}/styles/exm-navigation-icon-button-css.d.ts +0 -1
- package/dist/styles/exm-navigation-icon-button-css.js +29 -0
- package/{src → dist}/styles/exm-navigation-icon-css.d.ts +0 -1
- package/dist/styles/exm-navigation-icon-css.js +22 -0
- package/{src → dist}/styles/exm-navigation-rail-css.d.ts +0 -1
- package/dist/styles/exm-navigation-rail-css.js +50 -0
- package/{src → dist}/styles/exm-navigation-rail-nav-item-css.d.ts +0 -1
- package/dist/styles/exm-navigation-rail-nav-item-css.js +94 -0
- package/{src → dist}/styles/exm-navigation-sub-menu-css.d.ts +0 -1
- package/dist/styles/exm-navigation-sub-menu-css.js +21 -0
- package/{src → dist}/styles/exm-navigation-topbar-css.d.ts +0 -1
- package/dist/styles/exm-navigation-topbar-css.js +30 -0
- package/package.json +20 -22
- package/index.d.ts +0 -12
- package/index.js +0 -13
- package/src/exm-navigation-menu-button-base.d.ts +0 -7
- package/src/exm-navigation-menu-button.d.ts +0 -9
- package/src/exm-navigation-signals.d.ts +0 -4
- package/src/exm-navigation-sub-menu-base.js +0 -88
- package/src/mediaQueries.d.ts +0 -7
- package/src/styles/exm-navigate-drawer-nav-item-css.d.ts +0 -2
- package/src/styles/exm-navigate-drawer-nav-item-css.js +0 -4
- package/src/styles/exm-navigation-css.js +0 -4
- package/src/styles/exm-navigation-drawer-css.js +0 -4
- package/src/styles/exm-navigation-drawer-nav-item-css.js +0 -4
- package/src/styles/exm-navigation-drawer-nav-item.scss +0 -36
- package/src/styles/exm-navigation-drawer.scss +0 -24
- package/src/styles/exm-navigation-icon-button-css.js +0 -4
- package/src/styles/exm-navigation-icon-button.scss +0 -19
- package/src/styles/exm-navigation-icon-css.js +0 -4
- package/src/styles/exm-navigation-icon.scss +0 -18
- package/src/styles/exm-navigation-rail-css.js +0 -4
- package/src/styles/exm-navigation-rail-nav-item-css.js +0 -4
- package/src/styles/exm-navigation-rail-nav-item.scss +0 -92
- package/src/styles/exm-navigation-rail.scss +0 -44
- package/src/styles/exm-navigation-sub-menu-css.js +0 -4
- package/src/styles/exm-navigation-sub-menu.scss +0 -34
- package/src/styles/exm-navigation-topbar-css.js +0 -4
- package/src/styles/exm-navigation-topbar.scss +0 -27
- package/src/styles/exm-navigation.scss +0 -52
- /package/{src → dist}/exm-navigation-drawer-menu-base.d.ts +0 -0
- /package/{src → dist}/exm-navigation-drawer-menu-base.js +0 -0
- /package/{src → dist}/exm-navigation-drawer-menu.d.ts +0 -0
- /package/{src → dist}/exm-navigation-drawer-menu.js +0 -0
- /package/{src → dist}/exm-navigation-drawer-nav-item-base.d.ts +0 -0
- /package/{src → dist}/exm-navigation-drawer-nav-item.d.ts +0 -0
- /package/{src → dist}/exm-navigation-drawer-nav-item.js +0 -0
- /package/{src → dist}/exm-navigation-drawer.d.ts +0 -0
- /package/{src → dist}/exm-navigation-drawer.js +0 -0
- /package/{src → dist}/exm-navigation-icon-base.d.ts +0 -0
- /package/{src → dist}/exm-navigation-icon-base.js +0 -0
- /package/{src → dist}/exm-navigation-icon-button-base.d.ts +0 -0
- /package/{src → dist}/exm-navigation-icon-button.d.ts +0 -0
- /package/{src → dist}/exm-navigation-icon-button.js +0 -0
- /package/{src → dist}/exm-navigation-icon.d.ts +0 -0
- /package/{src → dist}/exm-navigation-icon.js +0 -0
- /package/{src → dist}/exm-navigation-rail-base.d.ts +0 -0
- /package/{src → dist}/exm-navigation-rail-nav-item-base.d.ts +0 -0
- /package/{src → dist}/exm-navigation-rail-nav-item-base.js +0 -0
- /package/{src → dist}/exm-navigation-rail-nav-item.d.ts +0 -0
- /package/{src → dist}/exm-navigation-rail-nav-item.js +0 -0
- /package/{src → dist}/exm-navigation-rail.d.ts +0 -0
- /package/{src → dist}/exm-navigation-rail.js +0 -0
- /package/{src → dist}/exm-navigation-sub-menu.d.ts +0 -0
- /package/{src → dist}/exm-navigation-sub-menu.js +0 -0
- /package/{src → dist}/exm-navigation-topbar-base.d.ts +0 -0
- /package/{src → dist}/exm-navigation-topbar.d.ts +0 -0
- /package/{src → dist}/exm-navigation-topbar.js +0 -0
- /package/{src → dist}/exm-navigation.d.ts +0 -0
- /package/{src → dist}/exm-navigation.js +0 -0
- /package/{src → dist}/types.d.ts +0 -0
- /package/{src → dist}/types.js +0 -0
package/README.md
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
# `<exm-navigation>` [](https://www.npmjs.com/package/@exmg/exm-navigation)
|
|
2
|
+
|
|
3
|
+
# @exmg/exm-navigation
|
|
4
|
+
|
|
5
|
+
## Install
|
|
6
|
+
|
|
7
|
+
```bash
|
|
8
|
+
npm install @exmg/exm-navigation
|
|
9
|
+
```
|
|
10
|
+
|
|
11
|
+
## Anatomy
|
|
12
|
+
|
|
13
|
+
This library contains following component:
|
|
14
|
+
|
|
15
|
+
1. Navigation (main component and fully composed navigation component)
|
|
16
|
+
|
|
17
|
+
Conceptual usage:
|
|
18
|
+
|
|
19
|
+
```html
|
|
20
|
+
<exm-navigation .items=${menuItems} .path=${['spaces']}>
|
|
21
|
+
<!-- Slot for adding a title to the topbar. Topbar is only visible on mobile -->
|
|
22
|
+
<section slot="topbar-title">My Title</section>
|
|
23
|
+
<!-- Slot for adding actions to the right of the topbar. Topbar is only visible on mobile -->
|
|
24
|
+
<section slot="topbar-actions">Actions</section>
|
|
25
|
+
<!-- Slot for adding a logo in the top part of the rail. This is not visible on mobile -->
|
|
26
|
+
<section slot="rail-top">Rail top</section>
|
|
27
|
+
<!-- Slot for adding extra actions or other content to the bottom of the rail. This is not visible on mobile -->
|
|
28
|
+
<section slot="rail-bottom">Rail bottom</section>
|
|
29
|
+
<!-- The actual page content to display -->
|
|
30
|
+
<section class="content">${this.renderPage()}</section>
|
|
31
|
+
</exm-navigation>
|
|
32
|
+
```
|
|
33
|
+
|
|
34
|
+
Some of the components used in the navigation c an be used separately. Please check the code for implementation
|
|
35
|
+
|
|
36
|
+
## API
|
|
37
|
+
|
|
38
|
+
### Slots
|
|
39
|
+
|
|
40
|
+
| Name | Description |
|
|
41
|
+
| ---------------- | ------------------------------------------------------------------------------------------------------- |
|
|
42
|
+
| `topbar-title` | Slot for adding a title to the topbar. Topbar is only visible on mobile |
|
|
43
|
+
| `topbar-actions` | Slot for adding actions to the right of the topbar. Topbar is only visible on mobile |
|
|
44
|
+
| `rail-top` | Slot for adding a logo in the top part of the rail. This is not visible on mobile |
|
|
45
|
+
| `rail-bottom` | Slot for adding extra actions or other content to the bottom of the rail. This is not visible on mobile |
|
|
46
|
+
| `default` | The actual page content to display |
|
|
47
|
+
|
|
48
|
+
### Properties/Attributes
|
|
49
|
+
|
|
50
|
+
| Name | Type | Default | Description |
|
|
51
|
+
| -------------------- | ------------ | ------- | ------------------------------------------------------------------------------------------ |
|
|
52
|
+
| `items` | `MenuItem[]` | _[]_ | The list of menuitems to display in the navigation component |
|
|
53
|
+
| `path` | `string[]` | _[]_ | The current/initial path for the navigation |
|
|
54
|
+
| `disable-navigation` | `boolean` | _false_ | Disable navigation managed by the component. In that case you can use the event to trigger |
|
|
55
|
+
|
|
56
|
+
#### MenuItem
|
|
57
|
+
|
|
58
|
+
```typescript
|
|
59
|
+
interface MenuItem {
|
|
60
|
+
id: string;
|
|
61
|
+
label: string;
|
|
62
|
+
path?: string;
|
|
63
|
+
url?: string;
|
|
64
|
+
icon?: string;
|
|
65
|
+
items?: MenuItem[];
|
|
66
|
+
}
|
|
67
|
+
```
|
|
68
|
+
|
|
69
|
+
### Events
|
|
70
|
+
|
|
71
|
+
| Name | Detail | Description |
|
|
72
|
+
| ------------------- | ---------------- | ----------------------------------- |
|
|
73
|
+
| `navigation-change` | `['one', 'two']` | The path selected in the navigation |
|
|
@@ -2,6 +2,8 @@ import { PropertyValues } from 'lit';
|
|
|
2
2
|
import { ExmgElement } from '@exmg/lit-base/index.js';
|
|
3
3
|
import { MenuItem } from './types.js';
|
|
4
4
|
import { ExmNavigationDrawer } from './exm-navigation-drawer.js';
|
|
5
|
+
import '@material/web/icon/icon.js';
|
|
6
|
+
import '@material/web/iconbutton/icon-button.js';
|
|
5
7
|
import './exm-navigation-icon-button.js';
|
|
6
8
|
import './exm-navigation-topbar.js';
|
|
7
9
|
import './exm-navigation-rail.js';
|
|
@@ -10,40 +12,57 @@ import './exm-navigation-drawer-menu.js';
|
|
|
10
12
|
import './exm-navigation-drawer.js';
|
|
11
13
|
declare const ExmNavigationBase_base: (new (...args: any[]) => {
|
|
12
14
|
media: "mobile" | "tablet" | "desktop";
|
|
15
|
+
touch: boolean;
|
|
13
16
|
}) & typeof ExmgElement;
|
|
14
17
|
export declare class ExmNavigationBase extends ExmNavigationBase_base {
|
|
15
18
|
items: MenuItem[];
|
|
16
19
|
path: string[];
|
|
17
20
|
drawerWidth: number;
|
|
21
|
+
disableNavigate: boolean;
|
|
18
22
|
drawer?: ExmNavigationDrawer;
|
|
19
23
|
navContent?: HTMLDivElement;
|
|
20
|
-
|
|
24
|
+
/**
|
|
25
|
+
* The menu item triggered by hovering and entering submenu's
|
|
26
|
+
* Once an item with endpoint is clicked, this value should be written to activeItem
|
|
27
|
+
*/
|
|
21
28
|
selectedItem: string[];
|
|
29
|
+
/**
|
|
30
|
+
* The currently active menu item
|
|
31
|
+
*/
|
|
22
32
|
activeItem: string[];
|
|
33
|
+
/**
|
|
34
|
+
* Wether or not the rail should be visible yes or no
|
|
35
|
+
*/
|
|
23
36
|
railOpen: boolean;
|
|
37
|
+
/**
|
|
38
|
+
* Wether or not the drawer should be visible yes or no
|
|
39
|
+
*/
|
|
24
40
|
drawerOpen: boolean;
|
|
25
|
-
|
|
41
|
+
/**
|
|
42
|
+
* Object with menuitem and a bool for having that path sub items yes or no
|
|
43
|
+
*/
|
|
26
44
|
navigationHasSubmenu: Record<string, boolean>;
|
|
27
45
|
static styles: import("lit").CSSResult[];
|
|
28
|
-
menu: MenuItem[];
|
|
29
|
-
expandedItems: {
|
|
30
|
-
[k: string]: boolean;
|
|
31
|
-
};
|
|
32
|
-
unSubscribeSelected: () => void;
|
|
33
46
|
protected updated(changedProperties: PropertyValues): void;
|
|
34
47
|
protected firstUpdated(changedProperties: PropertyValues): void;
|
|
35
48
|
connectedCallback(): void;
|
|
36
49
|
/**
|
|
37
50
|
* Set the correct values when the media changes.
|
|
38
51
|
*/
|
|
39
|
-
handleMediaTypeChange
|
|
40
|
-
|
|
52
|
+
private handleMediaTypeChange;
|
|
53
|
+
private getPathEndpoint;
|
|
54
|
+
private loadPage;
|
|
55
|
+
/**
|
|
56
|
+
* Handles the drawer state. If it should be open yes or no.
|
|
57
|
+
* @param param0
|
|
58
|
+
*/
|
|
59
|
+
handleDrawerOpen({ mobileForce, tabletForce }?: Record<string, boolean>): void;
|
|
41
60
|
/**
|
|
42
61
|
* Handle Rail item click or Drawer sub menu click.
|
|
43
62
|
* If the selected menu item has children, we add the first item to the list (as per Google implementation).
|
|
44
|
-
* In this case we also do not close the drawer in non
|
|
63
|
+
* In this case we also do not close the drawer in non desktop mode, so the user is able to select a next level in the menu
|
|
45
64
|
*/
|
|
46
|
-
handleRailItemClick
|
|
65
|
+
private handleRailItemClick;
|
|
47
66
|
/**
|
|
48
67
|
* Handle the mouse enter of the rail item.
|
|
49
68
|
*/
|
|
@@ -100,6 +119,13 @@ export declare class ExmNavigationBase extends ExmNavigationBase_base {
|
|
|
100
119
|
* Render the topbar. This is displayed on mobile and contains the menu button and a slot for the title
|
|
101
120
|
*/
|
|
102
121
|
private renderTopbar;
|
|
122
|
+
/**
|
|
123
|
+
* If there is an active item, and that item has children, the width of the drawer should be set for desktop.
|
|
124
|
+
* This will push the content to the right.
|
|
125
|
+
*
|
|
126
|
+
* @returns the width of the drawer area
|
|
127
|
+
*/
|
|
128
|
+
private getDrawerWidth;
|
|
103
129
|
render(): import("lit-html").TemplateResult<1>;
|
|
104
130
|
}
|
|
105
131
|
export {};
|
|
@@ -6,6 +6,8 @@ import { styleMap } from 'lit/directives/style-map.js';
|
|
|
6
6
|
import { MediaQueries } from './mixins/media-queries.js';
|
|
7
7
|
import { classMap } from 'lit/directives/class-map.js';
|
|
8
8
|
import { style } from './styles/exm-navigation-css.js';
|
|
9
|
+
import '@material/web/icon/icon.js';
|
|
10
|
+
import '@material/web/iconbutton/icon-button.js';
|
|
9
11
|
import './exm-navigation-icon-button.js';
|
|
10
12
|
import './exm-navigation-topbar.js';
|
|
11
13
|
import './exm-navigation-rail.js';
|
|
@@ -19,16 +21,28 @@ export class ExmNavigationBase extends MediaQueries(ExmgElement) {
|
|
|
19
21
|
this.items = [];
|
|
20
22
|
this.path = ['chat'];
|
|
21
23
|
this.drawerWidth = 319;
|
|
22
|
-
this.
|
|
24
|
+
this.disableNavigate = false;
|
|
25
|
+
/**
|
|
26
|
+
* The menu item triggered by hovering and entering submenu's
|
|
27
|
+
* Once an item with endpoint is clicked, this value should be written to activeItem
|
|
28
|
+
*/
|
|
23
29
|
this.selectedItem = [];
|
|
30
|
+
/**
|
|
31
|
+
* The currently active menu item
|
|
32
|
+
*/
|
|
24
33
|
this.activeItem = [];
|
|
34
|
+
/**
|
|
35
|
+
* Wether or not the rail should be visible yes or no
|
|
36
|
+
*/
|
|
25
37
|
this.railOpen = true;
|
|
38
|
+
/**
|
|
39
|
+
* Wether or not the drawer should be visible yes or no
|
|
40
|
+
*/
|
|
26
41
|
this.drawerOpen = false;
|
|
27
|
-
|
|
42
|
+
/**
|
|
43
|
+
* Object with menuitem and a bool for having that path sub items yes or no
|
|
44
|
+
*/
|
|
28
45
|
this.navigationHasSubmenu = {};
|
|
29
|
-
this.menu = [];
|
|
30
|
-
this.expandedItems = {};
|
|
31
|
-
this.unSubscribeSelected = () => { };
|
|
32
46
|
}
|
|
33
47
|
updated(changedProperties) {
|
|
34
48
|
if (changedProperties.has('media')) {
|
|
@@ -38,7 +52,7 @@ export class ExmNavigationBase extends MediaQueries(ExmgElement) {
|
|
|
38
52
|
for (const item of this.items) {
|
|
39
53
|
this.navigationHasSubmenu[item.id] = (item.items || []).length > 0;
|
|
40
54
|
}
|
|
41
|
-
if (this.navigationHasSubmenu[this.path[0]] && this.
|
|
55
|
+
if (this.navigationHasSubmenu[this.path[0]] && this.media === 'desktop') {
|
|
42
56
|
this.drawerOpen = true;
|
|
43
57
|
}
|
|
44
58
|
}
|
|
@@ -57,88 +71,111 @@ export class ExmNavigationBase extends MediaQueries(ExmgElement) {
|
|
|
57
71
|
* Set the correct values when the media changes.
|
|
58
72
|
*/
|
|
59
73
|
handleMediaTypeChange() {
|
|
60
|
-
this.
|
|
61
|
-
this.drawerOpen = this.media === 'desktop' && this.navigationHasSubmenu[this.selectedItem[0]];
|
|
74
|
+
this.drawerOpen = this.media === 'desktop' && this.navigationHasSubmenu[this.activeItem[0]];
|
|
62
75
|
this.railOpen = this.media !== 'mobile';
|
|
63
76
|
}
|
|
77
|
+
getPathEndpoint() {
|
|
78
|
+
let items = this.items;
|
|
79
|
+
let result;
|
|
80
|
+
const checkItems = (path, last) => {
|
|
81
|
+
const item = items.find((item) => item.id === path);
|
|
82
|
+
if (last) {
|
|
83
|
+
return item === null || item === void 0 ? void 0 : item.path;
|
|
84
|
+
}
|
|
85
|
+
items = (item === null || item === void 0 ? void 0 : item.items) || [];
|
|
86
|
+
return;
|
|
87
|
+
};
|
|
88
|
+
for (let i = 0; i < this.selectedItem.length; i++) {
|
|
89
|
+
result = checkItems(this.selectedItem[i], i === this.selectedItem.length - 1);
|
|
90
|
+
}
|
|
91
|
+
return result;
|
|
92
|
+
}
|
|
64
93
|
loadPage(path) {
|
|
65
94
|
this.path = path;
|
|
66
|
-
this.
|
|
95
|
+
this.activeItem = path;
|
|
96
|
+
const endPoint = this.getPathEndpoint();
|
|
97
|
+
// If the route does not have a path, skip navigating
|
|
98
|
+
if (!endPoint) {
|
|
99
|
+
return;
|
|
100
|
+
}
|
|
101
|
+
this.fire('navigation-change', path);
|
|
102
|
+
if (!this.disableNavigate) {
|
|
103
|
+
window.history.pushState({}, '', this.getPathEndpoint());
|
|
104
|
+
window.dispatchEvent(new PopStateEvent('popstate'));
|
|
105
|
+
}
|
|
106
|
+
}
|
|
107
|
+
/**
|
|
108
|
+
* Handles the drawer state. If it should be open yes or no.
|
|
109
|
+
* @param param0
|
|
110
|
+
*/
|
|
111
|
+
handleDrawerOpen({ mobileForce, tabletForce } = {}) {
|
|
112
|
+
if (this.media === 'mobile' || this.touch) {
|
|
113
|
+
// Only triggerable by button
|
|
114
|
+
if (mobileForce || !this.navigationHasSubmenu[this.activeItem[0]]) {
|
|
115
|
+
this.drawerOpen = false;
|
|
116
|
+
}
|
|
117
|
+
}
|
|
118
|
+
if (this.media === 'tablet') {
|
|
119
|
+
if (tabletForce) {
|
|
120
|
+
this.drawerOpen = false;
|
|
121
|
+
}
|
|
122
|
+
else {
|
|
123
|
+
this.drawerOpen = this.navigationHasSubmenu[this.selectedItem[0]];
|
|
124
|
+
}
|
|
125
|
+
}
|
|
126
|
+
if (this.media === 'desktop') {
|
|
127
|
+
if (this.navigationHasSubmenu[this.activeItem[0]]) {
|
|
128
|
+
this.drawerOpen = true;
|
|
129
|
+
}
|
|
130
|
+
else {
|
|
131
|
+
this.drawerOpen = this.navigationHasSubmenu[this.selectedItem[0]];
|
|
132
|
+
}
|
|
133
|
+
}
|
|
67
134
|
}
|
|
68
135
|
/**
|
|
69
136
|
* Handle Rail item click or Drawer sub menu click.
|
|
70
137
|
* If the selected menu item has children, we add the first item to the list (as per Google implementation).
|
|
71
|
-
* In this case we also do not close the drawer in non
|
|
138
|
+
* In this case we also do not close the drawer in non desktop mode, so the user is able to select a next level in the menu
|
|
72
139
|
*/
|
|
73
140
|
handleRailItemClick({ detail }) {
|
|
74
141
|
var _a;
|
|
75
|
-
if (this.
|
|
142
|
+
if (this.activeItem[0] !== detail || this.media !== 'desktop') {
|
|
76
143
|
const items = ((_a = this.items.find((item) => item.id === detail)) === null || _a === void 0 ? void 0 : _a.items) || [];
|
|
77
|
-
if (items.length) {
|
|
144
|
+
if (items.length && !this.touch) {
|
|
78
145
|
this.selectedItem = [detail, items[0].id];
|
|
79
146
|
}
|
|
80
147
|
else {
|
|
81
148
|
this.selectedItem = [detail];
|
|
82
149
|
}
|
|
83
|
-
// copy the selected item to the active item
|
|
84
|
-
this.activeItem = this.selectedItem;
|
|
85
|
-
/**
|
|
86
|
-
* If persistent menu close the drawer when a item is clicked and does not has children items
|
|
87
|
-
*/
|
|
88
|
-
if (this.persistent) {
|
|
89
|
-
this.drawerOpen = items.length > 0 || this.navigationHasSubmenu[detail];
|
|
90
|
-
}
|
|
91
|
-
else if (items.length === 0) {
|
|
92
|
-
this.drawerOpen = false;
|
|
93
|
-
}
|
|
94
150
|
this.loadPage(this.selectedItem);
|
|
151
|
+
this.handleDrawerOpen();
|
|
95
152
|
}
|
|
96
153
|
}
|
|
97
154
|
/**
|
|
98
155
|
* Handle the mouse enter of the rail item.
|
|
99
156
|
*/
|
|
100
157
|
handleRailItemMouseEnter({ detail }) {
|
|
101
|
-
if (this.
|
|
102
|
-
|
|
103
|
-
if (detail !== this.selectedItem[0]) {
|
|
104
|
-
this.activeItem = [detail];
|
|
105
|
-
return;
|
|
106
|
-
}
|
|
107
|
-
}
|
|
108
|
-
else if (this.navigationHasSubmenu[this.selectedItem[0]] && this.persistent) {
|
|
109
|
-
this.activeItem = this.selectedItem;
|
|
110
|
-
this.drawerOpen = true;
|
|
111
|
-
}
|
|
112
|
-
else {
|
|
113
|
-
this.activeItem = this.selectedItem;
|
|
114
|
-
this.drawerOpen = false;
|
|
158
|
+
if (this.touch) {
|
|
159
|
+
return;
|
|
115
160
|
}
|
|
116
|
-
this.
|
|
161
|
+
this.selectedItem = [detail];
|
|
162
|
+
this.handleDrawerOpen();
|
|
117
163
|
}
|
|
118
164
|
/**
|
|
119
165
|
* Handle the mouse leave of the rail item.
|
|
120
166
|
* If the item has no submenu and the current selected item has no submenu, it is safe to close the drawer
|
|
121
167
|
*/
|
|
122
|
-
handleRailItemMouseLeave({
|
|
123
|
-
if (!this.navigationHasSubmenu[detail] && !this.navigationHasSubmenu[this.selectedItem[0]]) {
|
|
124
|
-
this.drawerOpen = false;
|
|
125
|
-
}
|
|
126
|
-
if (!this.persistent && !this.navigationHasSubmenu[detail]) {
|
|
127
|
-
this.drawerOpen = false;
|
|
128
|
-
}
|
|
129
|
-
}
|
|
168
|
+
handleRailItemMouseLeave() { }
|
|
130
169
|
/**
|
|
131
170
|
* Handle drawer mouse leave. Should close the drawer
|
|
132
171
|
*/
|
|
133
172
|
handleDrawerMouseLeave() {
|
|
134
|
-
if (!this.navigationHasSubmenu[this.selectedItem[0]] || !this.persistent) {
|
|
135
|
-
this.drawerOpen = false;
|
|
136
|
-
}
|
|
137
173
|
/**
|
|
138
174
|
* On mouse leave the drawer we want to set the active item to the selected item.
|
|
139
175
|
* If not, it will show the active item on every hover and will make navigating in the selected item impossible
|
|
140
176
|
*/
|
|
141
|
-
this.
|
|
177
|
+
this.selectedItem = this.activeItem;
|
|
178
|
+
this.handleDrawerOpen({ tabletForce: true });
|
|
142
179
|
}
|
|
143
180
|
/**
|
|
144
181
|
* Handle the click on a sub menu item
|
|
@@ -147,10 +184,13 @@ export class ExmNavigationBase extends MediaQueries(ExmgElement) {
|
|
|
147
184
|
*/
|
|
148
185
|
handleSubMenuClick({ detail }) {
|
|
149
186
|
this.selectedItem = detail;
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
187
|
+
const endPoint = this.getPathEndpoint();
|
|
188
|
+
let mobileForce = false;
|
|
189
|
+
if (endPoint) {
|
|
190
|
+
this.loadPage(this.selectedItem);
|
|
191
|
+
mobileForce = true;
|
|
153
192
|
}
|
|
193
|
+
this.handleDrawerOpen({ mobileForce, tabletForce: this.touch && !!endPoint });
|
|
154
194
|
}
|
|
155
195
|
/**
|
|
156
196
|
* Handle the topbar menu click.
|
|
@@ -164,7 +204,7 @@ export class ExmNavigationBase extends MediaQueries(ExmgElement) {
|
|
|
164
204
|
* This should reset the active item, so the root-level menu gets triggered
|
|
165
205
|
*/
|
|
166
206
|
handleDrawerBackClick() {
|
|
167
|
-
this.
|
|
207
|
+
this.selectedItem = [];
|
|
168
208
|
}
|
|
169
209
|
/**
|
|
170
210
|
* Check if the passed paths last item has children yes or no
|
|
@@ -185,11 +225,10 @@ export class ExmNavigationBase extends MediaQueries(ExmgElement) {
|
|
|
185
225
|
renderDrawerMenuButton() {
|
|
186
226
|
return !this.railOpen
|
|
187
227
|
? html `
|
|
188
|
-
<section>
|
|
189
|
-
<
|
|
190
|
-
icon
|
|
191
|
-
|
|
192
|
-
></exm-navigation-icon-button>
|
|
228
|
+
<section class="drawer-menu-button">
|
|
229
|
+
<md-icon-button @click=${this.handleTopbarMenuClick}>
|
|
230
|
+
<md-icon>${this.drawerOpen ? 'menu_open' : 'menu'}</md-icon>
|
|
231
|
+
</md-icon-button>
|
|
193
232
|
</section>
|
|
194
233
|
`
|
|
195
234
|
: nothing;
|
|
@@ -199,34 +238,60 @@ export class ExmNavigationBase extends MediaQueries(ExmgElement) {
|
|
|
199
238
|
* If more levels deep, show the back button
|
|
200
239
|
*/
|
|
201
240
|
renderStartMenu() {
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
241
|
+
if (this.railOpen) {
|
|
242
|
+
return nothing;
|
|
243
|
+
}
|
|
244
|
+
return this.selectedItem.length === 0 ||
|
|
245
|
+
(this.selectedItem.length === 1 && !this.currentSelectedHasChildren(this.selectedItem))
|
|
205
246
|
? html `<exm-navigation-drawer-menu
|
|
206
247
|
.items=${this.items}
|
|
207
248
|
.path=${this.activeItem}
|
|
208
249
|
@drawer-menu-item-click=${this.handleRailItemClick}
|
|
209
250
|
></exm-navigation-drawer-menu>`
|
|
210
|
-
:
|
|
211
|
-
|
|
212
|
-
<
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
`
|
|
220
|
-
: nothing;
|
|
251
|
+
: html `
|
|
252
|
+
<section class="drawer-back-button">
|
|
253
|
+
<exm-navigation-icon-button
|
|
254
|
+
icon="arrow_back"
|
|
255
|
+
label="Main menu"
|
|
256
|
+
@navigation-icon-button-click=${this.handleDrawerBackClick}
|
|
257
|
+
></exm-navigation-icon-button>
|
|
258
|
+
</section>
|
|
259
|
+
`;
|
|
221
260
|
}
|
|
222
261
|
/**
|
|
223
262
|
* return the sub menus. More then 1 level deep
|
|
224
263
|
*/
|
|
225
264
|
renderDrawerSubMenu() {
|
|
265
|
+
/**
|
|
266
|
+
* When the selected item is empty we do not display the submenu on mobile
|
|
267
|
+
*/
|
|
268
|
+
if (this.selectedItem.length === 0 && this.media === 'mobile') {
|
|
269
|
+
return nothing;
|
|
270
|
+
}
|
|
271
|
+
/**
|
|
272
|
+
* Do we have all items of the selectedItem available in the active Item
|
|
273
|
+
*/
|
|
274
|
+
const selectedInActive = this.selectedItem.reduce((_, item, index) => {
|
|
275
|
+
if (item === this.activeItem[index]) {
|
|
276
|
+
return true;
|
|
277
|
+
}
|
|
278
|
+
return false;
|
|
279
|
+
}, false);
|
|
280
|
+
/**
|
|
281
|
+
* Determine the data to use for the submenu. This is needed to show the correct selected items in the submenu of the drawer
|
|
282
|
+
* If all selected Items ar in the active item, show the active item
|
|
283
|
+
* If the selected item haas no children, but the drawer is open, show the active item
|
|
284
|
+
* In all the other cases we use the selected item
|
|
285
|
+
*/
|
|
286
|
+
const selected = selectedInActive || (!this.navigationHasSubmenu[this.selectedItem[0]] && this.drawerOpen)
|
|
287
|
+
? this.activeItem
|
|
288
|
+
: this.selectedItem;
|
|
226
289
|
return html `
|
|
227
290
|
<exm-navigation-sub-menu
|
|
228
291
|
.items=${this.items}
|
|
229
|
-
.path=${
|
|
292
|
+
.path=${selected}
|
|
293
|
+
?has-back-button=${!this.railOpen &&
|
|
294
|
+
(selected.length > 1 || (selected.length > 0 && this.currentSelectedHasChildren(selected)))}
|
|
230
295
|
@sub-menu-item-click=${this.handleSubMenuClick}
|
|
231
296
|
></exm-navigation-sub-menu>
|
|
232
297
|
`;
|
|
@@ -237,11 +302,14 @@ export class ExmNavigationBase extends MediaQueries(ExmgElement) {
|
|
|
237
302
|
renderRail() {
|
|
238
303
|
return html `<exm-navigation-rail
|
|
239
304
|
.items=${this.items}
|
|
240
|
-
.selected=${this.
|
|
305
|
+
.selected=${this.activeItem}
|
|
241
306
|
@rail-item-click=${this.handleRailItemClick}
|
|
242
307
|
@rail-item-mouseenter=${this.handleRailItemMouseEnter}
|
|
243
308
|
@rail-item-mouseleave=${this.handleRailItemMouseLeave}
|
|
244
|
-
|
|
309
|
+
>
|
|
310
|
+
<slot name="rail-top" slot="rail-top"></slot>
|
|
311
|
+
<slot name="rail-bottom" slot="rail-bottom"></slot>
|
|
312
|
+
</exm-navigation-rail>`;
|
|
245
313
|
}
|
|
246
314
|
/**
|
|
247
315
|
* Render the topbar. This is displayed on mobile and contains the menu button and a slot for the title
|
|
@@ -249,12 +317,24 @@ export class ExmNavigationBase extends MediaQueries(ExmgElement) {
|
|
|
249
317
|
renderTopbar() {
|
|
250
318
|
return html `<exm-navigation-topbar ?drawer-open=${this.drawerOpen} @topbar-menu-click=${this.handleTopbarMenuClick}>
|
|
251
319
|
<slot name="topbar-title" slot="topbar-title"></slot>
|
|
320
|
+
<slot name="topbar-actions" slot="topbar-actions"></slot>
|
|
252
321
|
</exm-navigation-topbar>`;
|
|
253
322
|
}
|
|
323
|
+
/**
|
|
324
|
+
* If there is an active item, and that item has children, the width of the drawer should be set for desktop.
|
|
325
|
+
* This will push the content to the right.
|
|
326
|
+
*
|
|
327
|
+
* @returns the width of the drawer area
|
|
328
|
+
*/
|
|
329
|
+
getDrawerWidth() {
|
|
330
|
+
if (this.media === 'desktop' && this.activeItem.length > 0 && this.navigationHasSubmenu[this.activeItem[0]]) {
|
|
331
|
+
return this.drawerWidth;
|
|
332
|
+
}
|
|
333
|
+
return 0;
|
|
334
|
+
}
|
|
254
335
|
render() {
|
|
255
|
-
var _a;
|
|
256
336
|
const containerStyle = {
|
|
257
|
-
'--exm-drawer-width': `${
|
|
337
|
+
'--exm-drawer-width': `${this.getDrawerWidth()}px`,
|
|
258
338
|
};
|
|
259
339
|
const containerClass = { 'show-topbar': !this.railOpen };
|
|
260
340
|
return html `
|
|
@@ -271,7 +351,6 @@ export class ExmNavigationBase extends MediaQueries(ExmgElement) {
|
|
|
271
351
|
<slot></slot>
|
|
272
352
|
</section>
|
|
273
353
|
</section>
|
|
274
|
-
<slot></slot>
|
|
275
354
|
`;
|
|
276
355
|
}
|
|
277
356
|
}
|
|
@@ -285,15 +364,15 @@ __decorate([
|
|
|
285
364
|
__decorate([
|
|
286
365
|
property({ type: Number, attribute: 'drawer-width' })
|
|
287
366
|
], ExmNavigationBase.prototype, "drawerWidth", void 0);
|
|
367
|
+
__decorate([
|
|
368
|
+
property({ type: Boolean, attribute: 'disable-navigation' })
|
|
369
|
+
], ExmNavigationBase.prototype, "disableNavigate", void 0);
|
|
288
370
|
__decorate([
|
|
289
371
|
query('exm-navigation-drawer')
|
|
290
372
|
], ExmNavigationBase.prototype, "drawer", void 0);
|
|
291
373
|
__decorate([
|
|
292
374
|
query('#navigation-container')
|
|
293
375
|
], ExmNavigationBase.prototype, "navContent", void 0);
|
|
294
|
-
__decorate([
|
|
295
|
-
state()
|
|
296
|
-
], ExmNavigationBase.prototype, "persistent", void 0);
|
|
297
376
|
__decorate([
|
|
298
377
|
state()
|
|
299
378
|
], ExmNavigationBase.prototype, "selectedItem", void 0);
|
|
@@ -306,9 +385,6 @@ __decorate([
|
|
|
306
385
|
__decorate([
|
|
307
386
|
state()
|
|
308
387
|
], ExmNavigationBase.prototype, "drawerOpen", void 0);
|
|
309
|
-
__decorate([
|
|
310
|
-
state()
|
|
311
|
-
], ExmNavigationBase.prototype, "drawerHover", void 0);
|
|
312
388
|
__decorate([
|
|
313
389
|
state()
|
|
314
390
|
], ExmNavigationBase.prototype, "navigationHasSubmenu", void 0);
|
|
@@ -1,14 +1,11 @@
|
|
|
1
|
-
import { Drawer } from '@material/mwc-drawer';
|
|
2
1
|
import { ExmgElement } from '@exmg/lit-base';
|
|
3
|
-
import '@material/mwc-drawer';
|
|
4
2
|
export declare class ExmNavigationDrawerBase extends ExmgElement {
|
|
5
3
|
open: boolean;
|
|
6
4
|
persistent: boolean;
|
|
7
|
-
drawer?:
|
|
5
|
+
drawer?: HTMLDivElement;
|
|
8
6
|
static styles: import("lit").CSSResult[];
|
|
9
7
|
private handleMouseEnter;
|
|
10
8
|
private handleMouseLeave;
|
|
11
|
-
private handleDrawerClose;
|
|
12
9
|
protected firstUpdated(): Promise<void>;
|
|
13
10
|
render(): import("lit-html").TemplateResult<1>;
|
|
14
11
|
}
|
|
@@ -3,7 +3,7 @@ import { html } from 'lit';
|
|
|
3
3
|
import { property, query } from 'lit/decorators.js';
|
|
4
4
|
import { ExmgElement } from '@exmg/lit-base';
|
|
5
5
|
import { style } from './styles/exm-navigation-drawer-css.js';
|
|
6
|
-
import '
|
|
6
|
+
import { classMap } from 'lit/directives/class-map.js';
|
|
7
7
|
export class ExmNavigationDrawerBase extends ExmgElement {
|
|
8
8
|
constructor() {
|
|
9
9
|
super(...arguments);
|
|
@@ -16,9 +16,6 @@ export class ExmNavigationDrawerBase extends ExmgElement {
|
|
|
16
16
|
handleMouseLeave() {
|
|
17
17
|
this.fire('drawer-mouseleave');
|
|
18
18
|
}
|
|
19
|
-
handleDrawerClose() {
|
|
20
|
-
this.fire('drawer-mouseleave');
|
|
21
|
-
}
|
|
22
19
|
async firstUpdated() {
|
|
23
20
|
var _a;
|
|
24
21
|
await this.updateComplete;
|
|
@@ -30,10 +27,16 @@ export class ExmNavigationDrawerBase extends ExmgElement {
|
|
|
30
27
|
asideElement.addEventListener('mouseleave', this.handleMouseLeave.bind(this));
|
|
31
28
|
}
|
|
32
29
|
}
|
|
33
|
-
this.addEventListener('drawer-close', this.handleDrawerClose.bind(this));
|
|
34
30
|
}
|
|
35
31
|
render() {
|
|
36
|
-
|
|
32
|
+
const classNames = { open: this.open };
|
|
33
|
+
return html `<aside
|
|
34
|
+
class="${classMap(classNames)}"
|
|
35
|
+
@mouseenter=${this.handleMouseEnter}
|
|
36
|
+
@mouseleave=${this.handleMouseLeave}
|
|
37
|
+
>
|
|
38
|
+
<slot></slot>
|
|
39
|
+
</aside> `;
|
|
37
40
|
}
|
|
38
41
|
}
|
|
39
42
|
ExmNavigationDrawerBase.styles = [style];
|
|
@@ -44,6 +47,6 @@ __decorate([
|
|
|
44
47
|
property({ type: Boolean })
|
|
45
48
|
], ExmNavigationDrawerBase.prototype, "persistent", void 0);
|
|
46
49
|
__decorate([
|
|
47
|
-
query('
|
|
50
|
+
query('aside')
|
|
48
51
|
], ExmNavigationDrawerBase.prototype, "drawer", void 0);
|
|
49
52
|
//# sourceMappingURL=exm-navigation-drawer-base.js.map
|
|
@@ -6,6 +6,7 @@ import '@material/web/focus/md-focus-ring.js';
|
|
|
6
6
|
import './exm-navigation-icon.js';
|
|
7
7
|
import '@material/web/list/list.js';
|
|
8
8
|
import '@material/web/list/list-item.js';
|
|
9
|
+
import { classMap } from 'lit/directives/class-map.js';
|
|
9
10
|
export class ExmNavigationDrawerNavItemBase extends LitElement {
|
|
10
11
|
constructor() {
|
|
11
12
|
super(...arguments);
|
|
@@ -15,15 +16,18 @@ export class ExmNavigationDrawerNavItemBase extends LitElement {
|
|
|
15
16
|
this.submenuIcon = 'arrow_forward';
|
|
16
17
|
}
|
|
17
18
|
render() {
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
19
|
+
const classList = { selected: this.selected, 'has-sub-menu': this.hasSubmenu, 'has-icon': !!this.icon };
|
|
20
|
+
return html `
|
|
21
|
+
<button class="${classMap(classList)}">
|
|
22
|
+
${this.icon ? html `<exm-navigation-icon class="item-icon" icon=${this.icon}></exm-navigation-icon>` : nothing}
|
|
23
|
+
<span class="label"><slot></slot></span>
|
|
24
|
+
${this.hasSubmenu
|
|
25
|
+
? html `<exm-navigation-icon class="has-submenu" icon=${this.submenuIcon}></exm-navigation-icon>`
|
|
21
26
|
: nothing}
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
</md-list-item>`;
|
|
27
|
+
<md-ripple part="ripple"></md-ripple>
|
|
28
|
+
<md-focus-ring part="focus-ring" inward></md-focus-ring>
|
|
29
|
+
</button>
|
|
30
|
+
`;
|
|
27
31
|
}
|
|
28
32
|
}
|
|
29
33
|
ExmNavigationDrawerNavItemBase.styles = [style];
|
|
@@ -20,6 +20,8 @@ export class ExmNavigationIconButtonBase extends ExmgElement {
|
|
|
20
20
|
<button class="icon-button ${classMap(buttonClass)}" @click=${this.handleMenuButtonClick}>
|
|
21
21
|
<exm-navigation-icon icon=${this.icon}></exm-navigation-icon>
|
|
22
22
|
${this.label ? html ` <span class="label">${this.label}</span>` : nothing}
|
|
23
|
+
<md-ripple part="ripple"></md-ripple>
|
|
24
|
+
<md-focus-ring part="focus-ring" inward></md-focus-ring>
|
|
23
25
|
</button>
|
|
24
26
|
`;
|
|
25
27
|
}
|