{"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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"}