@internetarchive/ia-topnav 1.3.8 → 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.
- package/.prettierignore +1 -0
- package/README.md +7 -7
- package/demo/app-root.ts +186 -0
- package/demo/index.html +27 -0
- package/dist/demo/app-root.d.ts +8 -0
- package/dist/demo/app-root.js +181 -0
- package/dist/demo/app-root.js.map +1 -0
- package/dist/index.d.ts +2 -0
- package/dist/index.js +3 -0
- package/dist/index.js.map +1 -0
- package/dist/src/assets/img/hamburger.d.ts +7 -0
- package/dist/src/assets/img/hamburger.js +51 -0
- package/dist/src/assets/img/hamburger.js.map +1 -0
- package/dist/src/assets/img/ia-icon.d.ts +7 -0
- package/dist/src/assets/img/ia-icon.js +33 -0
- package/dist/src/assets/img/ia-icon.js.map +1 -0
- package/dist/src/assets/img/icon-audio.d.ts +2 -0
- package/dist/src/assets/img/icon-audio.js +28 -0
- package/dist/src/assets/img/icon-audio.js.map +1 -0
- package/dist/src/assets/img/icon-close.d.ts +2 -0
- package/dist/src/assets/img/icon-close.js +20 -0
- package/dist/src/assets/img/icon-close.js.map +1 -0
- package/dist/src/assets/img/icon-donate-unpadded.d.ts +2 -0
- package/dist/src/assets/img/icon-donate-unpadded.js +19 -0
- package/dist/src/assets/img/icon-donate-unpadded.js.map +1 -0
- package/dist/src/assets/img/icon-donate.d.ts +2 -0
- package/dist/src/assets/img/icon-donate.js +18 -0
- package/dist/src/assets/img/icon-donate.js.map +1 -0
- package/dist/src/assets/img/icon-ellipses.d.ts +2 -0
- package/dist/src/assets/img/icon-ellipses.js +19 -0
- package/dist/src/assets/img/icon-ellipses.js.map +1 -0
- package/dist/src/assets/img/icon-ia-logo.d.ts +2 -0
- package/dist/src/assets/img/icon-ia-logo.js +30 -0
- package/dist/src/assets/img/icon-ia-logo.js.map +1 -0
- package/dist/src/assets/img/icon-images.d.ts +2 -0
- package/dist/src/assets/img/icon-images.js +19 -0
- package/dist/src/assets/img/icon-images.js.map +1 -0
- package/dist/src/assets/img/icon-search.d.ts +2 -0
- package/dist/src/assets/img/icon-search.js +19 -0
- package/dist/src/assets/img/icon-search.js.map +1 -0
- package/dist/src/assets/img/icon-software.d.ts +2 -0
- package/dist/src/assets/img/icon-software.js +18 -0
- package/dist/src/assets/img/icon-software.js.map +1 -0
- package/dist/src/assets/img/icon-texts.d.ts +2 -0
- package/dist/src/assets/img/icon-texts.js +18 -0
- package/dist/src/assets/img/icon-texts.js.map +1 -0
- package/dist/src/assets/img/icon-upload-unpadded.d.ts +2 -0
- package/dist/src/assets/img/icon-upload-unpadded.js +18 -0
- package/dist/src/assets/img/icon-upload-unpadded.js.map +1 -0
- package/dist/src/assets/img/icon-upload.d.ts +2 -0
- package/dist/src/assets/img/icon-upload.js +21 -0
- package/dist/src/assets/img/icon-upload.js.map +1 -0
- package/dist/src/assets/img/icon-user.d.ts +2 -0
- package/dist/src/assets/img/icon-user.js +19 -0
- package/dist/src/assets/img/icon-user.js.map +1 -0
- package/dist/src/assets/img/icon-video.d.ts +2 -0
- package/dist/src/assets/img/icon-video.js +19 -0
- package/dist/src/assets/img/icon-video.js.map +1 -0
- package/dist/src/assets/img/icon-web.d.ts +2 -0
- package/dist/src/assets/img/icon-web.js +19 -0
- package/dist/src/assets/img/icon-web.js.map +1 -0
- package/dist/src/assets/img/icon.d.ts +5 -0
- package/dist/src/assets/img/icon.js +17 -0
- package/dist/src/assets/img/icon.js.map +1 -0
- package/dist/src/assets/img/icons.d.ts +18 -0
- package/dist/src/assets/img/icons.js +33 -0
- package/dist/src/assets/img/icons.js.map +1 -0
- package/dist/src/assets/img/wordmark-stacked.d.ts +2 -0
- package/dist/src/assets/img/wordmark-stacked.js +13 -0
- package/dist/src/assets/img/wordmark-stacked.js.map +1 -0
- package/dist/src/data/menus.d.ts +20 -0
- package/dist/src/data/menus.js +668 -0
- package/dist/src/data/menus.js.map +1 -0
- package/dist/src/desktop-subnav.d.ts +11 -0
- package/dist/src/desktop-subnav.js +55 -0
- package/dist/src/desktop-subnav.js.map +1 -0
- package/dist/src/dropdown-menu.d.ts +19 -0
- package/dist/src/dropdown-menu.js +115 -0
- package/dist/src/dropdown-menu.js.map +1 -0
- package/dist/src/ia-topnav.d.ts +68 -0
- package/dist/src/ia-topnav.js +315 -0
- package/dist/src/ia-topnav.js.map +1 -0
- package/dist/src/lib/formatUrl.d.ts +2 -0
- package/dist/src/lib/formatUrl.js +2 -0
- package/dist/src/lib/formatUrl.js.map +1 -0
- package/dist/src/lib/keyboard-navigation.d.ts +50 -0
- package/dist/src/lib/keyboard-navigation.js +136 -0
- package/dist/src/lib/keyboard-navigation.js.map +1 -0
- package/dist/src/lib/location-handler.d.ts +1 -0
- package/dist/src/lib/location-handler.js +5 -0
- package/dist/src/lib/location-handler.js.map +1 -0
- package/dist/src/lib/makeBooleanString.d.ts +2 -0
- package/dist/src/lib/makeBooleanString.js +12 -0
- package/dist/src/lib/makeBooleanString.js.map +1 -0
- package/dist/src/lib/query-handler.d.ts +4 -0
- package/dist/src/lib/query-handler.js +7 -0
- package/dist/src/lib/query-handler.js.map +1 -0
- package/dist/src/lib/toSentenceCase.d.ts +2 -0
- package/dist/src/lib/toSentenceCase.js +10 -0
- package/dist/src/lib/toSentenceCase.js.map +1 -0
- package/dist/src/login-button.d.ts +16 -0
- package/dist/src/login-button.js +83 -0
- package/dist/src/login-button.js.map +1 -0
- package/dist/src/media-button.d.ts +24 -0
- package/dist/src/media-button.js +119 -0
- package/dist/src/media-button.js.map +1 -0
- package/dist/src/media-menu.d.ts +20 -0
- package/dist/src/media-menu.js +148 -0
- package/dist/src/media-menu.js.map +1 -0
- package/dist/src/media-slider.d.ts +15 -0
- package/dist/src/media-slider.js +139 -0
- package/dist/src/media-slider.js.map +1 -0
- package/dist/src/media-subnav.d.ts +18 -0
- package/dist/src/media-subnav.js +126 -0
- package/dist/src/media-subnav.js.map +1 -0
- package/dist/src/models.d.ts +51 -0
- package/dist/src/models.js +25 -0
- package/dist/src/models.js.map +1 -0
- package/dist/src/more-slider.d.ts +10 -0
- package/dist/src/more-slider.js +50 -0
- package/dist/src/more-slider.js.map +1 -0
- package/dist/src/nav-search.d.ts +19 -0
- package/dist/src/nav-search.js +123 -0
- package/dist/src/nav-search.js.map +1 -0
- package/dist/src/primary-nav.d.ts +45 -0
- package/dist/src/primary-nav.js +280 -0
- package/dist/src/primary-nav.js.map +1 -0
- package/dist/src/save-page-form.d.ts +10 -0
- package/dist/src/save-page-form.js +63 -0
- package/dist/src/save-page-form.js.map +1 -0
- package/dist/src/search-menu.d.ts +20 -0
- package/dist/src/search-menu.js +162 -0
- package/dist/src/search-menu.js.map +1 -0
- package/dist/src/signed-out-dropdown.d.ts +4 -0
- package/dist/src/signed-out-dropdown.js +15 -0
- package/dist/src/signed-out-dropdown.js.map +1 -0
- package/dist/src/styles/base.d.ts +1 -0
- package/dist/src/styles/base.js +48 -0
- package/dist/src/styles/base.js.map +1 -0
- package/dist/src/styles/desktop-subnav.d.ts +2 -0
- package/dist/src/styles/desktop-subnav.js +37 -0
- package/dist/src/styles/desktop-subnav.js.map +1 -0
- package/dist/src/styles/dropdown-menu.d.ts +2 -0
- package/dist/src/styles/dropdown-menu.js +170 -0
- package/dist/src/styles/dropdown-menu.js.map +1 -0
- package/dist/src/styles/ia-topnav.d.ts +2 -0
- package/dist/src/styles/ia-topnav.js +87 -0
- package/dist/src/styles/ia-topnav.js.map +1 -0
- package/dist/src/styles/login-button.d.ts +2 -0
- package/dist/src/styles/login-button.js +82 -0
- package/dist/src/styles/login-button.js.map +1 -0
- package/dist/src/styles/media-button.d.ts +2 -0
- package/dist/src/styles/media-button.js +156 -0
- package/dist/src/styles/media-button.js.map +1 -0
- package/dist/src/styles/media-menu.d.ts +2 -0
- package/dist/src/styles/media-menu.js +66 -0
- package/dist/src/styles/media-menu.js.map +1 -0
- package/dist/src/styles/media-slider.d.ts +2 -0
- package/dist/src/styles/media-slider.js +81 -0
- package/dist/src/styles/media-slider.js.map +1 -0
- package/dist/src/styles/media-subnav.d.ts +2 -0
- package/dist/src/styles/media-subnav.js +159 -0
- package/dist/src/styles/media-subnav.js.map +1 -0
- package/dist/src/styles/more-slider.d.ts +2 -0
- package/dist/src/styles/more-slider.js +15 -0
- package/dist/src/styles/more-slider.js.map +1 -0
- package/dist/src/styles/nav-search.d.ts +2 -0
- package/dist/src/styles/nav-search.js +136 -0
- package/dist/src/styles/nav-search.js.map +1 -0
- package/dist/src/styles/primary-nav.d.ts +2 -0
- package/dist/src/styles/primary-nav.js +310 -0
- package/dist/src/styles/primary-nav.js.map +1 -0
- package/dist/src/styles/save-page-form.d.ts +2 -0
- package/dist/src/styles/save-page-form.js +54 -0
- package/dist/src/styles/save-page-form.js.map +1 -0
- package/dist/src/styles/search-menu.d.ts +2 -0
- package/dist/src/styles/search-menu.js +105 -0
- package/dist/src/styles/search-menu.js.map +1 -0
- package/dist/src/styles/signed-out-dropdown.d.ts +2 -0
- package/dist/src/styles/signed-out-dropdown.js +31 -0
- package/dist/src/styles/signed-out-dropdown.js.map +1 -0
- package/dist/src/styles/user-menu.d.ts +2 -0
- package/dist/src/styles/user-menu.js +31 -0
- package/dist/src/styles/user-menu.js.map +1 -0
- package/dist/src/styles/wayback-search.d.ts +2 -0
- package/dist/src/styles/wayback-search.js +48 -0
- package/dist/src/styles/wayback-search.js.map +1 -0
- package/dist/src/styles/wayback-slider.d.ts +2 -0
- package/dist/src/styles/wayback-slider.js +33 -0
- package/dist/src/styles/wayback-slider.js.map +1 -0
- package/dist/src/tracked-element.d.ts +5 -0
- package/dist/src/tracked-element.js +30 -0
- package/dist/src/tracked-element.js.map +1 -0
- package/dist/src/user-menu.d.ts +10 -0
- package/dist/src/user-menu.js +60 -0
- package/dist/src/user-menu.js.map +1 -0
- package/dist/src/wayback-search.d.ts +4 -0
- package/dist/src/wayback-search.js +14 -0
- package/dist/src/wayback-search.js.map +1 -0
- package/dist/src/wayback-slider.d.ts +18 -0
- package/dist/src/wayback-slider.js +99 -0
- package/dist/src/wayback-slider.js.map +1 -0
- package/dist/test/assets/img/hamburger.test.d.ts +1 -0
- package/dist/test/assets/img/hamburger.test.js +13 -0
- package/dist/test/assets/img/hamburger.test.js.map +1 -0
- package/dist/test/assets/img/user.test.d.ts +1 -0
- package/dist/test/assets/img/user.test.js +12 -0
- package/dist/test/assets/img/user.test.js.map +1 -0
- package/dist/test/data/menus.test.d.ts +1 -0
- package/dist/test/data/menus.test.js +11 -0
- package/dist/test/data/menus.test.js.map +1 -0
- package/dist/test/dropdown-menu.test.d.ts +1 -0
- package/dist/test/dropdown-menu.test.js +20 -0
- package/dist/test/dropdown-menu.test.js.map +1 -0
- package/dist/test/ia-icon.test.d.ts +1 -0
- package/dist/test/ia-icon.test.js +11 -0
- package/dist/test/ia-icon.test.js.map +1 -0
- package/dist/test/ia-topnav.test.d.ts +1 -0
- package/dist/test/ia-topnav.test.js +232 -0
- package/dist/test/ia-topnav.test.js.map +1 -0
- package/dist/test/login-button.test.d.ts +1 -0
- package/dist/test/login-button.test.js +14 -0
- package/dist/test/login-button.test.js.map +1 -0
- package/dist/test/media-button.test.d.ts +1 -0
- package/dist/test/media-button.test.js +13 -0
- package/dist/test/media-button.test.js.map +1 -0
- package/dist/test/media-menu.test.d.ts +1 -0
- package/dist/test/media-menu.test.js +27 -0
- package/dist/test/media-menu.test.js.map +1 -0
- package/dist/test/media-slider.test.d.ts +1 -0
- package/dist/test/media-slider.test.js +47 -0
- package/dist/test/media-slider.test.js.map +1 -0
- package/dist/test/more-slider.test.d.ts +1 -0
- package/dist/test/more-slider.test.js +17 -0
- package/dist/test/more-slider.test.js.map +1 -0
- package/dist/test/nav-search.test.d.ts +1 -0
- package/dist/test/nav-search.test.js +47 -0
- package/dist/test/nav-search.test.js.map +1 -0
- package/dist/test/primary-nav.test.d.ts +1 -0
- package/dist/test/primary-nav.test.js +65 -0
- package/dist/test/primary-nav.test.js.map +1 -0
- package/dist/test/save-page-form.test.d.ts +1 -0
- package/dist/test/save-page-form.test.js +47 -0
- package/dist/test/save-page-form.test.js.map +1 -0
- package/dist/test/search-menu.test.d.ts +1 -0
- package/dist/test/search-menu.test.js +42 -0
- package/dist/test/search-menu.test.js.map +1 -0
- package/dist/test/user-menu.test.d.ts +1 -0
- package/dist/test/user-menu.test.js +28 -0
- package/dist/test/user-menu.test.js.map +1 -0
- package/dist/test/wayback-slider.test.d.ts +1 -0
- package/dist/test/wayback-slider.test.js +80 -0
- package/dist/test/wayback-slider.test.js.map +1 -0
- package/eslint.config.mjs +53 -0
- package/package.json +47 -37
- package/prettier.config.js +9 -0
- package/src/assets/img/hamburger.ts +49 -0
- package/src/assets/img/{ia-icon.js → ia-icon.ts} +7 -16
- package/src/assets/img/{icon-audio.js → icon-audio.ts} +7 -2
- package/src/assets/img/icon-close.ts +20 -0
- package/src/assets/img/icon-donate-unpadded.ts +19 -0
- package/src/assets/img/icon-donate.ts +18 -0
- package/src/assets/img/icon-ellipses.ts +19 -0
- package/src/assets/img/icon-ia-logo.ts +30 -0
- package/src/assets/img/icon-images.ts +19 -0
- package/src/assets/img/icon-search.ts +19 -0
- package/src/assets/img/icon-software.ts +18 -0
- package/src/assets/img/icon-texts.ts +18 -0
- package/src/assets/img/{icon-upload-unpadded.js → icon-upload-unpadded.ts} +6 -2
- package/src/assets/img/icon-upload.ts +21 -0
- package/src/assets/img/icon-user.ts +19 -0
- package/src/assets/img/icon-video.ts +19 -0
- package/src/assets/img/icon-web.ts +19 -0
- package/src/assets/img/icon.ts +8 -0
- package/src/assets/img/icons.ts +33 -0
- package/src/assets/img/{wordmark-stacked.js → wordmark-stacked.ts} +1 -1
- package/src/data/{menus.js → menus.ts} +172 -135
- package/src/desktop-subnav.ts +49 -0
- package/src/dropdown-menu.ts +105 -0
- package/src/{ia-topnav.js → ia-topnav.ts} +130 -127
- package/src/lib/formatUrl.ts +2 -0
- package/src/lib/{keyboard-navigation.js → keyboard-navigation.ts} +53 -23
- package/src/lib/location-handler.ts +5 -0
- package/src/lib/makeBooleanString.ts +12 -0
- package/src/lib/query-handler.ts +7 -0
- package/src/lib/toSentenceCase.ts +10 -0
- package/src/{login-button.js → login-button.ts} +27 -31
- package/src/{media-button.js → media-button.ts} +39 -49
- package/src/media-menu.ts +143 -0
- package/src/{media-slider.js → media-slider.ts} +53 -41
- package/src/media-subnav.ts +132 -0
- package/src/models.ts +114 -0
- package/src/more-slider.ts +42 -0
- package/src/nav-search.ts +113 -0
- package/src/primary-nav.ts +266 -0
- package/src/save-page-form.ts +59 -0
- package/src/search-menu.ts +156 -0
- package/src/signed-out-dropdown.ts +11 -0
- package/src/styles/{base.js → base.ts} +2 -2
- package/src/styles/{desktop-subnav.js → desktop-subnav.ts} +2 -2
- package/src/styles/{dropdown-menu.js → dropdown-menu.ts} +4 -2
- package/src/styles/{ia-topnav.js → ia-topnav.ts} +1 -1
- package/src/styles/{login-button.js → login-button.ts} +1 -1
- package/src/styles/{media-button.js → media-button.ts} +2 -2
- package/src/styles/{media-menu.js → media-menu.ts} +1 -1
- package/src/styles/{media-slider.js → media-slider.ts} +1 -1
- package/src/styles/media-subnav.ts +159 -0
- package/src/styles/{more-slider.js → more-slider.ts} +1 -1
- package/src/styles/{nav-search.js → nav-search.ts} +2 -2
- package/src/styles/{primary-nav.js → primary-nav.ts} +4 -5
- package/src/styles/{save-page-form.js → save-page-form.ts} +7 -7
- package/src/styles/{search-menu.js → search-menu.ts} +1 -1
- package/src/styles/{signed-out-dropdown.js → signed-out-dropdown.ts} +1 -1
- package/src/styles/{user-menu.js → user-menu.ts} +1 -1
- package/src/styles/{wayback-search.js → wayback-search.ts} +3 -3
- package/src/styles/wayback-slider.ts +33 -0
- package/src/tracked-element.ts +32 -0
- package/src/user-menu.ts +57 -0
- package/src/wayback-search.ts +10 -0
- package/src/wayback-slider.ts +88 -0
- package/ssl/server.crt +22 -0
- package/ssl/server.key +28 -0
- package/test/assets/img/hamburger.test.ts +18 -0
- package/test/assets/img/user.test.ts +15 -0
- package/test/data/menus.test.ts +15 -0
- package/test/{dropdown-menu.test.js → dropdown-menu.test.ts} +4 -4
- package/test/{ia-icon.test.js → ia-icon.test.ts} +6 -4
- package/test/ia-topnav.test.ts +344 -0
- package/test/login-button.test.ts +19 -0
- package/test/media-button.test.ts +19 -0
- package/test/{media-menu.test.js → media-menu.test.ts} +14 -12
- package/test/media-slider.test.ts +63 -0
- package/test/more-slider.test.ts +21 -0
- package/test/nav-search.test.ts +70 -0
- package/test/primary-nav.test.ts +110 -0
- package/test/save-page-form.test.ts +62 -0
- package/test/{search-menu.test.js → search-menu.test.ts} +19 -10
- package/test/{user-menu.test.js → user-menu.test.ts} +10 -9
- package/test/wayback-slider.test.ts +97 -0
- package/tsconfig.json +31 -0
- package/web-dev-server.config.mjs +32 -0
- package/web-test-runner.config.mjs +41 -0
- package/.eslintrc +0 -16
- package/index.d.ts +0 -109
- package/src/assets/img/hamburger.js +0 -38
- package/src/assets/img/icon-close.js +0 -16
- package/src/assets/img/icon-donate-unpadded.js +0 -16
- package/src/assets/img/icon-donate.js +0 -15
- package/src/assets/img/icon-ellipses.js +0 -15
- package/src/assets/img/icon-ia-logo.js +0 -22
- package/src/assets/img/icon-images.js +0 -15
- package/src/assets/img/icon-search.js +0 -15
- package/src/assets/img/icon-software.js +0 -15
- package/src/assets/img/icon-texts.js +0 -15
- package/src/assets/img/icon-upload.js +0 -15
- package/src/assets/img/icon-user.js +0 -15
- package/src/assets/img/icon-video.js +0 -15
- package/src/assets/img/icon-web.js +0 -15
- package/src/assets/img/icon.js +0 -18
- package/src/assets/img/icons.js +0 -33
- package/src/desktop-subnav.js +0 -45
- package/src/dropdown-menu.js +0 -110
- package/src/lib/formatUrl.js +0 -1
- package/src/lib/location-handler.js +0 -5
- package/src/lib/query-handler.js +0 -7
- package/src/lib/toSentenceCase.js +0 -8
- package/src/media-menu.js +0 -154
- package/src/media-subnav.js +0 -112
- package/src/more-slider.js +0 -33
- package/src/nav-search.js +0 -111
- package/src/primary-nav.js +0 -258
- package/src/save-page-form.js +0 -59
- package/src/search-menu.js +0 -145
- package/src/signed-out-dropdown.js +0 -10
- package/src/styles/media-subnav.js +0 -156
- package/src/styles/wayback-slider.js +0 -30
- package/src/tracked-element.js +0 -29
- package/src/user-menu.js +0 -56
- package/src/wayback-search.js +0 -18
- package/src/wayback-slider.js +0 -87
- package/test/assets/img/hamburger.test.js +0 -15
- package/test/assets/img/user.test.js +0 -15
- package/test/data/menus.test.js +0 -19
- package/test/ia-topnav.test.js +0 -273
- package/test/login-button.test.js +0 -15
- package/test/media-button.test.js +0 -19
- package/test/media-slider.test.js +0 -57
- package/test/more-slider.test.js +0 -13
- package/test/nav-search.test.js +0 -61
- package/test/primary-nav.test.js +0 -82
- package/test/save-page-form.test.js +0 -35
- package/test/wayback-slider.test.js +0 -80
- /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 '
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
import './
|
|
5
|
-
import './
|
|
6
|
-
import './
|
|
7
|
-
import './
|
|
8
|
-
import
|
|
9
|
-
|
|
10
|
-
|
|
11
|
-
|
|
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
|
-
|
|
15
|
-
return iaTopNavCSS;
|
|
16
|
-
}
|
|
21
|
+
@property({ type: Boolean }) localLinks = false;
|
|
17
22
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
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
|
-
|
|
70
|
-
|
|
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 (
|
|
86
|
-
props.has('
|
|
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(
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
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(
|
|
102
|
+
this.menus = buildTopNavMenus(
|
|
103
|
+
this.username,
|
|
104
|
+
this.normalizedBaseHost,
|
|
105
|
+
this.waybackPagesArchived,
|
|
106
|
+
this.itemIdentifier,
|
|
107
|
+
);
|
|
112
108
|
}
|
|
113
109
|
|
|
114
|
-
menuToggled(
|
|
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(
|
|
143
|
-
this.dispatchEvent(
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
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(
|
|
151
|
-
this.dispatchEvent(
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
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(
|
|
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.
|
|
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) =>
|
|
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.
|
|
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.
|
|
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.
|
|
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) =>
|
|
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.
|
|
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.
|
|
316
|
+
.baseHost=${this.normalizedBaseHost}
|
|
316
317
|
.menuItems=${this.desktopSubnavMenuItems}
|
|
317
318
|
@focus=${this.closeMenus}
|
|
318
319
|
></desktop-subnav>
|
|
319
|
-
<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);
|
|
@@ -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 =
|
|
31
|
-
|
|
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 =
|
|
37
|
-
|
|
38
|
-
const
|
|
39
|
-
|
|
40
|
-
|
|
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
|
|
44
|
-
const savePageFormElements = Array.from(
|
|
45
|
-
|
|
46
|
-
|
|
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 = [
|
|
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
|
-
|
|
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 =
|
|
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
|
}
|