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.68 kB
{"version":3,"file":"header.mjs","sources":["../../../../src/govuk/components/header/header.mjs"],"sourcesContent":["import { getBreakpoint } from '../../common/index.mjs'\nimport { Component } from '../../component.mjs'\nimport { ElementError } from '../../errors/index.mjs'\n\n/**\n * Header component\n *\n * @preserve\n */\nexport class Header extends Component {\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 // Pad the header logo so it doesn't overlap the menu button\n this.$root.classList.add('govuk-header--with-js-navigation')\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","Component","constructor","$root","$menuButton","$menu","menuIsOpen","mql","querySelector","classList","add","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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"}