@internetarchive/ia-topnav 1.3.30 → 1.4.1-alpha-webdev8259.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 (53) hide show
  1. package/.prettierignore +1 -1
  2. package/LICENSE +661 -661
  3. package/README.md +147 -147
  4. package/demo/index.html +28 -28
  5. package/dist/index.d.ts +1 -0
  6. package/dist/index.js.map +1 -1
  7. package/dist/src/data/menus.js.map +1 -1
  8. package/dist/src/dropdown-menu.js +26 -26
  9. package/dist/src/dropdown-menu.js.map +1 -1
  10. package/dist/src/ia-topnav.d.ts +4 -1
  11. package/dist/src/ia-topnav.js +96 -81
  12. package/dist/src/ia-topnav.js.map +1 -1
  13. package/dist/src/lib/keyboard-navigation.js.map +1 -1
  14. package/dist/src/login-button.js +17 -17
  15. package/dist/src/login-button.js.map +1 -1
  16. package/dist/src/media-menu.js +21 -21
  17. package/dist/src/media-menu.js.map +1 -1
  18. package/dist/src/models.d.ts +1 -0
  19. package/dist/src/models.js.map +1 -1
  20. package/dist/src/primary-nav.d.ts +3 -1
  21. package/dist/src/primary-nav.js +118 -95
  22. package/dist/src/primary-nav.js.map +1 -1
  23. package/dist/src/styles/login-button.js +87 -87
  24. package/dist/src/styles/login-button.js.map +1 -1
  25. package/dist/src/styles/primary-nav.js +343 -308
  26. package/dist/src/styles/primary-nav.js.map +1 -1
  27. package/dist/src/user-menu.js +13 -13
  28. package/dist/src/user-menu.js.map +1 -1
  29. package/dist/test/ia-topnav.test.js +39 -9
  30. package/dist/test/ia-topnav.test.js.map +1 -1
  31. package/dist/test/primary-nav.test.js +55 -7
  32. package/dist/test/primary-nav.test.js.map +1 -1
  33. package/eslint.config.mjs +53 -53
  34. package/index.ts +4 -3
  35. package/package.json +72 -72
  36. package/prettier.config.js +9 -9
  37. package/src/data/menus.ts +652 -652
  38. package/src/dropdown-menu.ts +132 -132
  39. package/src/ia-topnav.ts +383 -366
  40. package/src/lib/keyboard-navigation.ts +166 -166
  41. package/src/login-button.ts +78 -78
  42. package/src/media-menu.ts +143 -143
  43. package/src/models.ts +65 -63
  44. package/src/primary-nav.ts +324 -296
  45. package/src/styles/login-button.ts +90 -90
  46. package/src/styles/primary-nav.ts +346 -311
  47. package/src/user-menu.ts +32 -32
  48. package/ssl/server.key +28 -28
  49. package/test/ia-topnav.test.ts +381 -343
  50. package/test/primary-nav.test.ts +163 -94
  51. package/tsconfig.json +31 -31
  52. package/web-dev-server.config.mjs +32 -32
  53. package/web-test-runner.config.mjs +41 -41
@@ -1,132 +1,132 @@
1
- import { CSSResult, html, nothing, PropertyValues, TemplateResult } from 'lit';
2
- import { property } from 'lit/decorators.js';
3
-
4
- import icons from './assets/img/icons';
5
- import { defaultTopNavConfig } from './data/menus';
6
- import formatUrl from './lib/format-url';
7
- import { makeBooleanString } from './lib/make-boolean-string';
8
- import { IATopNavConfig, IATopNavLink } from './models';
9
- import dropdownMenuCSS from './styles/dropdown-menu';
10
- import TrackedElement from './tracked-element';
11
- import { ifDefined } from 'lit/directives/if-defined.js';
12
- import KeyboardNavigation from './lib/keyboard-navigation';
13
-
14
- export default class DropdownMenu extends TrackedElement {
15
- @property({ type: String }) baseHost = '';
16
- @property({ type: Object }) config: IATopNavConfig = defaultTopNavConfig;
17
- @property({ type: Boolean }) hideSearch = false;
18
- @property({ type: Array }) menuItems: IATopNavLink[] | IATopNavLink[][] = [];
19
- @property({ type: Boolean }) animated = false;
20
- @property({ type: Boolean }) open = false;
21
-
22
- private previousKeydownListener?: // eslint-disable-next-line @typescript-eslint/no-explicit-any
23
- (this: HTMLElement, ev: KeyboardEvent) => any;
24
-
25
- static get styles(): CSSResult[] {
26
- return [dropdownMenuCSS];
27
- }
28
-
29
- updated(props: PropertyValues) {
30
- if (props.has('open') && this.open) {
31
- const container = this.shadowRoot?.querySelector(
32
- '.nav-container',
33
- ) as HTMLElement;
34
-
35
- if (container) {
36
- const keyboardNavigation = new KeyboardNavigation(
37
- container,
38
- 'usermenu',
39
- );
40
- this.addEventListener('keydown', keyboardNavigation.handleKeyDown);
41
- if (this.previousKeydownListener) {
42
- this.removeEventListener('keydown', this.previousKeydownListener);
43
- }
44
- this.previousKeydownListener = keyboardNavigation.handleKeyDown;
45
- }
46
- }
47
- }
48
-
49
- get dropdownItems() {
50
- if (!this.menuItems) return nothing;
51
-
52
- if (!Array.isArray(this.menuItems[0])) {
53
- const submenu = this.menuItems as IATopNavLink[];
54
- return this.dropdownSection(submenu);
55
- }
56
- return this.menuItems.map((submenu, i) => {
57
- const joiner = i ? DropdownMenu.dropdownDivider : html``;
58
- if (!Array.isArray(submenu)) {
59
- return;
60
- }
61
- return [joiner, ...this.dropdownSection(submenu)];
62
- });
63
- }
64
-
65
- static get dropdownDivider() {
66
- return html`<li class="divider"></li>`;
67
- }
68
-
69
- private dropdownSection(submenu: IATopNavLink[]): TemplateResult[] {
70
- return submenu.map(
71
- (item) => html`
72
- <li>
73
- ${item.url
74
- ? this.dropdownLink(item)
75
- : DropdownMenu.dropdownText(item)}
76
- </li>
77
- `,
78
- );
79
- }
80
-
81
- dropdownLink(link: IATopNavLink): TemplateResult {
82
- const calloutText = this.config?.callouts?.[link.title];
83
- const isMobileUpload = link.class === 'mobile-upload';
84
- const isTabbable = this.open && !isMobileUpload;
85
-
86
- return html`<a
87
- href="${formatUrl(link.url, this.baseHost)}"
88
- class=${ifDefined(link.class)}
89
- tabindex="${isTabbable ? '' : '-1'}"
90
- @click=${this.trackClick}
91
- data-event-click-tracking="${this.config
92
- ?.eventCategory}|Nav${link.analyticsEvent}"
93
- aria-label=${calloutText ? `New feature: ${link.title}` : nothing}
94
- >
95
- ${isMobileUpload ? icons.uploadUnpadded : nothing} ${link.title}
96
- ${calloutText
97
- ? html`<span class="callout" aria-hidden="true">${calloutText}</span>`
98
- : nothing}
99
- </a>`;
100
- }
101
-
102
- static dropdownText(item: IATopNavLink) {
103
- return html`<span class="info-item">${item.title}</span>`;
104
- }
105
-
106
- get menuClass() {
107
- const hiddenClass = this.hideSearch ? ' search-hidden' : '';
108
- if (this.open) {
109
- return `open${hiddenClass}`;
110
- }
111
- if (this.animated) {
112
- return `closed${hiddenClass}`;
113
- }
114
- return `initial${hiddenClass}`;
115
- }
116
-
117
- render() {
118
- return html`
119
- <div class="nav-container">
120
- <nav
121
- class="${this.menuClass}"
122
- aria-hidden="${makeBooleanString(!this.open)}"
123
- aria-expanded="${makeBooleanString(this.open)}"
124
- >
125
- <ul>
126
- ${this.dropdownItems}
127
- </ul>
128
- </nav>
129
- </div>
130
- `;
131
- }
132
- }
1
+ import { CSSResult, html, nothing, PropertyValues, TemplateResult } from 'lit';
2
+ import { property } from 'lit/decorators.js';
3
+
4
+ import icons from './assets/img/icons';
5
+ import { defaultTopNavConfig } from './data/menus';
6
+ import formatUrl from './lib/format-url';
7
+ import { makeBooleanString } from './lib/make-boolean-string';
8
+ import { IATopNavConfig, IATopNavLink } from './models';
9
+ import dropdownMenuCSS from './styles/dropdown-menu';
10
+ import TrackedElement from './tracked-element';
11
+ import { ifDefined } from 'lit/directives/if-defined.js';
12
+ import KeyboardNavigation from './lib/keyboard-navigation';
13
+
14
+ export default class DropdownMenu extends TrackedElement {
15
+ @property({ type: String }) baseHost = '';
16
+ @property({ type: Object }) config: IATopNavConfig = defaultTopNavConfig;
17
+ @property({ type: Boolean }) hideSearch = false;
18
+ @property({ type: Array }) menuItems: IATopNavLink[] | IATopNavLink[][] = [];
19
+ @property({ type: Boolean }) animated = false;
20
+ @property({ type: Boolean }) open = false;
21
+
22
+ private previousKeydownListener?: // eslint-disable-next-line @typescript-eslint/no-explicit-any
23
+ (this: HTMLElement, ev: KeyboardEvent) => any;
24
+
25
+ static get styles(): CSSResult[] {
26
+ return [dropdownMenuCSS];
27
+ }
28
+
29
+ updated(props: PropertyValues) {
30
+ if (props.has('open') && this.open) {
31
+ const container = this.shadowRoot?.querySelector(
32
+ '.nav-container',
33
+ ) as HTMLElement;
34
+
35
+ if (container) {
36
+ const keyboardNavigation = new KeyboardNavigation(
37
+ container,
38
+ 'usermenu',
39
+ );
40
+ this.addEventListener('keydown', keyboardNavigation.handleKeyDown);
41
+ if (this.previousKeydownListener) {
42
+ this.removeEventListener('keydown', this.previousKeydownListener);
43
+ }
44
+ this.previousKeydownListener = keyboardNavigation.handleKeyDown;
45
+ }
46
+ }
47
+ }
48
+
49
+ get dropdownItems() {
50
+ if (!this.menuItems) return nothing;
51
+
52
+ if (!Array.isArray(this.menuItems[0])) {
53
+ const submenu = this.menuItems as IATopNavLink[];
54
+ return this.dropdownSection(submenu);
55
+ }
56
+ return this.menuItems.map((submenu, i) => {
57
+ const joiner = i ? DropdownMenu.dropdownDivider : html``;
58
+ if (!Array.isArray(submenu)) {
59
+ return;
60
+ }
61
+ return [joiner, ...this.dropdownSection(submenu)];
62
+ });
63
+ }
64
+
65
+ static get dropdownDivider() {
66
+ return html`<li class="divider"></li>`;
67
+ }
68
+
69
+ private dropdownSection(submenu: IATopNavLink[]): TemplateResult[] {
70
+ return submenu.map(
71
+ (item) => html`
72
+ <li>
73
+ ${item.url
74
+ ? this.dropdownLink(item)
75
+ : DropdownMenu.dropdownText(item)}
76
+ </li>
77
+ `,
78
+ );
79
+ }
80
+
81
+ dropdownLink(link: IATopNavLink): TemplateResult {
82
+ const calloutText = this.config?.callouts?.[link.title];
83
+ const isMobileUpload = link.class === 'mobile-upload';
84
+ const isTabbable = this.open && !isMobileUpload;
85
+
86
+ return html`<a
87
+ href="${formatUrl(link.url, this.baseHost)}"
88
+ class=${ifDefined(link.class)}
89
+ tabindex="${isTabbable ? '' : '-1'}"
90
+ @click=${this.trackClick}
91
+ data-event-click-tracking="${this.config
92
+ ?.eventCategory}|Nav${link.analyticsEvent}"
93
+ aria-label=${calloutText ? `New feature: ${link.title}` : nothing}
94
+ >
95
+ ${isMobileUpload ? icons.uploadUnpadded : nothing} ${link.title}
96
+ ${calloutText
97
+ ? html`<span class="callout" aria-hidden="true">${calloutText}</span>`
98
+ : nothing}
99
+ </a>`;
100
+ }
101
+
102
+ static dropdownText(item: IATopNavLink) {
103
+ return html`<span class="info-item">${item.title}</span>`;
104
+ }
105
+
106
+ get menuClass() {
107
+ const hiddenClass = this.hideSearch ? ' search-hidden' : '';
108
+ if (this.open) {
109
+ return `open${hiddenClass}`;
110
+ }
111
+ if (this.animated) {
112
+ return `closed${hiddenClass}`;
113
+ }
114
+ return `initial${hiddenClass}`;
115
+ }
116
+
117
+ render() {
118
+ return html`
119
+ <div class="nav-container">
120
+ <nav
121
+ class="${this.menuClass}"
122
+ aria-hidden="${makeBooleanString(!this.open)}"
123
+ aria-expanded="${makeBooleanString(this.open)}"
124
+ >
125
+ <ul>
126
+ ${this.dropdownItems}
127
+ </ul>
128
+ </nav>
129
+ </div>
130
+ `;
131
+ }
132
+ }