@internetarchive/ia-topnav 1.1.19 → 1.1.21-alpha
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/.eslintrc +16 -16
- package/.storybook/.babelrc +15 -15
- package/.storybook/addons.js +7 -7
- package/.storybook/config.js +11 -11
- package/.storybook/webpack.config.js +5 -5
- package/LICENSE +661 -661
- package/README.md +145 -145
- package/demo.html +41 -41
- package/index.d.ts +105 -105
- package/index.js +3 -3
- package/package.json +65 -65
- package/src/assets/img/hamburger.js +36 -36
- package/src/assets/img/ia-icon.js +33 -33
- package/src/assets/img/icon-audio.js +23 -23
- package/src/assets/img/icon-close.js +16 -16
- package/src/assets/img/icon-donate.js +15 -15
- package/src/assets/img/icon-ellipses.js +15 -15
- package/src/assets/img/icon-ia-logo.js +24 -24
- package/src/assets/img/icon-images.js +15 -15
- package/src/assets/img/icon-search.js +15 -15
- package/src/assets/img/icon-software.js +15 -15
- package/src/assets/img/icon-texts.js +15 -15
- package/src/assets/img/icon-upload.js +15 -15
- package/src/assets/img/icon-user.js +15 -15
- package/src/assets/img/icon-video.js +15 -15
- package/src/assets/img/icon-web.js +15 -15
- package/src/assets/img/icon.js +18 -18
- package/src/assets/img/icons.js +29 -29
- package/src/assets/img/user.js +38 -38
- package/src/assets/img/wordmark-stacked.js +13 -13
- package/src/data/menus.js +603 -603
- package/src/desktop-subnav.js +45 -45
- package/src/dropdown-menu.js +98 -98
- package/src/ia-topnav.js +285 -285
- package/src/lib/formatUrl.js +1 -1
- package/src/lib/location-handler.js +5 -5
- package/src/lib/query-handler.js +7 -7
- package/src/lib/toSentenceCase.js +8 -8
- package/src/login-button.js +79 -79
- package/src/media-button.js +113 -113
- package/src/media-menu.js +133 -133
- package/src/media-slider.js +104 -104
- package/src/media-subnav.js +112 -112
- package/src/more-slider.js +33 -33
- package/src/nav-search.js +124 -124
- package/src/primary-nav.js +211 -211
- package/src/save-page-form.js +59 -59
- package/src/search-menu.js +115 -115
- package/src/signed-out-dropdown.js +10 -10
- package/src/styles/base.js +48 -48
- package/src/styles/desktop-subnav.js +37 -37
- package/src/styles/dropdown-menu.js +143 -143
- package/src/styles/ia-topnav.js +88 -88
- package/src/styles/login-button.js +70 -70
- package/src/styles/media-button.js +153 -153
- package/src/styles/media-menu.js +70 -70
- package/src/styles/media-slider.js +81 -81
- package/src/styles/media-subnav.js +156 -156
- package/src/styles/more-slider.js +15 -15
- package/src/styles/nav-search.js +134 -130
- package/src/styles/primary-nav.js +254 -254
- package/src/styles/save-page-form.js +53 -52
- package/src/styles/search-menu.js +104 -103
- package/src/styles/signed-out-dropdown.js +31 -31
- package/src/styles/user-menu.js +31 -31
- package/src/styles/wayback-search.js +48 -48
- package/src/styles/wayback-slider.js +30 -30
- package/src/tracked-element.js +27 -27
- package/src/user-menu.js +42 -42
- package/src/wayback-search.js +18 -18
- package/src/wayback-slider.js +88 -88
- package/stories/topnav-element.stories.js +7 -7
- package/test/assets/img/hamburger.test.js +15 -15
- package/test/assets/img/user.test.js +15 -15
- package/test/data/menus.test.js +19 -19
- package/test/dropdown-menu.test.js +25 -25
- package/test/ia-icon.test.js +13 -13
- package/test/ia-topnav.test.js +273 -273
- package/test/login-button.test.js +15 -15
- package/test/media-button.test.js +19 -19
- package/test/media-menu.test.js +40 -40
- package/test/media-slider.test.js +57 -57
- package/test/more-slider.test.js +13 -13
- package/test/nav-search.test.js +61 -61
- package/test/primary-nav.test.js +82 -82
- package/test/save-page-form.test.js +35 -35
- package/test/search-menu.test.js +49 -49
- package/test/user-menu.test.js +33 -33
- package/test/wayback-slider.test.js +80 -80
package/src/nav-search.js
CHANGED
|
@@ -1,124 +1,124 @@
|
|
|
1
|
-
import { nothing, html } from 'https://offshoot.ux.archive.org/lit.js';
|
|
2
|
-
|
|
3
|
-
import TrackedElement from './tracked-element.js';
|
|
4
|
-
import navSearchCSS from './styles/nav-search.js';
|
|
5
|
-
import icons from './assets/img/icons.js';
|
|
6
|
-
import formatUrl from './lib/formatUrl.js';
|
|
7
|
-
|
|
8
|
-
class NavSearch extends TrackedElement {
|
|
9
|
-
static get styles() {
|
|
10
|
-
return navSearchCSS;
|
|
11
|
-
}
|
|
12
|
-
|
|
13
|
-
static get properties() {
|
|
14
|
-
return {
|
|
15
|
-
baseHost: { type: String },
|
|
16
|
-
config: { type: Object },
|
|
17
|
-
locationHandler: { type: Object },
|
|
18
|
-
open: { type: Boolean },
|
|
19
|
-
openMenu: { type: String },
|
|
20
|
-
searchIn: { type: String },
|
|
21
|
-
searchQuery: { type: String },
|
|
22
|
-
};
|
|
23
|
-
}
|
|
24
|
-
|
|
25
|
-
constructor() {
|
|
26
|
-
super();
|
|
27
|
-
this.config = {};
|
|
28
|
-
this.locationHandler = () => {};
|
|
29
|
-
this.open = false;
|
|
30
|
-
this.openMenu = '';
|
|
31
|
-
this.searchIn = '';
|
|
32
|
-
this.inSearchBeta = false;
|
|
33
|
-
|
|
34
|
-
this.initSearchBetaOptIn();
|
|
35
|
-
}
|
|
36
|
-
|
|
37
|
-
updated() {
|
|
38
|
-
if (this.open) {
|
|
39
|
-
this.shadowRoot.querySelector('[name=query]').focus();
|
|
40
|
-
}
|
|
41
|
-
return true;
|
|
42
|
-
}
|
|
43
|
-
|
|
44
|
-
initSearchBetaOptIn() {
|
|
45
|
-
this.inSearchBeta = !!window.localStorage?.getItem('SearchBeta-opt-in');
|
|
46
|
-
}
|
|
47
|
-
|
|
48
|
-
search(e) {
|
|
49
|
-
const query = this.shadowRoot.querySelector('[name=query]').value;
|
|
50
|
-
|
|
51
|
-
if (!query) {
|
|
52
|
-
e.preventDefault();
|
|
53
|
-
return false;
|
|
54
|
-
}
|
|
55
|
-
|
|
56
|
-
// TV search points to a detail page with a q param instead
|
|
57
|
-
if (this.searchIn === 'TV') {
|
|
58
|
-
this.locationHandler(formatUrl(`/details/tv?q=${query}`, this.baseHost));
|
|
59
|
-
e.preventDefault();
|
|
60
|
-
return false;
|
|
61
|
-
}
|
|
62
|
-
|
|
63
|
-
this.trackSubmit(e);
|
|
64
|
-
return true;
|
|
65
|
-
}
|
|
66
|
-
|
|
67
|
-
toggleSearchMenu() {
|
|
68
|
-
if (this.openMenu === 'search') {
|
|
69
|
-
return;
|
|
70
|
-
}
|
|
71
|
-
this.dispatchEvent(new CustomEvent('menuToggled', {
|
|
72
|
-
detail: {
|
|
73
|
-
menuName: 'search'
|
|
74
|
-
},
|
|
75
|
-
composed: true,
|
|
76
|
-
bubbles: true,
|
|
77
|
-
}));
|
|
78
|
-
}
|
|
79
|
-
|
|
80
|
-
get searchInsideInput() {
|
|
81
|
-
return this.searchIn ? html`<input type='hidden' name='sin' value='${this.searchIn}' />` : nothing;
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
get searchEndpoint() {
|
|
85
|
-
return this.inSearchBeta ? '/search' : '/search.php';
|
|
86
|
-
}
|
|
87
|
-
|
|
88
|
-
render() {
|
|
89
|
-
const searchMenuClass = this.open ? 'flex' : 'search-inactive';
|
|
90
|
-
|
|
91
|
-
return html`
|
|
92
|
-
<div class="search-activated fade-in ${searchMenuClass}">
|
|
93
|
-
<form
|
|
94
|
-
id="nav-search"
|
|
95
|
-
class="highlight"
|
|
96
|
-
action=${formatUrl(this.searchEndpoint, this.baseHost)}
|
|
97
|
-
method="get"
|
|
98
|
-
@submit=${this.search}
|
|
99
|
-
data-event-submit-tracking="${this.config.eventCategory}|NavSearchSubmit"
|
|
100
|
-
>
|
|
101
|
-
<input
|
|
102
|
-
type="text"
|
|
103
|
-
name="query"
|
|
104
|
-
class="search-field"
|
|
105
|
-
placeholder="Search"
|
|
106
|
-
autocomplete="off"
|
|
107
|
-
@focus=${this.toggleSearchMenu}
|
|
108
|
-
value=${this.searchQuery || ''}
|
|
109
|
-
/>
|
|
110
|
-
${this.searchInsideInput}
|
|
111
|
-
<button
|
|
112
|
-
type="submit"
|
|
113
|
-
class="search"
|
|
114
|
-
data-event-click-tracking="${this.config.eventCategory}|NavSearchClose"
|
|
115
|
-
>
|
|
116
|
-
${icons.search}
|
|
117
|
-
</button>
|
|
118
|
-
</form>
|
|
119
|
-
</div>
|
|
120
|
-
`;
|
|
121
|
-
}
|
|
122
|
-
}
|
|
123
|
-
|
|
124
|
-
customElements.define('nav-search', NavSearch);
|
|
1
|
+
import { nothing, html } from 'https://offshoot.ux.archive.org/lit.js';
|
|
2
|
+
|
|
3
|
+
import TrackedElement from './tracked-element.js';
|
|
4
|
+
import navSearchCSS from './styles/nav-search.js';
|
|
5
|
+
import icons from './assets/img/icons.js';
|
|
6
|
+
import formatUrl from './lib/formatUrl.js';
|
|
7
|
+
|
|
8
|
+
class NavSearch extends TrackedElement {
|
|
9
|
+
static get styles() {
|
|
10
|
+
return navSearchCSS;
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
static get properties() {
|
|
14
|
+
return {
|
|
15
|
+
baseHost: { type: String },
|
|
16
|
+
config: { type: Object },
|
|
17
|
+
locationHandler: { type: Object },
|
|
18
|
+
open: { type: Boolean },
|
|
19
|
+
openMenu: { type: String },
|
|
20
|
+
searchIn: { type: String },
|
|
21
|
+
searchQuery: { type: String },
|
|
22
|
+
};
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
constructor() {
|
|
26
|
+
super();
|
|
27
|
+
this.config = {};
|
|
28
|
+
this.locationHandler = () => {};
|
|
29
|
+
this.open = false;
|
|
30
|
+
this.openMenu = '';
|
|
31
|
+
this.searchIn = '';
|
|
32
|
+
this.inSearchBeta = false;
|
|
33
|
+
|
|
34
|
+
this.initSearchBetaOptIn();
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
updated() {
|
|
38
|
+
if (this.open) {
|
|
39
|
+
this.shadowRoot.querySelector('[name=query]').focus();
|
|
40
|
+
}
|
|
41
|
+
return true;
|
|
42
|
+
}
|
|
43
|
+
|
|
44
|
+
initSearchBetaOptIn() {
|
|
45
|
+
this.inSearchBeta = !!window.localStorage?.getItem('SearchBeta-opt-in');
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
search(e) {
|
|
49
|
+
const query = this.shadowRoot.querySelector('[name=query]').value;
|
|
50
|
+
|
|
51
|
+
if (!query) {
|
|
52
|
+
e.preventDefault();
|
|
53
|
+
return false;
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
// TV search points to a detail page with a q param instead
|
|
57
|
+
if (this.searchIn === 'TV') {
|
|
58
|
+
this.locationHandler(formatUrl(`/details/tv?q=${query}`, this.baseHost));
|
|
59
|
+
e.preventDefault();
|
|
60
|
+
return false;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
this.trackSubmit(e);
|
|
64
|
+
return true;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
toggleSearchMenu() {
|
|
68
|
+
if (this.openMenu === 'search') {
|
|
69
|
+
return;
|
|
70
|
+
}
|
|
71
|
+
this.dispatchEvent(new CustomEvent('menuToggled', {
|
|
72
|
+
detail: {
|
|
73
|
+
menuName: 'search'
|
|
74
|
+
},
|
|
75
|
+
composed: true,
|
|
76
|
+
bubbles: true,
|
|
77
|
+
}));
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
get searchInsideInput() {
|
|
81
|
+
return this.searchIn ? html`<input type='hidden' name='sin' value='${this.searchIn}' />` : nothing;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
get searchEndpoint() {
|
|
85
|
+
return this.inSearchBeta ? '/search' : '/search.php';
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
render() {
|
|
89
|
+
const searchMenuClass = this.open ? 'flex' : 'search-inactive';
|
|
90
|
+
|
|
91
|
+
return html`
|
|
92
|
+
<div class="search-activated fade-in ${searchMenuClass}">
|
|
93
|
+
<form
|
|
94
|
+
id="nav-search"
|
|
95
|
+
class="highlight"
|
|
96
|
+
action=${formatUrl(this.searchEndpoint, this.baseHost)}
|
|
97
|
+
method="get"
|
|
98
|
+
@submit=${this.search}
|
|
99
|
+
data-event-submit-tracking="${this.config.eventCategory}|NavSearchSubmit"
|
|
100
|
+
>
|
|
101
|
+
<input
|
|
102
|
+
type="text"
|
|
103
|
+
name="query"
|
|
104
|
+
class="search-field"
|
|
105
|
+
placeholder="Search"
|
|
106
|
+
autocomplete="off"
|
|
107
|
+
@focus=${this.toggleSearchMenu}
|
|
108
|
+
value=${this.searchQuery || ''}
|
|
109
|
+
/>
|
|
110
|
+
${this.searchInsideInput}
|
|
111
|
+
<button
|
|
112
|
+
type="submit"
|
|
113
|
+
class="search"
|
|
114
|
+
data-event-click-tracking="${this.config.eventCategory}|NavSearchClose"
|
|
115
|
+
>
|
|
116
|
+
${icons.search}
|
|
117
|
+
</button>
|
|
118
|
+
</form>
|
|
119
|
+
</div>
|
|
120
|
+
`;
|
|
121
|
+
}
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
customElements.define('nav-search', NavSearch);
|
package/src/primary-nav.js
CHANGED
|
@@ -1,211 +1,211 @@
|
|
|
1
|
-
import { html, nothing } from 'https://offshoot.ux.archive.org/lit.js';
|
|
2
|
-
import TrackedElement from './tracked-element.js';
|
|
3
|
-
import icons from './assets/img/icons.js';
|
|
4
|
-
import './assets/img/hamburger.js';
|
|
5
|
-
import './login-button.js';
|
|
6
|
-
import './nav-search.js';
|
|
7
|
-
import './media-menu.js';
|
|
8
|
-
import logoWordmarkStacked from './assets/img/wordmark-stacked.js';
|
|
9
|
-
import primaryNavCSS from './styles/primary-nav.js';
|
|
10
|
-
import locationHandler from './lib/location-handler.js';
|
|
11
|
-
import formatUrl from './lib/formatUrl.js';
|
|
12
|
-
|
|
13
|
-
class PrimaryNav extends TrackedElement {
|
|
14
|
-
static get styles() {
|
|
15
|
-
return primaryNavCSS;
|
|
16
|
-
}
|
|
17
|
-
|
|
18
|
-
static get properties() {
|
|
19
|
-
return {
|
|
20
|
-
mediaBaseHost: { type: String },
|
|
21
|
-
baseHost: { type: String },
|
|
22
|
-
hideSearch: { type: Boolean },
|
|
23
|
-
config: { type: Object },
|
|
24
|
-
openMenu: { type: String },
|
|
25
|
-
screenName: { type: String },
|
|
26
|
-
searchIn: { type: String },
|
|
27
|
-
searchQuery: { type: String },
|
|
28
|
-
secondIdentitySlotMode: { type: String },
|
|
29
|
-
selectedMenuOption: { type: String },
|
|
30
|
-
signedOutMenuOpen: { type: Boolean },
|
|
31
|
-
userMenuOpen: { type: Boolean },
|
|
32
|
-
username: { type: String },
|
|
33
|
-
userProfileImagePath: { type: String },
|
|
34
|
-
userProfileLastModified: { type: String },
|
|
35
|
-
};
|
|
36
|
-
}
|
|
37
|
-
|
|
38
|
-
constructor() {
|
|
39
|
-
super();
|
|
40
|
-
this.config = {};
|
|
41
|
-
this.openMenu = '';
|
|
42
|
-
this.searchIn = '';
|
|
43
|
-
this.selectedMenuOption = '';
|
|
44
|
-
this.signedOutMenuOpen = false;
|
|
45
|
-
this.userMenuOpen = false;
|
|
46
|
-
this.mediaBaseHost = 'https://archive.org';
|
|
47
|
-
this.secondIdentitySlotMode = '';
|
|
48
|
-
}
|
|
49
|
-
|
|
50
|
-
toggleMediaMenu(e) {
|
|
51
|
-
this.trackClick(e);
|
|
52
|
-
this.dispatchEvent(
|
|
53
|
-
new CustomEvent('menuToggled', {
|
|
54
|
-
detail: {
|
|
55
|
-
menuName: 'media',
|
|
56
|
-
},
|
|
57
|
-
}),
|
|
58
|
-
);
|
|
59
|
-
}
|
|
60
|
-
|
|
61
|
-
toggleSearchMenu(e) {
|
|
62
|
-
this.trackClick(e);
|
|
63
|
-
this.dispatchEvent(
|
|
64
|
-
new CustomEvent('menuToggled', {
|
|
65
|
-
detail: {
|
|
66
|
-
menuName: 'search',
|
|
67
|
-
},
|
|
68
|
-
}),
|
|
69
|
-
);
|
|
70
|
-
}
|
|
71
|
-
|
|
72
|
-
toggleUserMenu(e) {
|
|
73
|
-
this.trackClick(e);
|
|
74
|
-
this.dispatchEvent(
|
|
75
|
-
new CustomEvent('menuToggled', {
|
|
76
|
-
detail: {
|
|
77
|
-
menuName: 'user',
|
|
78
|
-
},
|
|
79
|
-
}),
|
|
80
|
-
);
|
|
81
|
-
}
|
|
82
|
-
|
|
83
|
-
get truncatedScreenName() {
|
|
84
|
-
if (this.screenName && this.screenName.length > 10) {
|
|
85
|
-
return `${this.screenName.substr(0, 9)}…`;
|
|
86
|
-
}
|
|
87
|
-
return this.screenName;
|
|
88
|
-
}
|
|
89
|
-
|
|
90
|
-
get userIcon() {
|
|
91
|
-
const userMenuClass = this.openMenu === 'user' ? 'active' : '';
|
|
92
|
-
const userMenuToolTip = this.openMenu === 'user' ? 'Close user menu' : 'Expand user menu';
|
|
93
|
-
|
|
94
|
-
return html`
|
|
95
|
-
<button
|
|
96
|
-
class="user-menu ${userMenuClass}"
|
|
97
|
-
title="${userMenuToolTip}"
|
|
98
|
-
@click="${this.toggleUserMenu}"
|
|
99
|
-
data-event-click-tracking="${this.config.eventCategory}|NavUserMenu"
|
|
100
|
-
>
|
|
101
|
-
<img
|
|
102
|
-
src="${this.mediaBaseHost}${this.userProfileImagePath}?${this.userProfileLastModified}"
|
|
103
|
-
alt="${this.username}"
|
|
104
|
-
/>
|
|
105
|
-
<span class="username">${this.truncatedScreenName}</span>
|
|
106
|
-
</button>
|
|
107
|
-
`;
|
|
108
|
-
}
|
|
109
|
-
|
|
110
|
-
get loginIcon() {
|
|
111
|
-
return html`
|
|
112
|
-
<login-button
|
|
113
|
-
.baseHost=${this.baseHost}
|
|
114
|
-
.config=${this.config}
|
|
115
|
-
.dropdownOpen=${this.signedOutMenuOpen}
|
|
116
|
-
.openMenu=${this.openMenu}
|
|
117
|
-
@signedOutMenuToggled=${this.signedOutMenuToggled}
|
|
118
|
-
></login-button>
|
|
119
|
-
`;
|
|
120
|
-
}
|
|
121
|
-
|
|
122
|
-
get searchMenuOpen() {
|
|
123
|
-
return this.openMenu === 'search';
|
|
124
|
-
}
|
|
125
|
-
|
|
126
|
-
get allowSecondaryIcon() {
|
|
127
|
-
return this.secondIdentitySlotMode === 'allow';
|
|
128
|
-
}
|
|
129
|
-
|
|
130
|
-
get searchMenu() {
|
|
131
|
-
if (this.hideSearch) return nothing;
|
|
132
|
-
|
|
133
|
-
return html`
|
|
134
|
-
<button
|
|
135
|
-
class="search-trigger"
|
|
136
|
-
@click="${this.toggleSearchMenu}"
|
|
137
|
-
data-event-click-tracking="${this.config.eventCategory}|NavSearchOpen"
|
|
138
|
-
>
|
|
139
|
-
${icons.search}
|
|
140
|
-
</button>
|
|
141
|
-
<nav-search
|
|
142
|
-
.baseHost=${this.baseHost}
|
|
143
|
-
.config=${this.config}
|
|
144
|
-
.locationHandler=${locationHandler}
|
|
145
|
-
.open=${this.searchMenuOpen}
|
|
146
|
-
.openMenu=${this.openMenu}
|
|
147
|
-
.searchIn=${this.searchIn}
|
|
148
|
-
.searchQuery=${this.searchQuery}
|
|
149
|
-
></nav-search>
|
|
150
|
-
`;
|
|
151
|
-
}
|
|
152
|
-
|
|
153
|
-
get secondLogoSlot() {
|
|
154
|
-
return this.allowSecondaryIcon
|
|
155
|
-
? html`
|
|
156
|
-
<slot name="opt-sec-logo"></slot>
|
|
157
|
-
<slot name="opt-sec-logo-mobile"></slot>
|
|
158
|
-
`
|
|
159
|
-
: nothing;
|
|
160
|
-
}
|
|
161
|
-
|
|
162
|
-
get secondLogoClass() {
|
|
163
|
-
return this.allowSecondaryIcon ? 'second-logo' : '';
|
|
164
|
-
}
|
|
165
|
-
|
|
166
|
-
render() {
|
|
167
|
-
const mediaMenuTabIndex = this.openMenu === 'media' ? '' : '-1';
|
|
168
|
-
return html`
|
|
169
|
-
<nav>
|
|
170
|
-
<div class=${`branding ${this.secondLogoClass}`}>
|
|
171
|
-
<a
|
|
172
|
-
href=${formatUrl('/', this.baseHost)}
|
|
173
|
-
@click=${this.trackClick}
|
|
174
|
-
data-event-click-tracking="${this.config.eventCategory}|NavHome"
|
|
175
|
-
title="Go home"
|
|
176
|
-
class="link-home"
|
|
177
|
-
>${icons.iaLogo}${logoWordmarkStacked}</a
|
|
178
|
-
>
|
|
179
|
-
${this.secondLogoSlot}
|
|
180
|
-
</div>
|
|
181
|
-
${this.searchMenu}
|
|
182
|
-
<a href="${formatUrl('/create', this.baseHost)}" class="upload">
|
|
183
|
-
${icons.upload}
|
|
184
|
-
<span>Upload</span>
|
|
185
|
-
</a>
|
|
186
|
-
<div class="user-info">
|
|
187
|
-
${this.username ? this.userIcon : this.loginIcon}
|
|
188
|
-
</div>
|
|
189
|
-
<media-menu
|
|
190
|
-
.baseHost=${this.baseHost}
|
|
191
|
-
.config=${this.config}
|
|
192
|
-
?mediaMenuAnimate="${this.mediaMenuAnimate}"
|
|
193
|
-
tabindex="${mediaMenuTabIndex}"
|
|
194
|
-
.selectedMenuOption=${this.selectedMenuOption}
|
|
195
|
-
.openMenu=${this.openMenu}
|
|
196
|
-
></media-menu>
|
|
197
|
-
<button
|
|
198
|
-
class="hamburger"
|
|
199
|
-
@click="${this.toggleMediaMenu}"
|
|
200
|
-
tabindex="1"
|
|
201
|
-
data-event-click-tracking="${this.config.eventCategory}|NavHamburger"
|
|
202
|
-
title="Open main menu"
|
|
203
|
-
>
|
|
204
|
-
<icon-hamburger ?active=${this.openMenu === 'media'}></icon-hamburger>
|
|
205
|
-
</button>
|
|
206
|
-
</nav>
|
|
207
|
-
`;
|
|
208
|
-
}
|
|
209
|
-
}
|
|
210
|
-
|
|
211
|
-
customElements.define('primary-nav', PrimaryNav);
|
|
1
|
+
import { html, nothing } from 'https://offshoot.ux.archive.org/lit.js';
|
|
2
|
+
import TrackedElement from './tracked-element.js';
|
|
3
|
+
import icons from './assets/img/icons.js';
|
|
4
|
+
import './assets/img/hamburger.js';
|
|
5
|
+
import './login-button.js';
|
|
6
|
+
import './nav-search.js';
|
|
7
|
+
import './media-menu.js';
|
|
8
|
+
import logoWordmarkStacked from './assets/img/wordmark-stacked.js';
|
|
9
|
+
import primaryNavCSS from './styles/primary-nav.js';
|
|
10
|
+
import locationHandler from './lib/location-handler.js';
|
|
11
|
+
import formatUrl from './lib/formatUrl.js';
|
|
12
|
+
|
|
13
|
+
class PrimaryNav extends TrackedElement {
|
|
14
|
+
static get styles() {
|
|
15
|
+
return primaryNavCSS;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
static get properties() {
|
|
19
|
+
return {
|
|
20
|
+
mediaBaseHost: { type: String },
|
|
21
|
+
baseHost: { type: String },
|
|
22
|
+
hideSearch: { type: Boolean },
|
|
23
|
+
config: { type: Object },
|
|
24
|
+
openMenu: { type: String },
|
|
25
|
+
screenName: { type: String },
|
|
26
|
+
searchIn: { type: String },
|
|
27
|
+
searchQuery: { type: String },
|
|
28
|
+
secondIdentitySlotMode: { type: String },
|
|
29
|
+
selectedMenuOption: { type: String },
|
|
30
|
+
signedOutMenuOpen: { type: Boolean },
|
|
31
|
+
userMenuOpen: { type: Boolean },
|
|
32
|
+
username: { type: String },
|
|
33
|
+
userProfileImagePath: { type: String },
|
|
34
|
+
userProfileLastModified: { type: String },
|
|
35
|
+
};
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
constructor() {
|
|
39
|
+
super();
|
|
40
|
+
this.config = {};
|
|
41
|
+
this.openMenu = '';
|
|
42
|
+
this.searchIn = '';
|
|
43
|
+
this.selectedMenuOption = '';
|
|
44
|
+
this.signedOutMenuOpen = false;
|
|
45
|
+
this.userMenuOpen = false;
|
|
46
|
+
this.mediaBaseHost = 'https://archive.org';
|
|
47
|
+
this.secondIdentitySlotMode = '';
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
toggleMediaMenu(e) {
|
|
51
|
+
this.trackClick(e);
|
|
52
|
+
this.dispatchEvent(
|
|
53
|
+
new CustomEvent('menuToggled', {
|
|
54
|
+
detail: {
|
|
55
|
+
menuName: 'media',
|
|
56
|
+
},
|
|
57
|
+
}),
|
|
58
|
+
);
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
toggleSearchMenu(e) {
|
|
62
|
+
this.trackClick(e);
|
|
63
|
+
this.dispatchEvent(
|
|
64
|
+
new CustomEvent('menuToggled', {
|
|
65
|
+
detail: {
|
|
66
|
+
menuName: 'search',
|
|
67
|
+
},
|
|
68
|
+
}),
|
|
69
|
+
);
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
toggleUserMenu(e) {
|
|
73
|
+
this.trackClick(e);
|
|
74
|
+
this.dispatchEvent(
|
|
75
|
+
new CustomEvent('menuToggled', {
|
|
76
|
+
detail: {
|
|
77
|
+
menuName: 'user',
|
|
78
|
+
},
|
|
79
|
+
}),
|
|
80
|
+
);
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
get truncatedScreenName() {
|
|
84
|
+
if (this.screenName && this.screenName.length > 10) {
|
|
85
|
+
return `${this.screenName.substr(0, 9)}…`;
|
|
86
|
+
}
|
|
87
|
+
return this.screenName;
|
|
88
|
+
}
|
|
89
|
+
|
|
90
|
+
get userIcon() {
|
|
91
|
+
const userMenuClass = this.openMenu === 'user' ? 'active' : '';
|
|
92
|
+
const userMenuToolTip = this.openMenu === 'user' ? 'Close user menu' : 'Expand user menu';
|
|
93
|
+
|
|
94
|
+
return html`
|
|
95
|
+
<button
|
|
96
|
+
class="user-menu ${userMenuClass}"
|
|
97
|
+
title="${userMenuToolTip}"
|
|
98
|
+
@click="${this.toggleUserMenu}"
|
|
99
|
+
data-event-click-tracking="${this.config.eventCategory}|NavUserMenu"
|
|
100
|
+
>
|
|
101
|
+
<img
|
|
102
|
+
src="${this.mediaBaseHost}${this.userProfileImagePath}?${this.userProfileLastModified}"
|
|
103
|
+
alt="${this.username}"
|
|
104
|
+
/>
|
|
105
|
+
<span class="username">${this.truncatedScreenName}</span>
|
|
106
|
+
</button>
|
|
107
|
+
`;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
get loginIcon() {
|
|
111
|
+
return html`
|
|
112
|
+
<login-button
|
|
113
|
+
.baseHost=${this.baseHost}
|
|
114
|
+
.config=${this.config}
|
|
115
|
+
.dropdownOpen=${this.signedOutMenuOpen}
|
|
116
|
+
.openMenu=${this.openMenu}
|
|
117
|
+
@signedOutMenuToggled=${this.signedOutMenuToggled}
|
|
118
|
+
></login-button>
|
|
119
|
+
`;
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
get searchMenuOpen() {
|
|
123
|
+
return this.openMenu === 'search';
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
get allowSecondaryIcon() {
|
|
127
|
+
return this.secondIdentitySlotMode === 'allow';
|
|
128
|
+
}
|
|
129
|
+
|
|
130
|
+
get searchMenu() {
|
|
131
|
+
if (this.hideSearch) return nothing;
|
|
132
|
+
|
|
133
|
+
return html`
|
|
134
|
+
<button
|
|
135
|
+
class="search-trigger"
|
|
136
|
+
@click="${this.toggleSearchMenu}"
|
|
137
|
+
data-event-click-tracking="${this.config.eventCategory}|NavSearchOpen"
|
|
138
|
+
>
|
|
139
|
+
${icons.search}
|
|
140
|
+
</button>
|
|
141
|
+
<nav-search
|
|
142
|
+
.baseHost=${this.baseHost}
|
|
143
|
+
.config=${this.config}
|
|
144
|
+
.locationHandler=${locationHandler}
|
|
145
|
+
.open=${this.searchMenuOpen}
|
|
146
|
+
.openMenu=${this.openMenu}
|
|
147
|
+
.searchIn=${this.searchIn}
|
|
148
|
+
.searchQuery=${this.searchQuery}
|
|
149
|
+
></nav-search>
|
|
150
|
+
`;
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
get secondLogoSlot() {
|
|
154
|
+
return this.allowSecondaryIcon
|
|
155
|
+
? html`
|
|
156
|
+
<slot name="opt-sec-logo"></slot>
|
|
157
|
+
<slot name="opt-sec-logo-mobile"></slot>
|
|
158
|
+
`
|
|
159
|
+
: nothing;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
get secondLogoClass() {
|
|
163
|
+
return this.allowSecondaryIcon ? 'second-logo' : '';
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
render() {
|
|
167
|
+
const mediaMenuTabIndex = this.openMenu === 'media' ? '' : '-1';
|
|
168
|
+
return html`
|
|
169
|
+
<nav>
|
|
170
|
+
<div class=${`branding ${this.secondLogoClass}`}>
|
|
171
|
+
<a
|
|
172
|
+
href=${formatUrl('/', this.baseHost)}
|
|
173
|
+
@click=${this.trackClick}
|
|
174
|
+
data-event-click-tracking="${this.config.eventCategory}|NavHome"
|
|
175
|
+
title="Go home"
|
|
176
|
+
class="link-home"
|
|
177
|
+
>${icons.iaLogo}${logoWordmarkStacked}</a
|
|
178
|
+
>
|
|
179
|
+
${this.secondLogoSlot}
|
|
180
|
+
</div>
|
|
181
|
+
${this.searchMenu}
|
|
182
|
+
<a href="${formatUrl('/create', this.baseHost)}" class="upload">
|
|
183
|
+
${icons.upload}
|
|
184
|
+
<span>Upload</span>
|
|
185
|
+
</a>
|
|
186
|
+
<div class="user-info">
|
|
187
|
+
${this.username ? this.userIcon : this.loginIcon}
|
|
188
|
+
</div>
|
|
189
|
+
<media-menu
|
|
190
|
+
.baseHost=${this.baseHost}
|
|
191
|
+
.config=${this.config}
|
|
192
|
+
?mediaMenuAnimate="${this.mediaMenuAnimate}"
|
|
193
|
+
tabindex="${mediaMenuTabIndex}"
|
|
194
|
+
.selectedMenuOption=${this.selectedMenuOption}
|
|
195
|
+
.openMenu=${this.openMenu}
|
|
196
|
+
></media-menu>
|
|
197
|
+
<button
|
|
198
|
+
class="hamburger"
|
|
199
|
+
@click="${this.toggleMediaMenu}"
|
|
200
|
+
tabindex="1"
|
|
201
|
+
data-event-click-tracking="${this.config.eventCategory}|NavHamburger"
|
|
202
|
+
title="Open main menu"
|
|
203
|
+
>
|
|
204
|
+
<icon-hamburger ?active=${this.openMenu === 'media'}></icon-hamburger>
|
|
205
|
+
</button>
|
|
206
|
+
</nav>
|
|
207
|
+
`;
|
|
208
|
+
}
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
customElements.define('primary-nav', PrimaryNav);
|