@internetarchive/ia-topnav 1.3.6 → 1.3.7

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 (85) hide show
  1. package/.eslintrc +16 -16
  2. package/LICENSE +661 -661
  3. package/README.md +147 -147
  4. package/index.d.ts +109 -109
  5. package/index.js +3 -3
  6. package/package.json +61 -61
  7. package/src/assets/img/hamburger.js +38 -38
  8. package/src/assets/img/ia-icon.js +33 -33
  9. package/src/assets/img/icon-audio.js +23 -23
  10. package/src/assets/img/icon-close.js +16 -16
  11. package/src/assets/img/icon-donate-unpadded.js +16 -16
  12. package/src/assets/img/icon-donate.js +15 -15
  13. package/src/assets/img/icon-ellipses.js +15 -15
  14. package/src/assets/img/icon-ia-logo.js +22 -22
  15. package/src/assets/img/icon-images.js +15 -15
  16. package/src/assets/img/icon-search.js +15 -15
  17. package/src/assets/img/icon-software.js +15 -15
  18. package/src/assets/img/icon-texts.js +15 -15
  19. package/src/assets/img/icon-upload-unpadded.js +14 -14
  20. package/src/assets/img/icon-upload.js +15 -15
  21. package/src/assets/img/icon-user.js +15 -15
  22. package/src/assets/img/icon-video.js +15 -15
  23. package/src/assets/img/icon-web.js +15 -15
  24. package/src/assets/img/icon.js +18 -18
  25. package/src/assets/img/icons.js +33 -33
  26. package/src/assets/img/wordmark-stacked.js +13 -13
  27. package/src/data/menus.js +646 -646
  28. package/src/desktop-subnav.js +45 -45
  29. package/src/dropdown-menu.js +110 -109
  30. package/src/ia-topnav.js +324 -314
  31. package/src/lib/formatUrl.js +1 -1
  32. package/src/lib/keyboard-navigation.js +128 -0
  33. package/src/lib/location-handler.js +5 -5
  34. package/src/lib/query-handler.js +7 -7
  35. package/src/lib/toSentenceCase.js +8 -8
  36. package/src/login-button.js +79 -79
  37. package/src/media-button.js +113 -113
  38. package/src/media-menu.js +154 -133
  39. package/src/media-slider.js +118 -104
  40. package/src/media-subnav.js +112 -112
  41. package/src/more-slider.js +33 -33
  42. package/src/nav-search.js +111 -117
  43. package/src/primary-nav.js +258 -224
  44. package/src/save-page-form.js +59 -59
  45. package/src/search-menu.js +145 -115
  46. package/src/signed-out-dropdown.js +10 -10
  47. package/src/styles/base.js +48 -48
  48. package/src/styles/desktop-subnav.js +37 -37
  49. package/src/styles/dropdown-menu.js +168 -166
  50. package/src/styles/ia-topnav.js +87 -87
  51. package/src/styles/login-button.js +82 -79
  52. package/src/styles/media-button.js +156 -156
  53. package/src/styles/media-menu.js +66 -70
  54. package/src/styles/media-slider.js +81 -81
  55. package/src/styles/media-subnav.js +156 -156
  56. package/src/styles/more-slider.js +15 -15
  57. package/src/styles/nav-search.js +136 -136
  58. package/src/styles/primary-nav.js +311 -300
  59. package/src/styles/save-page-form.js +54 -54
  60. package/src/styles/search-menu.js +105 -99
  61. package/src/styles/signed-out-dropdown.js +31 -31
  62. package/src/styles/user-menu.js +31 -31
  63. package/src/styles/wayback-search.js +48 -48
  64. package/src/styles/wayback-slider.js +30 -30
  65. package/src/tracked-element.js +29 -27
  66. package/src/user-menu.js +56 -42
  67. package/src/wayback-search.js +18 -18
  68. package/src/wayback-slider.js +87 -87
  69. package/test/assets/img/hamburger.test.js +15 -15
  70. package/test/assets/img/user.test.js +15 -15
  71. package/test/data/menus.test.js +19 -19
  72. package/test/dropdown-menu.test.js +25 -25
  73. package/test/ia-icon.test.js +13 -13
  74. package/test/ia-topnav.test.js +273 -273
  75. package/test/login-button.test.js +15 -15
  76. package/test/media-button.test.js +19 -19
  77. package/test/media-menu.test.js +40 -40
  78. package/test/media-slider.test.js +57 -57
  79. package/test/more-slider.test.js +13 -13
  80. package/test/nav-search.test.js +61 -61
  81. package/test/primary-nav.test.js +82 -82
  82. package/test/save-page-form.test.js +35 -35
  83. package/test/search-menu.test.js +49 -49
  84. package/test/user-menu.test.js +33 -33
  85. package/test/wayback-slider.test.js +80 -80
package/src/media-menu.js CHANGED
@@ -1,133 +1,154 @@
1
- import { LitElement, html } from 'https://offshoot.prod.archive.org/lit.js';
2
-
3
- import './media-button.js';
4
- import mediaMenuCSS from './styles/media-menu.js';
5
- import formatUrl from './lib/formatUrl.js';
6
-
7
- const menuSelection = [
8
- {
9
- icon: 'web',
10
- menu: 'web',
11
- href: 'https://web.archive.org',
12
- label: 'Wayback Machine',
13
- },
14
- {
15
- icon: 'texts',
16
- menu: 'texts',
17
- href: '/details/texts',
18
- label: 'Texts',
19
- },
20
- {
21
- icon: 'video',
22
- menu: 'video',
23
- href: '/details/movies',
24
- label: 'Video',
25
- },
26
- {
27
- icon: 'audio',
28
- menu: 'audio',
29
- href: '/details/audio',
30
- label: 'Audio',
31
- },
32
- {
33
- icon: 'software',
34
- menu: 'software',
35
- href: '/details/software',
36
- label: 'Software',
37
- },
38
- {
39
- icon: 'images',
40
- menu: 'images',
41
- href: '/details/image',
42
- label: 'Images',
43
- },
44
- {
45
- icon: 'donate',
46
- menu: 'donate',
47
- href: '/donate/',
48
- label: 'Donate',
49
- followable: true,
50
- },
51
- {
52
- icon: 'ellipses',
53
- menu: 'more',
54
- href: '/about/',
55
- label: 'More',
56
- },
57
- ];
58
-
59
- class MediaMenu extends LitElement {
60
- static get styles() {
61
- return mediaMenuCSS;
62
- }
63
-
64
- static get properties() {
65
- return {
66
- baseHost: { type: String },
67
- config: { type: Object },
68
- openMenu: { type: String },
69
- selectedMenuOption: { type: String },
70
- };
71
- }
72
-
73
- constructor() {
74
- super();
75
- this.config = {};
76
- this.openMenu = '';
77
- this.selectedMenuOption = '';
78
- }
79
-
80
- get mediaMenuOptionsTemplate() {
81
- const buttons = menuSelection.map(({
82
- icon,
83
- menu,
84
- label,
85
- href,
86
- followable,
87
- }) => {
88
- const selected = this.selectedMenuOption === menu;
89
- return html`
90
- <media-button
91
- .config=${this.config}
92
- .icon=${icon}
93
- .href=${formatUrl(href, this.baseHost)}
94
- .followable=${followable}
95
- .label=${label}
96
- .mediatype=${menu}
97
- .openMenu=${this.openMenu}
98
- .selected=${selected}
99
- data-mediatype="${menu}"
100
- ></media-button>
101
- `;
102
- });
103
- return buttons;
104
- }
105
-
106
- get menuOpened() {
107
- return this.openMenu === 'media';
108
- }
109
-
110
- get menuClass() {
111
- return this.menuOpened ? 'open' : 'closed';
112
- }
113
-
114
- render() {
115
- return html`
116
- <div class="media-menu-container ${this.menuClass}">
117
- <div class="overflow-clip">
118
- <nav
119
- class="media-menu-inner"
120
- aria-hidden="${!this.menuOpened}"
121
- aria-expanded="${this.menuOpened}"
122
- >
123
- <div class="menu-group">
124
- ${this.mediaMenuOptionsTemplate}
125
- </div>
126
- </nav>
127
- </div>
128
- </div>
129
- `;
130
- }
131
- }
132
-
133
- customElements.define('media-menu', MediaMenu);
1
+ import { LitElement, html } from 'https://offshoot.prod.archive.org/lit.js';
2
+
3
+ import './media-button.js';
4
+ import mediaMenuCSS from './styles/media-menu.js';
5
+ import formatUrl from './lib/formatUrl.js';
6
+
7
+ const menuSelection = [
8
+ {
9
+ icon: 'web',
10
+ menu: 'web',
11
+ href: 'https://web.archive.org',
12
+ label: 'Wayback Machine',
13
+ },
14
+ {
15
+ icon: 'texts',
16
+ menu: 'texts',
17
+ href: '/details/texts',
18
+ label: 'Texts',
19
+ },
20
+ {
21
+ icon: 'video',
22
+ menu: 'video',
23
+ href: '/details/movies',
24
+ label: 'Video',
25
+ },
26
+ {
27
+ icon: 'audio',
28
+ menu: 'audio',
29
+ href: '/details/audio',
30
+ label: 'Audio',
31
+ },
32
+ {
33
+ icon: 'software',
34
+ menu: 'software',
35
+ href: '/details/software',
36
+ label: 'Software',
37
+ },
38
+ {
39
+ icon: 'images',
40
+ menu: 'images',
41
+ href: '/details/image',
42
+ label: 'Images',
43
+ },
44
+ {
45
+ icon: 'donate',
46
+ menu: 'donate',
47
+ href: '/donate/',
48
+ label: 'Donate',
49
+ followable: true,
50
+ },
51
+ {
52
+ icon: 'ellipses',
53
+ menu: 'more',
54
+ href: '/about/',
55
+ label: 'More',
56
+ },
57
+ ];
58
+
59
+ class MediaMenu extends LitElement {
60
+ static get styles() {
61
+ return mediaMenuCSS;
62
+ }
63
+
64
+ static get properties() {
65
+ return {
66
+ baseHost: { type: String },
67
+ config: { type: Object },
68
+ openMenu: { type: String },
69
+ selectedMenuOption: { type: String },
70
+ currentTab: { type: Object },
71
+ };
72
+ }
73
+
74
+ constructor() {
75
+ super();
76
+ this.config = {};
77
+ this.openMenu = '';
78
+ this.selectedMenuOption = '';
79
+ this.currentTab = {};
80
+ }
81
+
82
+ updated(props) {
83
+ if (props.has('currentTab')) {
84
+ const mediaButtons = Array.from(this.shadowRoot.querySelectorAll('media-button'));
85
+
86
+ mediaButtons.map((button, index) => {
87
+ const linkItem = button.shadowRoot.querySelector('a.menu-item');
88
+ if (linkItem) {
89
+ if (linkItem.classList.contains(`${this.selectedMenuOption}`)) {
90
+ linkItem.classList.remove('selected');
91
+ linkItem.blur();
92
+
93
+ const newFocusIndex = this.currentTab.moveTo === 'next' ? index + 1 : index - 1;
94
+ mediaButtons[newFocusIndex].shadowRoot.querySelector('a.menu-item').focus();
95
+ }
96
+ }
97
+ });
98
+ }
99
+ }
100
+
101
+ get mediaMenuOptionsTemplate() {
102
+ const buttons = menuSelection.map(({
103
+ icon,
104
+ menu,
105
+ label,
106
+ href,
107
+ followable,
108
+ }) => {
109
+ const selected = this.selectedMenuOption === menu;
110
+ return html`
111
+ <media-button
112
+ .config=${this.config}
113
+ .icon=${icon}
114
+ .href=${formatUrl(href, this.baseHost)}
115
+ .followable=${followable}
116
+ .label=${label}
117
+ .mediatype=${menu}
118
+ .openMenu=${this.openMenu}
119
+ .selected=${selected}
120
+ .selectedMenuOption=${this.selectedMenuOption}
121
+ data-mediatype="${menu}"
122
+ ></media-button>
123
+ `;
124
+ });
125
+ return buttons;
126
+ }
127
+
128
+ get menuOpened() {
129
+ return this.openMenu === 'media';
130
+ }
131
+
132
+ get menuClass() {
133
+ return this.menuOpened ? 'open' : 'closed';
134
+ }
135
+
136
+ render() {
137
+ return html`
138
+ <div class="media-menu-container ${this.menuClass}">
139
+ <div class="overflow-clip">
140
+ <nav
141
+ class="media-menu-inner"
142
+ aria-expanded="${this.menuOpened}"
143
+ >
144
+ <div class="menu-group">
145
+ ${this.mediaMenuOptionsTemplate}
146
+ </div>
147
+ </nav>
148
+ </div>
149
+ </div>
150
+ `;
151
+ }
152
+ }
153
+
154
+ customElements.define('media-menu', MediaMenu);
@@ -1,104 +1,118 @@
1
- import { LitElement, html } from 'https://offshoot.prod.archive.org/lit.js';
2
- import './media-subnav.js';
3
- import mediaSliderCSS from './styles/media-slider.js';
4
-
5
- class MediaSlider extends LitElement {
6
- static get styles() {
7
- return mediaSliderCSS;
8
- }
9
-
10
- static get properties() {
11
- return {
12
- baseHost: { type: String },
13
- config: { type: Object },
14
- mediaSliderOpen: { type: Boolean },
15
- menus: { type: Object },
16
- selectedMenuOption: { type: String },
17
- };
18
- }
19
-
20
- constructor() {
21
- super();
22
-
23
- this.config = {};
24
- this.mediaSliderOpen = false;
25
- this.menus = {};
26
- this.selectedMenuOption = 'texts';
27
- }
28
-
29
- shouldUpdate() {
30
- const scrollPane = this.shadowRoot ? this.shadowRoot.querySelector('.information-menu') : null;
31
-
32
- if (scrollPane) {
33
- scrollPane.scrollTop = 0;
34
- }
35
- return true;
36
- }
37
-
38
-
39
- render() {
40
- const sliderDetailsClass = this.mediaSliderOpen ? 'open' : 'closed';
41
-
42
- return html`
43
- <div class="media-slider-container">
44
- <div class="overflow-clip ${sliderDetailsClass}">
45
- <div class="information-menu ${sliderDetailsClass}">
46
- <div class="info-box">
47
- <media-subnav
48
- .baseHost=${this.baseHost}
49
- .config=${this.config}
50
- class="${this.selectedMenuOption === 'audio' ? '' : 'hidden'}"
51
- menu="audio"
52
- .menuItems=${this.menus.audio}
53
- ></media-subnav>
54
- <media-subnav
55
- .baseHost=${this.baseHost}
56
- .config=${this.config}
57
- class="${this.selectedMenuOption === 'images' ? '' : 'hidden'}"
58
- menu="images"
59
- .menuItems=${this.menus.images}
60
- ></media-subnav>
61
- <media-subnav
62
- .baseHost=${this.baseHost}
63
- .config=${this.config}
64
- class="${this.selectedMenuOption === 'software' ? '' : 'hidden'}"
65
- menu="software"
66
- .menuItems=${this.menus.software}
67
- ></media-subnav>
68
- <media-subnav
69
- .baseHost=${this.baseHost}
70
- .config=${this.config}
71
- class="${this.selectedMenuOption === 'texts' ? '' : 'hidden'}"
72
- menu="texts"
73
- .menuItems=${this.menus.texts}
74
- ></media-subnav>
75
- <media-subnav
76
- .baseHost=${this.baseHost}
77
- .config=${this.config}
78
- class="${this.selectedMenuOption === 'video' ? '' : 'hidden'}"
79
- menu="video"
80
- .menuItems=${this.menus.video}
81
- ></media-subnav>
82
- <media-subnav
83
- .baseHost=${this.baseHost}
84
- .config=${this.config}
85
- class="${this.selectedMenuOption === 'web' ? '' : 'hidden'}"
86
- menu="web"
87
- .menuItems=${this.menus.web}
88
- ></media-subnav>
89
- <media-subnav
90
- .baseHost=${this.baseHost}
91
- .config=${this.config}
92
- class="${this.selectedMenuOption === 'more' ? '' : 'hidden'}"
93
- menu="more"
94
- .menuItems=${this.menus.more}
95
- ></media-subnav>
96
- </div>
97
- </div>
98
- </div>
99
- </div>
100
- `;
101
- }
102
- }
103
-
104
- customElements.define('media-slider', MediaSlider);
1
+ import { LitElement, html } from 'https://offshoot.prod.archive.org/lit.js';
2
+ import './media-subnav.js';
3
+ import mediaSliderCSS from './styles/media-slider.js';
4
+ import KeyboardNavigation from './lib/keyboard-navigation.js';
5
+
6
+ class MediaSlider extends LitElement {
7
+ static get styles() {
8
+ return mediaSliderCSS;
9
+ }
10
+
11
+ static get properties() {
12
+ return {
13
+ baseHost: { type: String },
14
+ config: { type: Object },
15
+ mediaSliderOpen: { type: Boolean },
16
+ menus: { type: Object },
17
+ selectedMenuOption: { type: String },
18
+ };
19
+ }
20
+
21
+ constructor() {
22
+ super();
23
+
24
+ this.config = {};
25
+ this.mediaSliderOpen = false;
26
+ this.menus = {};
27
+ this.selectedMenuOption = 'texts';
28
+ }
29
+
30
+ updated(props) {
31
+ if (props.has('selectedMenuOption') && this.selectedMenuOption) {
32
+ const container = this.shadowRoot?.querySelector('.has-focused')?.shadowRoot;
33
+
34
+ if (container) {
35
+ const keyboardNavigation = new KeyboardNavigation(container, this.selectedMenuOption);
36
+ this.addEventListener('keydown', keyboardNavigation.handleKeyDown);
37
+ this.removeEventListener('keydown', this.previousKeydownListener);
38
+ this.previousKeydownListener = keyboardNavigation.handleKeyDown;
39
+ }
40
+ }
41
+ }
42
+
43
+ shouldUpdate() {
44
+ const scrollPane = this.shadowRoot ? this.shadowRoot.querySelector('.information-menu') : null;
45
+
46
+ if (scrollPane) {
47
+ scrollPane.scrollTop = 0;
48
+ }
49
+ return true;
50
+ }
51
+
52
+
53
+ render() {
54
+ const sliderDetailsClass = this.mediaSliderOpen ? 'open' : 'closed';
55
+
56
+ return html`
57
+ <div class="media-slider-container">
58
+ <div class="overflow-clip ${sliderDetailsClass}">
59
+ <div class="information-menu ${sliderDetailsClass}">
60
+ <div class="info-box">
61
+ <media-subnav
62
+ .baseHost=${this.baseHost}
63
+ .config=${this.config}
64
+ class="${this.selectedMenuOption === 'audio' ? 'has-focused' : 'hidden'}"
65
+ menu="audio"
66
+ .menuItems=${this.menus.audio}
67
+ ></media-subnav>
68
+ <media-subnav
69
+ .baseHost=${this.baseHost}
70
+ .config=${this.config}
71
+ class="${this.selectedMenuOption === 'images' ? 'has-focused' : 'hidden'}"
72
+ menu="images"
73
+ .menuItems=${this.menus.images}
74
+ ></media-subnav>
75
+ <media-subnav
76
+ .baseHost=${this.baseHost}
77
+ .config=${this.config}
78
+ class="${this.selectedMenuOption === 'software' ? 'has-focused' : 'hidden'}"
79
+ menu="software"
80
+ .menuItems=${this.menus.software}
81
+ ></media-subnav>
82
+ <media-subnav
83
+ .baseHost=${this.baseHost}
84
+ .config=${this.config}
85
+ class="${this.selectedMenuOption === 'texts' ? 'has-focused' : 'hidden'}"
86
+ menu="texts"
87
+ .menuItems=${this.menus.texts}
88
+ ></media-subnav>
89
+ <media-subnav
90
+ .baseHost=${this.baseHost}
91
+ .config=${this.config}
92
+ class="${this.selectedMenuOption === 'video' ? 'has-focused' : 'hidden'}"
93
+ menu="video"
94
+ .menuItems=${this.menus.video}
95
+ ></media-subnav>
96
+ <media-subnav
97
+ .baseHost=${this.baseHost}
98
+ .config=${this.config}
99
+ class="${this.selectedMenuOption === 'web' ? 'has-focused' : 'hidden'}"
100
+ menu="web"
101
+ .menuItems=${this.menus.web}
102
+ ></media-subnav>
103
+ <media-subnav
104
+ .baseHost=${this.baseHost}
105
+ .config=${this.config}
106
+ class="${this.selectedMenuOption === 'more' ? 'has-focused' : 'hidden'}"
107
+ menu="more"
108
+ .menuItems=${this.menus.more}
109
+ ></media-subnav>
110
+ </div>
111
+ </div>
112
+ </div>
113
+ </div>
114
+ `;
115
+ }
116
+ }
117
+
118
+ customElements.define('media-slider', MediaSlider);