UNPKG

govuk-frontend

Version:

GOV.UK Frontend contains the code you need to start building a user interface for government platforms and services.

1 lines 7.76 kB
{"version":3,"file":"header.mjs","sources":["../../../../src/govuk/components/header/header.mjs"],"sourcesContent":["import { getBreakpoint } from '../../common/index.mjs'\nimport { ElementError } from '../../errors/index.mjs'\nimport { GOVUKFrontendComponent } from '../../govuk-frontend-component.mjs'\n\n/**\n * Header component\n *\n * @preserve\n */\nexport class Header extends GOVUKFrontendComponent {\n /** @private */\n $menuButton\n\n /** @private */\n $menu\n\n /**\n * Save the opened/closed state for the nav in memory so that we can\n * accurately maintain state when the screen is changed from small to big and\n * back to small\n *\n * @private\n */\n menuIsOpen = false\n\n /**\n * A global const for storing a matchMedia instance which we'll use to detect\n * when a screen size change happens. We rely on it being null if the feature\n * isn't available to initially apply hidden attributes\n *\n * @private\n * @type {MediaQueryList | null}\n */\n mql = null\n\n /**\n * Apply a matchMedia for desktop which will trigger a state sync if the\n * browser viewport moves between states.\n *\n * @param {Element | null} $root - HTML element to use for header\n */\n constructor($root) {\n super($root)\n\n const $menuButton = this.$root.querySelector('.govuk-js-header-toggle')\n\n // Headers don't necessarily have a navigation. When they don't, the menu\n // toggle won't be rendered by our macro (or may be omitted when writing\n // plain HTML)\n if (!$menuButton) {\n return this\n }\n\n const menuId = $menuButton.getAttribute('aria-controls')\n if (!menuId) {\n throw new ElementError({\n component: Header,\n identifier:\n 'Navigation button (`<button class=\"govuk-js-header-toggle\">`) attribute (`aria-controls`)'\n })\n }\n\n const $menu = document.getElementById(menuId)\n if (!$menu) {\n throw new ElementError({\n component: Header,\n element: $menu,\n identifier: `Navigation (\\`<ul id=\"${menuId}\">\\`)`\n })\n }\n\n this.$menu = $menu\n this.$menuButton = $menuButton\n\n this.setupResponsiveChecks()\n\n this.$menuButton.addEventListener('click', () =>\n this.handleMenuButtonClick()\n )\n }\n\n /**\n * Setup viewport resize check\n *\n * @private\n */\n setupResponsiveChecks() {\n const breakpoint = getBreakpoint('desktop')\n\n if (!breakpoint.value) {\n throw new ElementError({\n component: Header,\n identifier: `CSS custom property (\\`${breakpoint.property}\\`) on pseudo-class \\`:root\\``\n })\n }\n\n // Media query list for GOV.UK Frontend desktop breakpoint\n this.mql = window.matchMedia(`(min-width: ${breakpoint.value})`)\n\n // MediaQueryList.addEventListener isn't supported by Safari < 14 so we need\n // to be able to fall back to the deprecated MediaQueryList.addListener\n if ('addEventListener' in this.mql) {\n this.mql.addEventListener('change', () => this.checkMode())\n } else {\n // @ts-expect-error Property 'addListener' does not exist\n // eslint-disable-next-line @typescript-eslint/no-unsafe-call\n this.mql.addListener(() => this.checkMode())\n }\n\n this.checkMode()\n }\n\n /**\n * Sync menu state\n *\n * Uses the global variable menuIsOpen to correctly set the accessible and\n * visual states of the menu and the menu button.\n * Additionally will force the menu to be visible and the menu button to be\n * hidden if the matchMedia is triggered to desktop.\n *\n * @private\n */\n checkMode() {\n if (!this.mql || !this.$menu || !this.$menuButton) {\n return\n }\n\n if (this.mql.matches) {\n this.$menu.removeAttribute('hidden')\n this.$menuButton.setAttribute('hidden', '')\n } else {\n this.$menuButton.removeAttribute('hidden')\n this.$menuButton.setAttribute('aria-expanded', this.menuIsOpen.toString())\n\n if (this.menuIsOpen) {\n this.$menu.removeAttribute('hidden')\n } else {\n this.$menu.setAttribute('hidden', '')\n }\n }\n }\n\n /**\n * Handle menu button click\n *\n * When the menu button is clicked, change the visibility of the menu and then\n * sync the accessibility state and menu button state\n *\n * @private\n */\n handleMenuButtonClick() {\n this.menuIsOpen = !this.menuIsOpen\n this.checkMode()\n }\n\n /**\n * Name for the component used when initialising using data-module attributes.\n */\n static moduleName = 'govuk-header'\n}\n"],"names":["Header","GOVUKFrontendComponent","constructor","$root","$menuButton","$menu","menuIsOpen","mql","querySelector","menuId","getAttribute","ElementError","component","identifier","document","getElementById","element","setupResponsiveChecks","addEventListener","handleMenuButtonClick","breakpoint","getBreakpoint","value","property","window","matchMedia","checkMode","addListener","matches","removeAttribute","setAttribute","toString","moduleName"],"mappings":"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"}