@internetarchive/ia-topnav 1.3.9 → 1.3.10-webdev-7394.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 (393) hide show
  1. package/.prettierignore +1 -0
  2. package/README.md +7 -7
  3. package/demo/app-root.ts +186 -0
  4. package/demo/index.html +27 -0
  5. package/dist/demo/app-root.d.ts +8 -0
  6. package/dist/demo/app-root.js +181 -0
  7. package/dist/demo/app-root.js.map +1 -0
  8. package/dist/index.d.ts +2 -0
  9. package/dist/index.js +3 -0
  10. package/dist/index.js.map +1 -0
  11. package/dist/src/assets/img/hamburger.d.ts +7 -0
  12. package/dist/src/assets/img/hamburger.js +51 -0
  13. package/dist/src/assets/img/hamburger.js.map +1 -0
  14. package/dist/src/assets/img/ia-icon.d.ts +7 -0
  15. package/dist/src/assets/img/ia-icon.js +33 -0
  16. package/dist/src/assets/img/ia-icon.js.map +1 -0
  17. package/dist/src/assets/img/icon-audio.d.ts +2 -0
  18. package/dist/src/assets/img/icon-audio.js +28 -0
  19. package/dist/src/assets/img/icon-audio.js.map +1 -0
  20. package/dist/src/assets/img/icon-close.d.ts +2 -0
  21. package/dist/src/assets/img/icon-close.js +20 -0
  22. package/dist/src/assets/img/icon-close.js.map +1 -0
  23. package/dist/src/assets/img/icon-donate-unpadded.d.ts +2 -0
  24. package/dist/src/assets/img/icon-donate-unpadded.js +19 -0
  25. package/dist/src/assets/img/icon-donate-unpadded.js.map +1 -0
  26. package/dist/src/assets/img/icon-donate.d.ts +2 -0
  27. package/dist/src/assets/img/icon-donate.js +18 -0
  28. package/dist/src/assets/img/icon-donate.js.map +1 -0
  29. package/dist/src/assets/img/icon-ellipses.d.ts +2 -0
  30. package/dist/src/assets/img/icon-ellipses.js +19 -0
  31. package/dist/src/assets/img/icon-ellipses.js.map +1 -0
  32. package/dist/src/assets/img/icon-ia-logo.d.ts +2 -0
  33. package/dist/src/assets/img/icon-ia-logo.js +30 -0
  34. package/dist/src/assets/img/icon-ia-logo.js.map +1 -0
  35. package/dist/src/assets/img/icon-images.d.ts +2 -0
  36. package/dist/src/assets/img/icon-images.js +19 -0
  37. package/dist/src/assets/img/icon-images.js.map +1 -0
  38. package/dist/src/assets/img/icon-search.d.ts +2 -0
  39. package/dist/src/assets/img/icon-search.js +19 -0
  40. package/dist/src/assets/img/icon-search.js.map +1 -0
  41. package/dist/src/assets/img/icon-software.d.ts +2 -0
  42. package/dist/src/assets/img/icon-software.js +18 -0
  43. package/dist/src/assets/img/icon-software.js.map +1 -0
  44. package/dist/src/assets/img/icon-texts.d.ts +2 -0
  45. package/dist/src/assets/img/icon-texts.js +18 -0
  46. package/dist/src/assets/img/icon-texts.js.map +1 -0
  47. package/dist/src/assets/img/icon-upload-unpadded.d.ts +2 -0
  48. package/dist/src/assets/img/icon-upload-unpadded.js +18 -0
  49. package/dist/src/assets/img/icon-upload-unpadded.js.map +1 -0
  50. package/dist/src/assets/img/icon-upload.d.ts +2 -0
  51. package/dist/src/assets/img/icon-upload.js +21 -0
  52. package/dist/src/assets/img/icon-upload.js.map +1 -0
  53. package/dist/src/assets/img/icon-user.d.ts +2 -0
  54. package/dist/src/assets/img/icon-user.js +19 -0
  55. package/dist/src/assets/img/icon-user.js.map +1 -0
  56. package/dist/src/assets/img/icon-video.d.ts +2 -0
  57. package/dist/src/assets/img/icon-video.js +19 -0
  58. package/dist/src/assets/img/icon-video.js.map +1 -0
  59. package/dist/src/assets/img/icon-web.d.ts +2 -0
  60. package/dist/src/assets/img/icon-web.js +19 -0
  61. package/dist/src/assets/img/icon-web.js.map +1 -0
  62. package/dist/src/assets/img/icon.d.ts +5 -0
  63. package/dist/src/assets/img/icon.js +17 -0
  64. package/dist/src/assets/img/icon.js.map +1 -0
  65. package/dist/src/assets/img/icons.d.ts +18 -0
  66. package/dist/src/assets/img/icons.js +33 -0
  67. package/dist/src/assets/img/icons.js.map +1 -0
  68. package/dist/src/assets/img/wordmark-stacked.d.ts +2 -0
  69. package/dist/src/assets/img/wordmark-stacked.js +13 -0
  70. package/dist/src/assets/img/wordmark-stacked.js.map +1 -0
  71. package/dist/src/data/menus.d.ts +20 -0
  72. package/dist/src/data/menus.js +668 -0
  73. package/dist/src/data/menus.js.map +1 -0
  74. package/dist/src/desktop-subnav.d.ts +11 -0
  75. package/dist/src/desktop-subnav.js +55 -0
  76. package/dist/src/desktop-subnav.js.map +1 -0
  77. package/dist/src/dropdown-menu.d.ts +19 -0
  78. package/dist/src/dropdown-menu.js +115 -0
  79. package/dist/src/dropdown-menu.js.map +1 -0
  80. package/dist/src/ia-topnav.d.ts +68 -0
  81. package/dist/src/ia-topnav.js +315 -0
  82. package/dist/src/ia-topnav.js.map +1 -0
  83. package/dist/src/lib/formatUrl.d.ts +2 -0
  84. package/dist/src/lib/formatUrl.js +2 -0
  85. package/dist/src/lib/formatUrl.js.map +1 -0
  86. package/dist/src/lib/keyboard-navigation.d.ts +50 -0
  87. package/dist/src/lib/keyboard-navigation.js +136 -0
  88. package/dist/src/lib/keyboard-navigation.js.map +1 -0
  89. package/dist/src/lib/location-handler.d.ts +1 -0
  90. package/dist/src/lib/location-handler.js +5 -0
  91. package/dist/src/lib/location-handler.js.map +1 -0
  92. package/dist/src/lib/makeBooleanString.d.ts +2 -0
  93. package/dist/src/lib/makeBooleanString.js +12 -0
  94. package/dist/src/lib/makeBooleanString.js.map +1 -0
  95. package/dist/src/lib/query-handler.d.ts +4 -0
  96. package/dist/src/lib/query-handler.js +7 -0
  97. package/dist/src/lib/query-handler.js.map +1 -0
  98. package/dist/src/lib/toSentenceCase.d.ts +2 -0
  99. package/dist/src/lib/toSentenceCase.js +10 -0
  100. package/dist/src/lib/toSentenceCase.js.map +1 -0
  101. package/dist/src/login-button.d.ts +16 -0
  102. package/dist/src/login-button.js +83 -0
  103. package/dist/src/login-button.js.map +1 -0
  104. package/dist/src/media-button.d.ts +24 -0
  105. package/dist/src/media-button.js +119 -0
  106. package/dist/src/media-button.js.map +1 -0
  107. package/dist/src/media-menu.d.ts +20 -0
  108. package/dist/src/media-menu.js +148 -0
  109. package/dist/src/media-menu.js.map +1 -0
  110. package/dist/src/media-slider.d.ts +15 -0
  111. package/dist/src/media-slider.js +139 -0
  112. package/dist/src/media-slider.js.map +1 -0
  113. package/dist/src/media-subnav.d.ts +18 -0
  114. package/dist/src/media-subnav.js +126 -0
  115. package/dist/src/media-subnav.js.map +1 -0
  116. package/dist/src/models.d.ts +51 -0
  117. package/dist/src/models.js +25 -0
  118. package/dist/src/models.js.map +1 -0
  119. package/dist/src/more-slider.d.ts +10 -0
  120. package/dist/src/more-slider.js +50 -0
  121. package/dist/src/more-slider.js.map +1 -0
  122. package/dist/src/nav-search.d.ts +19 -0
  123. package/dist/src/nav-search.js +123 -0
  124. package/dist/src/nav-search.js.map +1 -0
  125. package/dist/src/primary-nav.d.ts +45 -0
  126. package/dist/src/primary-nav.js +280 -0
  127. package/dist/src/primary-nav.js.map +1 -0
  128. package/dist/src/save-page-form.d.ts +10 -0
  129. package/dist/src/save-page-form.js +63 -0
  130. package/dist/src/save-page-form.js.map +1 -0
  131. package/dist/src/search-menu.d.ts +20 -0
  132. package/dist/src/search-menu.js +162 -0
  133. package/dist/src/search-menu.js.map +1 -0
  134. package/dist/src/signed-out-dropdown.d.ts +4 -0
  135. package/dist/src/signed-out-dropdown.js +15 -0
  136. package/dist/src/signed-out-dropdown.js.map +1 -0
  137. package/dist/src/styles/base.d.ts +1 -0
  138. package/dist/src/styles/base.js +48 -0
  139. package/dist/src/styles/base.js.map +1 -0
  140. package/dist/src/styles/desktop-subnav.d.ts +2 -0
  141. package/dist/src/styles/desktop-subnav.js +37 -0
  142. package/dist/src/styles/desktop-subnav.js.map +1 -0
  143. package/dist/src/styles/dropdown-menu.d.ts +2 -0
  144. package/dist/src/styles/dropdown-menu.js +170 -0
  145. package/dist/src/styles/dropdown-menu.js.map +1 -0
  146. package/dist/src/styles/ia-topnav.d.ts +2 -0
  147. package/dist/src/styles/ia-topnav.js +87 -0
  148. package/dist/src/styles/ia-topnav.js.map +1 -0
  149. package/dist/src/styles/login-button.d.ts +2 -0
  150. package/dist/src/styles/login-button.js +82 -0
  151. package/dist/src/styles/login-button.js.map +1 -0
  152. package/dist/src/styles/media-button.d.ts +2 -0
  153. package/dist/src/styles/media-button.js +156 -0
  154. package/dist/src/styles/media-button.js.map +1 -0
  155. package/dist/src/styles/media-menu.d.ts +2 -0
  156. package/dist/src/styles/media-menu.js +66 -0
  157. package/dist/src/styles/media-menu.js.map +1 -0
  158. package/dist/src/styles/media-slider.d.ts +2 -0
  159. package/dist/src/styles/media-slider.js +81 -0
  160. package/dist/src/styles/media-slider.js.map +1 -0
  161. package/dist/src/styles/media-subnav.d.ts +2 -0
  162. package/dist/src/styles/media-subnav.js +159 -0
  163. package/dist/src/styles/media-subnav.js.map +1 -0
  164. package/dist/src/styles/more-slider.d.ts +2 -0
  165. package/dist/src/styles/more-slider.js +15 -0
  166. package/dist/src/styles/more-slider.js.map +1 -0
  167. package/dist/src/styles/nav-search.d.ts +2 -0
  168. package/dist/src/styles/nav-search.js +136 -0
  169. package/dist/src/styles/nav-search.js.map +1 -0
  170. package/dist/src/styles/primary-nav.d.ts +2 -0
  171. package/dist/src/styles/primary-nav.js +310 -0
  172. package/dist/src/styles/primary-nav.js.map +1 -0
  173. package/dist/src/styles/save-page-form.d.ts +2 -0
  174. package/dist/src/styles/save-page-form.js +54 -0
  175. package/dist/src/styles/save-page-form.js.map +1 -0
  176. package/dist/src/styles/search-menu.d.ts +2 -0
  177. package/dist/src/styles/search-menu.js +105 -0
  178. package/dist/src/styles/search-menu.js.map +1 -0
  179. package/dist/src/styles/signed-out-dropdown.d.ts +2 -0
  180. package/dist/src/styles/signed-out-dropdown.js +31 -0
  181. package/dist/src/styles/signed-out-dropdown.js.map +1 -0
  182. package/dist/src/styles/user-menu.d.ts +2 -0
  183. package/dist/src/styles/user-menu.js +31 -0
  184. package/dist/src/styles/user-menu.js.map +1 -0
  185. package/dist/src/styles/wayback-search.d.ts +2 -0
  186. package/dist/src/styles/wayback-search.js +48 -0
  187. package/dist/src/styles/wayback-search.js.map +1 -0
  188. package/dist/src/styles/wayback-slider.d.ts +2 -0
  189. package/dist/src/styles/wayback-slider.js +33 -0
  190. package/dist/src/styles/wayback-slider.js.map +1 -0
  191. package/dist/src/tracked-element.d.ts +5 -0
  192. package/dist/src/tracked-element.js +30 -0
  193. package/dist/src/tracked-element.js.map +1 -0
  194. package/dist/src/user-menu.d.ts +10 -0
  195. package/dist/src/user-menu.js +60 -0
  196. package/dist/src/user-menu.js.map +1 -0
  197. package/dist/src/wayback-search.d.ts +4 -0
  198. package/dist/src/wayback-search.js +14 -0
  199. package/dist/src/wayback-search.js.map +1 -0
  200. package/dist/src/wayback-slider.d.ts +18 -0
  201. package/dist/src/wayback-slider.js +99 -0
  202. package/dist/src/wayback-slider.js.map +1 -0
  203. package/dist/test/assets/img/hamburger.test.d.ts +1 -0
  204. package/dist/test/assets/img/hamburger.test.js +13 -0
  205. package/dist/test/assets/img/hamburger.test.js.map +1 -0
  206. package/dist/test/assets/img/user.test.d.ts +1 -0
  207. package/dist/test/assets/img/user.test.js +12 -0
  208. package/dist/test/assets/img/user.test.js.map +1 -0
  209. package/dist/test/data/menus.test.d.ts +1 -0
  210. package/dist/test/data/menus.test.js +11 -0
  211. package/dist/test/data/menus.test.js.map +1 -0
  212. package/dist/test/dropdown-menu.test.d.ts +1 -0
  213. package/dist/test/dropdown-menu.test.js +20 -0
  214. package/dist/test/dropdown-menu.test.js.map +1 -0
  215. package/dist/test/ia-icon.test.d.ts +1 -0
  216. package/dist/test/ia-icon.test.js +11 -0
  217. package/dist/test/ia-icon.test.js.map +1 -0
  218. package/dist/test/ia-topnav.test.d.ts +1 -0
  219. package/dist/test/ia-topnav.test.js +232 -0
  220. package/dist/test/ia-topnav.test.js.map +1 -0
  221. package/dist/test/login-button.test.d.ts +1 -0
  222. package/dist/test/login-button.test.js +14 -0
  223. package/dist/test/login-button.test.js.map +1 -0
  224. package/dist/test/media-button.test.d.ts +1 -0
  225. package/dist/test/media-button.test.js +13 -0
  226. package/dist/test/media-button.test.js.map +1 -0
  227. package/dist/test/media-menu.test.d.ts +1 -0
  228. package/dist/test/media-menu.test.js +27 -0
  229. package/dist/test/media-menu.test.js.map +1 -0
  230. package/dist/test/media-slider.test.d.ts +1 -0
  231. package/dist/test/media-slider.test.js +47 -0
  232. package/dist/test/media-slider.test.js.map +1 -0
  233. package/dist/test/more-slider.test.d.ts +1 -0
  234. package/dist/test/more-slider.test.js +17 -0
  235. package/dist/test/more-slider.test.js.map +1 -0
  236. package/dist/test/nav-search.test.d.ts +1 -0
  237. package/dist/test/nav-search.test.js +47 -0
  238. package/dist/test/nav-search.test.js.map +1 -0
  239. package/dist/test/primary-nav.test.d.ts +1 -0
  240. package/dist/test/primary-nav.test.js +65 -0
  241. package/dist/test/primary-nav.test.js.map +1 -0
  242. package/dist/test/save-page-form.test.d.ts +1 -0
  243. package/dist/test/save-page-form.test.js +47 -0
  244. package/dist/test/save-page-form.test.js.map +1 -0
  245. package/dist/test/search-menu.test.d.ts +1 -0
  246. package/dist/test/search-menu.test.js +42 -0
  247. package/dist/test/search-menu.test.js.map +1 -0
  248. package/dist/test/user-menu.test.d.ts +1 -0
  249. package/dist/test/user-menu.test.js +28 -0
  250. package/dist/test/user-menu.test.js.map +1 -0
  251. package/dist/test/wayback-slider.test.d.ts +1 -0
  252. package/dist/test/wayback-slider.test.js +80 -0
  253. package/dist/test/wayback-slider.test.js.map +1 -0
  254. package/eslint.config.mjs +53 -0
  255. package/package.json +47 -37
  256. package/prettier.config.js +9 -0
  257. package/src/assets/img/hamburger.ts +49 -0
  258. package/src/assets/img/{ia-icon.js → ia-icon.ts} +7 -16
  259. package/src/assets/img/{icon-audio.js → icon-audio.ts} +7 -2
  260. package/src/assets/img/icon-close.ts +20 -0
  261. package/src/assets/img/icon-donate-unpadded.ts +19 -0
  262. package/src/assets/img/icon-donate.ts +18 -0
  263. package/src/assets/img/icon-ellipses.ts +19 -0
  264. package/src/assets/img/icon-ia-logo.ts +30 -0
  265. package/src/assets/img/icon-images.ts +19 -0
  266. package/src/assets/img/icon-search.ts +19 -0
  267. package/src/assets/img/icon-software.ts +18 -0
  268. package/src/assets/img/icon-texts.ts +18 -0
  269. package/src/assets/img/{icon-upload-unpadded.js → icon-upload-unpadded.ts} +6 -2
  270. package/src/assets/img/icon-upload.ts +21 -0
  271. package/src/assets/img/icon-user.ts +19 -0
  272. package/src/assets/img/icon-video.ts +19 -0
  273. package/src/assets/img/icon-web.ts +19 -0
  274. package/src/assets/img/icon.ts +8 -0
  275. package/src/assets/img/icons.ts +33 -0
  276. package/src/assets/img/{wordmark-stacked.js → wordmark-stacked.ts} +1 -1
  277. package/src/data/{menus.js → menus.ts} +172 -135
  278. package/src/desktop-subnav.ts +49 -0
  279. package/src/dropdown-menu.ts +105 -0
  280. package/src/{ia-topnav.js → ia-topnav.ts} +130 -127
  281. package/src/lib/formatUrl.ts +2 -0
  282. package/src/lib/{keyboard-navigation.js → keyboard-navigation.ts} +53 -23
  283. package/src/lib/location-handler.ts +5 -0
  284. package/src/lib/makeBooleanString.ts +12 -0
  285. package/src/lib/query-handler.ts +7 -0
  286. package/src/lib/toSentenceCase.ts +10 -0
  287. package/src/{login-button.js → login-button.ts} +27 -31
  288. package/src/{media-button.js → media-button.ts} +39 -49
  289. package/src/media-menu.ts +143 -0
  290. package/src/{media-slider.js → media-slider.ts} +53 -41
  291. package/src/media-subnav.ts +132 -0
  292. package/src/models.ts +114 -0
  293. package/src/more-slider.ts +42 -0
  294. package/src/nav-search.ts +113 -0
  295. package/src/primary-nav.ts +266 -0
  296. package/src/save-page-form.ts +59 -0
  297. package/src/search-menu.ts +156 -0
  298. package/src/signed-out-dropdown.ts +11 -0
  299. package/src/styles/{base.js → base.ts} +2 -2
  300. package/src/styles/{desktop-subnav.js → desktop-subnav.ts} +2 -2
  301. package/src/styles/{dropdown-menu.js → dropdown-menu.ts} +4 -2
  302. package/src/styles/{ia-topnav.js → ia-topnav.ts} +1 -1
  303. package/src/styles/{login-button.js → login-button.ts} +1 -1
  304. package/src/styles/{media-button.js → media-button.ts} +2 -2
  305. package/src/styles/{media-menu.js → media-menu.ts} +1 -1
  306. package/src/styles/{media-slider.js → media-slider.ts} +1 -1
  307. package/src/styles/media-subnav.ts +159 -0
  308. package/src/styles/{more-slider.js → more-slider.ts} +1 -1
  309. package/src/styles/{nav-search.js → nav-search.ts} +2 -2
  310. package/src/styles/{primary-nav.js → primary-nav.ts} +2 -3
  311. package/src/styles/{save-page-form.js → save-page-form.ts} +7 -7
  312. package/src/styles/{search-menu.js → search-menu.ts} +1 -1
  313. package/src/styles/{signed-out-dropdown.js → signed-out-dropdown.ts} +1 -1
  314. package/src/styles/{user-menu.js → user-menu.ts} +1 -1
  315. package/src/styles/{wayback-search.js → wayback-search.ts} +3 -3
  316. package/src/styles/wayback-slider.ts +33 -0
  317. package/src/tracked-element.ts +32 -0
  318. package/src/user-menu.ts +57 -0
  319. package/src/wayback-search.ts +10 -0
  320. package/src/wayback-slider.ts +88 -0
  321. package/ssl/server.crt +22 -0
  322. package/ssl/server.key +28 -0
  323. package/test/assets/img/hamburger.test.ts +18 -0
  324. package/test/assets/img/user.test.ts +15 -0
  325. package/test/data/menus.test.ts +15 -0
  326. package/test/{dropdown-menu.test.js → dropdown-menu.test.ts} +4 -4
  327. package/test/{ia-icon.test.js → ia-icon.test.ts} +6 -4
  328. package/test/ia-topnav.test.ts +344 -0
  329. package/test/login-button.test.ts +19 -0
  330. package/test/media-button.test.ts +19 -0
  331. package/test/{media-menu.test.js → media-menu.test.ts} +14 -12
  332. package/test/media-slider.test.ts +63 -0
  333. package/test/more-slider.test.ts +21 -0
  334. package/test/nav-search.test.ts +70 -0
  335. package/test/primary-nav.test.ts +110 -0
  336. package/test/save-page-form.test.ts +62 -0
  337. package/test/{search-menu.test.js → search-menu.test.ts} +19 -10
  338. package/test/{user-menu.test.js → user-menu.test.ts} +10 -9
  339. package/test/wayback-slider.test.ts +97 -0
  340. package/tsconfig.json +31 -0
  341. package/web-dev-server.config.mjs +32 -0
  342. package/web-test-runner.config.mjs +41 -0
  343. package/.eslintrc +0 -16
  344. package/index.d.ts +0 -109
  345. package/src/assets/img/hamburger.js +0 -38
  346. package/src/assets/img/icon-close.js +0 -16
  347. package/src/assets/img/icon-donate-unpadded.js +0 -16
  348. package/src/assets/img/icon-donate.js +0 -15
  349. package/src/assets/img/icon-ellipses.js +0 -15
  350. package/src/assets/img/icon-ia-logo.js +0 -22
  351. package/src/assets/img/icon-images.js +0 -15
  352. package/src/assets/img/icon-search.js +0 -15
  353. package/src/assets/img/icon-software.js +0 -15
  354. package/src/assets/img/icon-texts.js +0 -15
  355. package/src/assets/img/icon-upload.js +0 -15
  356. package/src/assets/img/icon-user.js +0 -15
  357. package/src/assets/img/icon-video.js +0 -15
  358. package/src/assets/img/icon-web.js +0 -15
  359. package/src/assets/img/icon.js +0 -18
  360. package/src/assets/img/icons.js +0 -33
  361. package/src/desktop-subnav.js +0 -45
  362. package/src/dropdown-menu.js +0 -110
  363. package/src/lib/formatUrl.js +0 -1
  364. package/src/lib/location-handler.js +0 -5
  365. package/src/lib/query-handler.js +0 -7
  366. package/src/lib/toSentenceCase.js +0 -8
  367. package/src/media-menu.js +0 -154
  368. package/src/media-subnav.js +0 -112
  369. package/src/more-slider.js +0 -33
  370. package/src/nav-search.js +0 -111
  371. package/src/primary-nav.js +0 -258
  372. package/src/save-page-form.js +0 -59
  373. package/src/search-menu.js +0 -145
  374. package/src/signed-out-dropdown.js +0 -10
  375. package/src/styles/media-subnav.js +0 -156
  376. package/src/styles/wayback-slider.js +0 -30
  377. package/src/tracked-element.js +0 -29
  378. package/src/user-menu.js +0 -56
  379. package/src/wayback-search.js +0 -18
  380. package/src/wayback-slider.js +0 -87
  381. package/test/assets/img/hamburger.test.js +0 -15
  382. package/test/assets/img/user.test.js +0 -15
  383. package/test/data/menus.test.js +0 -19
  384. package/test/ia-topnav.test.js +0 -273
  385. package/test/login-button.test.js +0 -15
  386. package/test/media-button.test.js +0 -19
  387. package/test/media-slider.test.js +0 -57
  388. package/test/more-slider.test.js +0 -13
  389. package/test/nav-search.test.js +0 -61
  390. package/test/primary-nav.test.js +0 -82
  391. package/test/save-page-form.test.js +0 -35
  392. package/test/wayback-slider.test.js +0 -80
  393. /package/{index.js → index.ts} +0 -0
@@ -0,0 +1,49 @@
1
+ import { html, nothing, TemplateResult } from 'lit';
2
+ import { customElement, property } from 'lit/decorators.js';
3
+
4
+ import TrackedElement from './tracked-element';
5
+ import desktopSubnavCSS from './styles/desktop-subnav';
6
+ import icons from './assets/img/icons';
7
+ import formatUrl from './lib/formatUrl';
8
+ import { IATopNavLink } from './models';
9
+
10
+ @customElement('desktop-subnav')
11
+ export class DesktopSubnav extends TrackedElement {
12
+ @property({ type: String }) baseHost = '';
13
+ @property({ type: Array }) menuItems: IATopNavLink[] = [];
14
+
15
+ static get styles() {
16
+ return desktopSubnavCSS;
17
+ }
18
+
19
+ get listItems() {
20
+ return this.menuItems
21
+ ? this.menuItems.map(
22
+ (link) => html`
23
+ <li>
24
+ <a
25
+ class="${link.title.toLowerCase()}"
26
+ .href="${formatUrl(link.url, this.baseHost)}"
27
+ >${link.title}${DesktopSubnav.iconFor(link.title)}</a
28
+ >
29
+ </li>
30
+ `,
31
+ )
32
+ : nothing;
33
+ }
34
+
35
+ static iconFor(title: string): TemplateResult {
36
+ const subnavIcons: Record<string, TemplateResult> = {
37
+ Donate: icons.donate,
38
+ };
39
+ return subnavIcons[title] ? subnavIcons[title] : html``;
40
+ }
41
+
42
+ render() {
43
+ return html`
44
+ <ul>
45
+ ${this.listItems}
46
+ </ul>
47
+ `;
48
+ }
49
+ }
@@ -0,0 +1,105 @@
1
+ import { CSSResult, html, nothing, 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/formatUrl';
7
+ import { makeBooleanString } from './lib/makeBooleanString';
8
+ import { IATopNavConfig, IATopNavLink } from './models';
9
+ import dropdownMenuCSS from './styles/dropdown-menu';
10
+ import TrackedElement from './tracked-element';
11
+
12
+ export default class DropdownMenu extends TrackedElement {
13
+ @property({ type: String }) baseHost = '';
14
+ @property({ type: Object }) config: IATopNavConfig = defaultTopNavConfig;
15
+ @property({ type: Boolean }) hideSearch = false;
16
+ @property({ type: Array }) menuItems: IATopNavLink[] | IATopNavLink[][] = [];
17
+ @property({ type: Boolean }) animated = false;
18
+ @property({ type: Boolean }) open = false;
19
+
20
+ static get styles(): CSSResult[] {
21
+ return [dropdownMenuCSS];
22
+ }
23
+
24
+ get dropdownItems() {
25
+ if (!this.menuItems) return nothing;
26
+
27
+ if (!Array.isArray(this.menuItems[0])) {
28
+ const submenu = this.menuItems as IATopNavLink[];
29
+ return this.dropdownSection(submenu);
30
+ }
31
+ return this.menuItems.map((submenu, i) => {
32
+ const joiner = i ? DropdownMenu.dropdownDivider : html``;
33
+ if (!Array.isArray(submenu)) {
34
+ return;
35
+ }
36
+ return [joiner, ...this.dropdownSection(submenu)];
37
+ });
38
+ }
39
+
40
+ static get dropdownDivider() {
41
+ return html`<li role="presentation" class="divider"></li>`;
42
+ }
43
+
44
+ private dropdownSection(submenu: IATopNavLink[]): TemplateResult[] {
45
+ return submenu.map(
46
+ (item) => html`
47
+ <li>
48
+ ${item.url
49
+ ? this.dropdownLink(item)
50
+ : DropdownMenu.dropdownText(item)}
51
+ </li>
52
+ `,
53
+ );
54
+ }
55
+
56
+ dropdownLink(link: IATopNavLink): TemplateResult {
57
+ const calloutText = this.config?.callouts?.[link.title];
58
+ return html`<a
59
+ .href="${formatUrl(link.url, this.baseHost)}"
60
+ .class="${link.class}"
61
+ tabindex="${this.open ? '' : '-1'}"
62
+ @click=${this.trackClick}
63
+ data-event-click-tracking="${this.config
64
+ ?.eventCategory}|Nav${link.analyticsEvent}"
65
+ aria-label=${calloutText ? `New feature: ${link.title}` : nothing}
66
+ >
67
+ ${link.class === 'mobile-upload' ? icons.uploadUnpadded : nothing}
68
+ ${link.title}
69
+ ${calloutText
70
+ ? html`<span class="callout" aria-hidden="true">${calloutText}</span>`
71
+ : nothing}
72
+ </a>`;
73
+ }
74
+
75
+ static dropdownText(item: IATopNavLink) {
76
+ return html`<span class="info-item">${item.title}</span>`;
77
+ }
78
+
79
+ get menuClass() {
80
+ const hiddenClass = this.hideSearch ? ' search-hidden' : '';
81
+ if (this.open) {
82
+ return `open${hiddenClass}`;
83
+ }
84
+ if (this.animated) {
85
+ return `closed${hiddenClass}`;
86
+ }
87
+ return `initial${hiddenClass}`;
88
+ }
89
+
90
+ render() {
91
+ return html`
92
+ <div class="nav-container">
93
+ <nav
94
+ class="${this.menuClass}"
95
+ aria-hidden="${makeBooleanString(!this.open)}"
96
+ aria-expanded="${makeBooleanString(this.open)}"
97
+ >
98
+ <ul>
99
+ ${this.dropdownItems}
100
+ </ul>
101
+ </nav>
102
+ </div>
103
+ `;
104
+ }
105
+ }
@@ -1,119 +1,115 @@
1
- import { LitElement, html, nothing } from 'https://offshoot.prod.archive.org/lit.js';
2
-
3
- import './primary-nav.js';
4
- import './user-menu.js';
5
- import './search-menu.js';
6
- import './media-slider.js';
7
- import './desktop-subnav.js';
8
- import './dropdown-menu.js';
9
- import './signed-out-dropdown.js';
10
- import iaTopNavCSS from './styles/ia-topnav.js';
11
- import { buildTopNavMenus, defaultTopNavConfig } from './data/menus.js';
12
-
1
+ import { LitElement, PropertyValues, html, nothing } from 'lit';
2
+ import { customElement, property, state } from 'lit/decorators.js';
3
+
4
+ import { buildTopNavMenus, defaultTopNavConfig } from './data/menus';
5
+ import './desktop-subnav';
6
+ import './dropdown-menu';
7
+ import './media-slider';
8
+ import {
9
+ IATopNavConfig,
10
+ IATopNavMenuConfig,
11
+ IATopNavSecondIdentitySlotMode,
12
+ } from './models';
13
+ import './primary-nav';
14
+ import './search-menu';
15
+ import './signed-out-dropdown';
16
+ import iaTopNavCSS from './styles/ia-topnav';
17
+ import './user-menu';
18
+
19
+ @customElement('ia-topnav')
13
20
  export default class IATopNav extends LitElement {
14
- static get styles() {
15
- return iaTopNavCSS;
16
- }
21
+ @property({ type: Boolean }) localLinks = false;
17
22
 
18
- // NOTE:
19
- // When adding properties, also add them to index.d.ts in the root `ia-topnav` directory
20
- // so Typescript can find them
21
- static get properties() {
22
- return {
23
- // we default to fully-qualified `https://archive.org` urls in nav, set to false for relatives
24
- localLinks: Boolean,
25
- // @see `data/menus.js` for a description:
26
- waybackPagesArchived: String,
27
- // the base host is for navigation, so may be empty for relative links
28
- baseHost: { type: String },
29
- // the media base host is the base host for images, such as the profile picture
30
- // which may not be hosted locally
31
- mediaBaseHost: { type: String },
32
- /** Whether the user has privs to edit all items */
33
- admin: { type: Boolean },
34
- /** Whether the user has privs to manage item flags */
35
- canManageFlags: { type: Boolean },
36
- config: {
37
- type: Object,
38
- converter(value) {
39
- return JSON.parse(atob(value));
40
- },
41
- },
42
- hideSearch: { type: Boolean },
43
- /** Identifier for the item or collection currently being viewed */
44
- itemIdentifier: { type: String },
45
- mediaSliderOpen: { type: Boolean },
46
- menus: {
47
- type: Object,
48
- converter(value) {
49
- return JSON.parse(atob(value));
50
- },
51
- },
52
- openMenu: { type: String },
53
- screenName: { type: String },
54
- searchIn: { type: String },
55
- searchQuery: {
56
- type: String,
57
- converter(value) {
58
- return atob(value);
59
- },
60
- },
61
- selectedMenuOption: { type: String },
62
- username: { type: String },
63
- userProfileImagePath: { type: String },
64
- secondIdentitySlotMode: { type: String },
65
- currentTab: { type: Object },
66
- };
23
+ @property({ type: String }) waybackPagesArchived = '';
24
+
25
+ @property({ type: String }) baseHost = 'https://archive.org';
26
+
27
+ @property({ type: String }) mediaBaseHost = 'https://archive.org';
28
+
29
+ @property({ type: Boolean }) admin = false;
30
+
31
+ @property({ type: Boolean }) canManageFlags = false;
32
+
33
+ @property({ type: Object }) config: IATopNavConfig = defaultTopNavConfig;
34
+
35
+ @property({ type: Boolean }) hideSearch = false;
36
+
37
+ @property({ type: String }) itemIdentifier = '';
38
+
39
+ @property({ type: Boolean }) mediaSliderOpen = false;
40
+
41
+ @property({ type: String }) openMenu = '';
42
+
43
+ @property({ type: String }) screenName: string = '';
44
+
45
+ @property({ type: String }) searchIn = '';
46
+
47
+ @property({ type: String }) searchQuery = '';
48
+
49
+ @property({ type: String }) selectedMenuOption = '';
50
+
51
+ @property({ type: String }) username: string = '';
52
+
53
+ @property({ type: String }) userProfileImagePath =
54
+ '/services/img/user/profile';
55
+
56
+ @property({ type: String })
57
+ secondIdentitySlotMode: IATopNavSecondIdentitySlotMode = '';
58
+
59
+ @property({ type: Object }) currentTab?: {
60
+ mediatype: string;
61
+ moveTo: string;
62
+ };
63
+
64
+ @state() private menus: IATopNavMenuConfig = buildTopNavMenus();
65
+
66
+ private get normalizedBaseHost() {
67
+ return !this.localLinks ? this.baseHost : '';
67
68
  }
68
69
 
69
- constructor() {
70
- super();
71
- this.menuSetup();
72
- this.mediaBaseHost = 'https://archive.org';
73
- this.userProfileImagePath = '/services/img/user/profile';
74
- this.config = defaultTopNavConfig;
75
- this.hideSearch = false;
76
- this.mediaSliderOpen = false;
77
- this.openMenu = '';
78
- this.searchIn = '';
79
- this.selectedMenuOption = '';
80
- this.secondIdentitySlotMode = '';
81
- this.currentTab = {};
70
+ static get styles() {
71
+ return iaTopNavCSS;
82
72
  }
83
73
 
84
- updated(props) {
85
- if (props.has('username') || props.has('localLinks') || props.has('baseHost') ||
86
- props.has('waybackPagesArchived') || props.has('itemIdentifier')) {
74
+ updated(props: PropertyValues) {
75
+ if (
76
+ props.has('username') ||
77
+ props.has('waybackPagesArchived') ||
78
+ props.has('itemIdentifier') ||
79
+ props.has('localLinks') ||
80
+ props.has('baseHost')
81
+ ) {
87
82
  this.menuSetup();
88
83
  }
89
84
  }
90
85
 
91
86
  firstUpdated() {
92
- // close open menu on `esc` click
93
- document.addEventListener('keydown', e => {
94
- if (e.key === 'Escape') {
95
- this.openMenu = '';
96
- this.mediaSliderOpen = false;
97
- }
98
- }, false);
87
+ // close open menu on `esc` click
88
+ document.addEventListener(
89
+ 'keydown',
90
+ (e) => {
91
+ if (e.key === 'Escape') {
92
+ this.openMenu = '';
93
+ this.mediaSliderOpen = false;
94
+ }
95
+ },
96
+ false,
97
+ );
99
98
  }
100
99
 
101
100
  menuSetup() {
102
- this.localLinks = this.getAttribute('localLinks') !== 'false' && this.getAttribute('localLinks') !== false;
103
- this.username = this.getAttribute('username')
104
- this.screenName = this.getAttribute('screenname');
105
- this.waybackPagesArchived = this.getAttribute('waybackPagesArchived') ?? ''
106
-
107
- // ensure we update other components that use `baseHost`
108
- this.baseHost = this.localLinks ? '' : 'https://archive.org';
109
-
110
101
  // re/build the nav
111
- this.menus = buildTopNavMenus(this.username, this.localLinks, this.waybackPagesArchived, this.itemIdentifier);
102
+ this.menus = buildTopNavMenus(
103
+ this.username,
104
+ this.normalizedBaseHost,
105
+ this.waybackPagesArchived,
106
+ this.itemIdentifier,
107
+ );
112
108
  }
113
109
 
114
- menuToggled({ detail }) {
110
+ menuToggled(e: CustomEvent) {
115
111
  const currentMenu = this.openMenu;
116
- this.openMenu = currentMenu === detail.menuName ? '' : detail.menuName;
112
+ this.openMenu = currentMenu === e.detail.menuName ? '' : e.detail.menuName;
117
113
  // Keeps media slider open if media menu is open
118
114
  if (this.openMenu === 'media') {
119
115
  return;
@@ -135,32 +131,36 @@ export default class IATopNav extends LitElement {
135
131
  this.closeMediaSlider();
136
132
  }
137
133
 
138
- searchInChanged(e) {
134
+ searchInChanged(e: CustomEvent) {
139
135
  this.searchIn = e.detail.searchIn;
140
136
  }
141
137
 
142
- trackClick({ detail }) {
143
- this.dispatchEvent(new CustomEvent('analyticsClick', {
144
- bubbles: true,
145
- composed: true,
146
- detail,
147
- }));
138
+ trackClick(e: CustomEvent) {
139
+ this.dispatchEvent(
140
+ new CustomEvent('analyticsClick', {
141
+ bubbles: true,
142
+ composed: true,
143
+ detail: e.detail,
144
+ }),
145
+ );
148
146
  }
149
147
 
150
- trackSubmit({ detail }) {
151
- this.dispatchEvent(new CustomEvent('analyticsSubmit', {
152
- bubbles: true,
153
- composed: true,
154
- detail,
155
- }));
148
+ trackSubmit(e: CustomEvent) {
149
+ this.dispatchEvent(
150
+ new CustomEvent('analyticsSubmit', {
151
+ bubbles: true,
152
+ composed: true,
153
+ detail: e.detail,
154
+ }),
155
+ );
156
156
  }
157
157
 
158
- mediaTypeSelected({ detail }) {
159
- if (this.selectedMenuOption === detail.mediatype) {
158
+ mediaTypeSelected(e: CustomEvent) {
159
+ if (this.selectedMenuOption === e.detail.mediatype) {
160
160
  this.closeMediaSlider();
161
161
  return;
162
162
  }
163
- this.selectedMenuOption = detail.mediatype;
163
+ this.selectedMenuOption = e.detail.mediatype;
164
164
  this.openMediaSlider();
165
165
  }
166
166
 
@@ -195,7 +195,7 @@ export default class IATopNav extends LitElement {
195
195
  get userMenu() {
196
196
  return html`
197
197
  <user-menu
198
- .baseHost=${this.baseHost}
198
+ .baseHost=${this.normalizedBaseHost}
199
199
  .config=${this.config}
200
200
  .menuItems=${this.userMenuItems}
201
201
  ?open=${this.openMenu === 'user'}
@@ -204,7 +204,8 @@ export default class IATopNav extends LitElement {
204
204
  tabindex="${this.userMenuTabIndex}"
205
205
  @menuToggled=${this.menuToggled}
206
206
  @trackClick=${this.trackClick}
207
- @focusToOtherMenuItem=${(e) => this.currentTab = e.detail}
207
+ @focusToOtherMenuItem=${(e: CustomEvent) =>
208
+ (this.currentTab = e.detail)}
208
209
  ></user-menu>
209
210
  `;
210
211
  }
@@ -212,7 +213,7 @@ export default class IATopNav extends LitElement {
212
213
  get signedOutDropdown() {
213
214
  return html`
214
215
  <signed-out-dropdown
215
- .baseHost=${this.baseHost}
216
+ .baseHost=${this.normalizedBaseHost}
216
217
  .config=${this.config}
217
218
  .open=${this.signedOutOpened}
218
219
  ?hideSearch=${this.hideSearch}
@@ -241,7 +242,7 @@ export default class IATopNav extends LitElement {
241
242
 
242
243
  return this.itemIdentifier && this.admin
243
244
  ? [basicItems, adminItems]
244
- : basicItems;
245
+ : [basicItems];
245
246
  }
246
247
 
247
248
  get desktopSubnavMenuItems() {
@@ -269,7 +270,7 @@ export default class IATopNav extends LitElement {
269
270
  return html`
270
271
  <div class="topnav">
271
272
  <primary-nav
272
- .baseHost=${this.baseHost}
273
+ .baseHost=${this.normalizedBaseHost}
273
274
  .mediaBaseHost=${this.mediaBaseHost}
274
275
  .config=${this.config}
275
276
  .openMenu=${this.openMenu}
@@ -283,7 +284,6 @@ export default class IATopNav extends LitElement {
283
284
  .currentTab=${this.currentTab}
284
285
  ?hideSearch=${this.hideSearch}
285
286
  @mediaTypeSelected=${this.mediaTypeSelected}
286
- @toggleSearchMenu=${this.toggleSearchMenu}
287
287
  @trackClick=${this.trackClick}
288
288
  @trackSubmit=${this.trackSubmit}
289
289
  @menuToggled=${this.menuToggled}
@@ -291,18 +291,19 @@ export default class IATopNav extends LitElement {
291
291
  ${this.secondLogoSlot}
292
292
  </primary-nav>
293
293
  <media-slider
294
- .baseHost=${this.baseHost}
294
+ .baseHost=${this.normalizedBaseHost}
295
295
  .config=${this.config}
296
296
  .selectedMenuOption=${this.selectedMenuOption}
297
297
  .mediaSliderOpen=${this.mediaSliderOpen}
298
298
  .menus=${this.menus}
299
299
  tabindex="${this.mediaSliderOpen ? '1' : '-1'}"
300
- @focusToOtherMenuItem=${(e) => this.currentTab = e.detail}
300
+ @focusToOtherMenuItem=${(e: CustomEvent) =>
301
+ (this.currentTab = e.detail)}
301
302
  ></media-slider>
302
303
  </div>
303
304
  ${this.username ? this.userMenu : this.signedOutDropdown}
304
305
  <search-menu
305
- .baseHost=${this.baseHost}
306
+ .baseHost=${this.normalizedBaseHost}
306
307
  .config=${this.config}
307
308
  .openMenu=${this.openMenu}
308
309
  tabindex="${this.searchMenuTabIndex}"
@@ -312,13 +313,15 @@ export default class IATopNav extends LitElement {
312
313
  @trackSubmit=${this.trackSubmit}
313
314
  ></search-menu>
314
315
  <desktop-subnav
315
- .baseHost=${this.baseHost}
316
+ .baseHost=${this.normalizedBaseHost}
316
317
  .menuItems=${this.desktopSubnavMenuItems}
317
318
  @focus=${this.closeMenus}
318
319
  ></desktop-subnav>
319
- <div id="close-layer" class="${this.closeLayerClass}" @click=${this.closeMenus}></div>
320
+ <div
321
+ id="close-layer"
322
+ class="${this.closeLayerClass}"
323
+ @click=${this.closeMenus}
324
+ ></div>
320
325
  `;
321
326
  }
322
327
  }
323
-
324
- customElements.define('ia-topnav', IATopNav);
@@ -0,0 +1,2 @@
1
+ export default (url: string = '', baseHost: string): string =>
2
+ /^https?:/.test(url) ? url : (`${baseHost}${url}` as string & Location);
@@ -1,10 +1,15 @@
1
1
  export default class KeyboardNavigation {
2
+ elementsContainer: HTMLElement;
3
+ menuOption: string;
4
+ focusableElements: HTMLElement[];
5
+ focusedIndex: number;
6
+
2
7
  /**
3
8
  * Constructor for the KeyboardNavigation class.
4
9
  * @param {HTMLElement} elementsContainer - The container element that holds the focusable elements.
5
10
  * @param {string} menuOption - The type of menu option ('web' or 'usermenu').
6
11
  */
7
- constructor(elementsContainer, menuOption) {
12
+ constructor(elementsContainer: HTMLElement, menuOption: string) {
8
13
  this.elementsContainer = elementsContainer;
9
14
  this.menuOption = menuOption;
10
15
  this.focusableElements = this.getFocusableElements();
@@ -18,7 +23,7 @@ export default class KeyboardNavigation {
18
23
  * Returns the initial focused index based on the menu option.
19
24
  * @returns {number} The initial focused index (0 for 'web', 1 for 'usermenu').
20
25
  */
21
- getInitialFocusedIndex() {
26
+ getInitialFocusedIndex(): number {
22
27
  return this.menuOption === 'usermenu' ? 1 : 0;
23
28
  }
24
29
 
@@ -26,38 +31,57 @@ export default class KeyboardNavigation {
26
31
  * Gets an array of focusable elements within the container.
27
32
  * @returns {HTMLElement[]} An array of focusable elements.
28
33
  */
29
- getFocusableElements() {
30
- const focusableTagSelectors = 'a[href], button, input, [tabindex]:not([tabindex="-1"])';
31
- const isDisabledOrHidden = el => !el.hasAttribute('disabled') && !el.getAttribute('aria-hidden');
34
+ getFocusableElements(): HTMLElement[] {
35
+ const focusableTagSelectors =
36
+ 'a[href], button, input, [tabindex]:not([tabindex="-1"])';
37
+ const isDisabledOrHidden = (el: Element) =>
38
+ !el.hasAttribute('disabled') && !el.getAttribute('aria-hidden');
32
39
 
33
40
  let elements;
34
41
  if (this.menuOption === 'web') {
35
42
  // wayback focusable elements
36
- const waybackSlider = this.elementsContainer.querySelector('wayback-slider').shadowRoot;
37
- const waybackSearch = waybackSlider.querySelector('wayback-search');
38
- const waybackSearchElements = Array.from(waybackSearch.shadowRoot.querySelectorAll(focusableTagSelectors));
39
-
40
- const normalElements = Array.from(waybackSlider.querySelectorAll(focusableTagSelectors));
43
+ const waybackSlider =
44
+ this.elementsContainer.querySelector('wayback-slider')?.shadowRoot;
45
+ const waybackSearch = waybackSlider?.querySelector('wayback-search');
46
+ const waybackSearchElements = Array.from(
47
+ waybackSearch?.shadowRoot?.querySelectorAll(focusableTagSelectors) ??
48
+ [],
49
+ );
50
+
51
+ const normalElements = Array.from(
52
+ waybackSlider?.querySelectorAll(focusableTagSelectors) ?? [],
53
+ );
41
54
 
42
55
  // wayback save-form focusable elements
43
- const savePageForm = waybackSlider.querySelector('save-page-form');
44
- const savePageFormElements = Array.from(savePageForm.shadowRoot.querySelectorAll(focusableTagSelectors));
45
-
46
- elements = [...waybackSearchElements, ...normalElements, ...savePageFormElements];
56
+ const savePageForm = waybackSlider?.querySelector('save-page-form');
57
+ const savePageFormElements = Array.from(
58
+ savePageForm?.shadowRoot?.querySelectorAll(focusableTagSelectors) ?? [],
59
+ );
60
+
61
+ elements = [
62
+ ...waybackSearchElements,
63
+ ...normalElements,
64
+ ...savePageFormElements,
65
+ ];
47
66
  } else {
48
67
  elements = this.elementsContainer.querySelectorAll(focusableTagSelectors);
49
68
  }
50
69
 
51
- return Array.from(elements).filter(isDisabledOrHidden);
70
+ return Array.from(elements).filter(isDisabledOrHidden) as HTMLElement[];
52
71
  }
53
72
 
54
73
  /**
55
74
  * Handles keyboard events and focuses the appropriate element.
56
75
  * @param {KeyboardEvent} event - The keyboard event object.
57
76
  */
58
- handleKeyDown(event) {
77
+ handleKeyDown(event: KeyboardEvent) {
59
78
  const { key } = event;
60
- const isArrowKey = ['ArrowDown', 'ArrowRight', 'ArrowUp', 'ArrowLeft'].includes(key);
79
+ const isArrowKey = [
80
+ 'ArrowDown',
81
+ 'ArrowRight',
82
+ 'ArrowUp',
83
+ 'ArrowLeft',
84
+ ].includes(key);
61
85
  const isTabKey = key === 'Tab';
62
86
 
63
87
  if (isArrowKey) {
@@ -72,9 +96,13 @@ export default class KeyboardNavigation {
72
96
  * Handles arrow key events and focuses the next or previous element for topnav sub-nav and usermenu
73
97
  * @param {string} key - The key that was pressed ('ArrowDown', 'ArrowRight', 'ArrowUp', or 'ArrowLeft').
74
98
  */
75
- handleArrowKey(key) {
99
+ handleArrowKey(key: string) {
76
100
  const isDownOrRight = ['ArrowDown', 'ArrowRight'].includes(key);
77
- isDownOrRight ? this.focusNext() : this.focusPrevious();
101
+ if (isDownOrRight) {
102
+ this.focusNext();
103
+ } else {
104
+ this.focusPrevious();
105
+ }
78
106
  }
79
107
 
80
108
  /**
@@ -82,7 +110,9 @@ export default class KeyboardNavigation {
82
110
  */
83
111
  focusPrevious() {
84
112
  if (this.focusableElements.length === 0) return;
85
- this.focusedIndex = (this.focusedIndex - 1 + this.focusableElements.length) % this.focusableElements.length;
113
+ this.focusedIndex =
114
+ (this.focusedIndex - 1 + this.focusableElements.length) %
115
+ this.focusableElements.length;
86
116
  this.focusableElements[this.focusedIndex]?.focus();
87
117
  }
88
118
 
@@ -99,7 +129,7 @@ export default class KeyboardNavigation {
99
129
  * Handles the Tab key event and focuses the next or previous menu item.
100
130
  * @param {KeyboardEvent} event - The keyboard event object.
101
131
  */
102
- handleTabKey(event) {
132
+ handleTabKey(event: KeyboardEvent) {
103
133
  if (this.menuOption) {
104
134
  const isShiftPressed = event.shiftKey;
105
135
  this.focusToOtherMenuItems(isShiftPressed);
@@ -113,7 +143,7 @@ export default class KeyboardNavigation {
113
143
  * Focuses the other parent menu items based on the provided flag.
114
144
  * @param {boolean} isPrevious - A flag indicating whether to focus the previous menu item.
115
145
  */
116
- focusToOtherMenuItems(isPrevious = false) {
146
+ focusToOtherMenuItems(isPrevious: boolean = false) {
117
147
  this.elementsContainer.dispatchEvent(
118
148
  new CustomEvent('focusToOtherMenuItem', {
119
149
  bubbles: true,
@@ -122,7 +152,7 @@ export default class KeyboardNavigation {
122
152
  mediatype: this.menuOption,
123
153
  moveTo: isPrevious ? 'prev' : 'next',
124
154
  },
125
- })
155
+ }),
126
156
  );
127
157
  }
128
158
  }
@@ -0,0 +1,5 @@
1
+ /* istanbul ignore file */
2
+
3
+ export default function (url: string) {
4
+ window.location.href = url;
5
+ }