{
  "version": 3,
  "sources": ["../components/timer.js", "../components/TabbedNavigator.js", "../components/site-nav.js", "../components/scroll-to-top.js", "../components/combobox/listbox.js", "../components/secondary-nav.js", "../components/wx-loader.js", "../locationSearch.js", "../components/combobox/combobox.js", "../components/recent-locations.js", "../components/combobox/location-listbox.js", "../components/saved-locations.js", "../components/saved-locations-section.js", "../aws-rum.js", "../components/offline-banner.js", "../components/aria-live.js", "../components/combobox/filterable-listbox.js", "../components/Tabs.js", "../components/county-alert-daily-alert-handler.js", "../components/state-index-filter.js"],
  "sourcesContent": ["/** Convenience class for using setTimeout. */\nexport default class Timer {\n  constructor() {\n    this.timer = this.callback = this.delay = null;\n  }\n\n  stop = () => {\n    if (this.timer === null) return;\n    clearTimeout(this.timer);\n    this.timer = this.callback = this.delay = null;\n  };\n\n  start = (callback, delay) => {\n    this.stop();\n    this.callback = callback;\n    this.delay = Number.isFinite(delay) ? delay : 2000;\n    this.timer = setTimeout(callback, this.delay);\n  };\n\n  reset = () => {\n    if (this.timer === null) return;\n    this.start(this.callback, this.delay);\n  };\n}\n", "class TabbedNavigator extends HTMLElement {\n  constructor() {\n    super();\n\n    // Bind this context to methods that need it\n    this.handleAlertAnchorClick = this.handleAlertAnchorClick.bind(this);\n    this.handleDescendantClick = this.handleDescendantClick.bind(this);\n    this.handleTabButtonClick = this.handleTabButtonClick.bind(this);\n    this.handlePopState = this.handlePopState.bind(this);\n    this.switchToTab = this.switchToTab.bind(this);\n    this.scrollToAccordion = this.scrollToAccordion.bind(this);\n    this.navigateAlertAnchor = this.navigateAlertAnchor.bind(this);\n    this.updateTabScrollState = this.updateTabScrollState.bind(this);\n  }\n\n  connectedCallback() {\n    const pointTablist = this.querySelector(\"#point-page-tablist\");\n    if (pointTablist) {\n      // Capture scroll events because they do not bubble.\n      this.addEventListener(\"scroll\", this.updateTabScrollState, true);\n      this.tablistResizeObserver = new ResizeObserver(\n        this.updateTabScrollState,\n      );\n      this.tablistResizeObserver.observe(this);\n      this.tablistResizeObserver.observe(pointTablist);\n      pointTablist.querySelectorAll(\".tab-button\").forEach((tab) => {\n        this.tablistResizeObserver.observe(tab);\n      });\n      this.updateTabScrollState();\n    }\n\n    // If no tabs are selected by default, then select the first one\n    const selected = Array.from(\n      this.querySelectorAll(\".tab-button[data-selected]\"),\n    );\n    if (!selected.length) {\n      this.switchToTab(this.querySelector(\"button\").dataset.tabName);\n    }\n\n    // Intercept click events on Alert links at the\n    // top of the page and handle them in this component\n    Array.from(document.querySelectorAll(\"wx-point-alert-links a\")).forEach(\n      (alertAnchor) => {\n        alertAnchor.addEventListener(\"click\", this.handleAlertAnchorClick);\n      },\n    );\n\n    // Intercept click events on Alert spans that are in tab\n    // containers controlled by this component\n    this.addEventListener(\"click\", this.handleDescendantClick);\n    window.addEventListener(\"popstate\", this.handlePopState);\n\n    // Add needed event listeners\n    Array.from(this.querySelectorAll(\"button.tab-button\")).forEach((button) => {\n      button.addEventListener(\"click\", this.handleTabButtonClick);\n      button.addEventListener(\"keydown\", this.handleTabListKeydown);\n    });\n  }\n\n  disconnectedCallback() {\n    this.tablistResizeObserver?.disconnect();\n    this.removeEventListener(\"scroll\", this.updateTabScrollState, true);\n    window.removeEventListener(\"popstate\", this.handlePopState);\n\n    // Remove any event listeners\n    Array.from(this.querySelectorAll(\"button.tab-button\")).forEach((button) => {\n      button.removeEventListener(\"click\", this.handleTabButtonClick);\n      button.removeEventListener(\"keydown\", this.handleTabListKeydown);\n    });\n  }\n\n  updateTabScrollState() {\n    const tablist = this.querySelector(\"#point-page-tablist\");\n    const maxScroll = tablist ? tablist.scrollWidth - tablist.clientWidth : 0;\n    this.toggleAttribute(\"data-tabs-overflow\", maxScroll > 0);\n    this.toggleAttribute(\n      \"data-tabs-scroll-left\",\n      maxScroll > 0 && tablist.scrollLeft > 0,\n    );\n    // Allow for fractional scroll positions at the right edge.\n    this.toggleAttribute(\n      \"data-tabs-scroll-right\",\n      maxScroll > 0 && maxScroll - tablist.scrollLeft > 1,\n    );\n  }\n\n  navigateWithInitialHash() {\n    const hash = new URL(window.location).hash;\n    if (!hash || hash === \"\") {\n      return;\n    }\n\n    try {\n      const matchedTabButton = this.querySelector(\n        `[data-tab-name=\"${hash.replace(\"#\", \"\")}\"]`,\n      );\n      if (matchedTabButton) {\n        this.switchToTab(matchedTabButton.dataset.tabName);\n        matchedTabButton.parentElement.scrollIntoView();\n        return;\n      }\n\n      const childElement = this.querySelector(\n        `${hash},wx-tab-container, .wx-tab-container ${hash}`,\n      );\n      if (childElement) {\n        const tabContainer = childElement.closest(\".wx-tab-container\");\n        this.switchToTab(tabContainer.id);\n        if (childElement.matches(\".usa-accordion\")) {\n          this.toggleAccordion(childElement, true);\n          document.addEventListener(\"DOMContentLoaded\", () => {\n            this.scrollToAccordion(childElement);\n          });\n        }\n      }\n    } catch (e) {\n      // Guard against hashes that are not valid DOM identifiers. We can't\n      // prevent users from typing random stuff in the address bar, but we\n      // prevent our scripts from crashing if they do.\n    }\n  }\n\n  switchToTab(tabId) {\n    // First, deactivate all tabs\n    Array.from(this.querySelectorAll(\".tab-button, .wx-tab-container\")).forEach(\n      (element) => {\n        element.removeAttribute(\"data-selected\");\n        if (element.matches(\".tab-button\")) {\n          element.setAttribute(\"aria-expanded\", \"false\");\n          element.setAttribute(\"tabindex\", \"-1\");\n        }\n      },\n    );\n\n    // Active the tab button\n    const tabButton = this.querySelector(`[data-tab-name=\"${tabId}\"]`);\n    tabButton.setAttribute(\"data-selected\", \"\");\n    tabButton.setAttribute(\"aria-expanded\", \"true\");\n    tabButton.removeAttribute(\"tabindex\");\n\n    // Activate the corresponding container\n    const tabContainer = this.querySelector(`#${tabId}`);\n    tabContainer.setAttribute(\"data-selected\", \"\");\n\n    // Trigger a custom event for use externally\n    // when tabs switch\n    const event = new CustomEvent(\"wx:tab-switched\", {\n      detail: {\n        tabId,\n      },\n      bubbles: true,\n    });\n    this.dispatchEvent(event);\n  }\n\n  handleTabButtonClick(event) {\n    const tabButton = event.currentTarget;\n    this.switchToTab(tabButton.dataset.tabName);\n    // Since this was an actual click, update the hash\n    // of the site to the tab button's id and push it into the browser history\n    window.history.pushState(null, null, tabButton.dataset.url);\n  }\n\n  handlePopState() {\n    const currentPath = window.location.pathname;\n    const matchingTab = Array.from(\n      this.querySelectorAll(\".tab-button[data-url]\"),\n    ).find((tabButton) => {\n      const tabUrl = new URL(tabButton.dataset.url, window.location.origin);\n      return tabUrl.pathname === currentPath;\n    });\n\n    if (matchingTab) {\n      this.switchToTab(matchingTab.dataset.tabName);\n      matchingTab.focus({ preventScroll: true });\n    }\n  }\n\n  /**\n   * A catch-all listener for click events inside the navigator and any\n   * of its constituent tab content panes.\n   * We use this to filter out for wx-alert clicks, which will be handled\n   * separately.\n   */\n  handleDescendantClick(event) {\n    if (!event.target.matches(\"a\")) {\n      return;\n    }\n    const linkWrapper = event.target.closest(\".wx-alert-link\");\n    if (!linkWrapper) {\n      return;\n    }\n    this.navigateAlertAnchor(event.target);\n  }\n\n  navigateAlertAnchor(anchorEl) {\n    const hash = new URL(anchorEl.href).hash;\n    const accordionEl = this.querySelector(`${hash}.usa-accordion`);\n\n    if (accordionEl) {\n      // If we get here, then the element referred\n      // to by the href is a child of this tabbed\n      // navigator.\n      // We need to toggle to the correct tab pane\n      // to properly display and scroll to the element.\n      const tabContainer = accordionEl.closest(\".wx-tab-container\");\n      this.switchToTab(tabContainer.id);\n      this.toggleAccordion(accordionEl, true);\n\n      // Because we use a sticky position on\n      // the tab button area, the normal browser\n      // scrolling will not display the proper position\n      // to the user. Instead, we have to roll our\n      // own scrolling method\n      this.scrollToAccordion(accordionEl);\n      window.history.replaceState(null, null, hash);\n    }\n  }\n\n  handleAlertAnchorClick(event) {\n    event.preventDefault();\n    this.navigateAlertAnchor(event.currentTarget);\n  }\n\n  toggleAccordion(accordionElement, on = true) {\n    const button = accordionElement.querySelector(\n      \"button.usa-accordion__button\",\n    );\n    const content = accordionElement.querySelector(\".usa-accordion__content\");\n\n    if (on) {\n      button.setAttribute(\"aria-expanded\", \"true\");\n      content.removeAttribute(\"hidden\");\n    } else {\n      button.setAttribute(\"aria-expanded\", \"false\");\n      content.addAttribute(\"hidden\", \"\");\n    }\n  }\n\n  handleTabListKeydown(event) {\n    // Per W3C guidelines, arrow keys and other navigation\n    // keys should be used (instead of tab) to navigate the\n    // focus of tab buttons.\n    // See (https://www.w3.org/WAI/ARIA/apg/patterns/tabs/examples/tabs-manual/)\n    const currentElement = event.target;\n    const isFirst = currentElement.matches(\":first-child\");\n    const isLast = currentElement.matches(\":last-child\");\n    if (event.key === \"ArrowRight\") {\n      if (isLast) {\n        event.target.parentElement\n          .querySelector(\".tab-button:first-child\")\n          .focus();\n      } else {\n        currentElement.nextElementSibling.focus();\n      }\n      event.preventDefault();\n    } else if (event.key === \"ArrowLeft\") {\n      if (isFirst) {\n        event.target.parentElement\n          .querySelector(\".tab-button:last-child\")\n          .focus();\n      } else {\n        currentElement.previousElementSibling.focus();\n      }\n      event.preventDefault();\n    } else if (event.key === \"Home\") {\n      event.target.parentElement\n        .querySelector(\".tab-button:first-child\")\n        .focus();\n      event.preventDefault();\n    } else if (event.key === \"End\") {\n      event.target.parentElement\n        .querySelector(\".tab-button:last-child\")\n        .focus();\n      event.preventDefault();\n    }\n  }\n\n  scrollToAccordion(accordionElement) {\n    const accordionTop = accordionElement.getBoundingClientRect().top;\n    const buttonArea = this.querySelector(\".tab-buttons\");\n    const buttonAreaHeight = buttonArea.getBoundingClientRect().height;\n    const scrollY = accordionTop + window.scrollY - buttonAreaHeight;\n    window.scrollTo(0, scrollY);\n  }\n}\n\nif (!window.customElements.get(\"wx-tabbed-nav\")) {\n  window.customElements.define(\"wx-tabbed-nav\", TabbedNavigator);\n}\n", "/**\n * Site navigation interaction\n */\n\n// Import the tabbed-nav component, which is used by\n// the search box popout\nimport \"./TabbedNavigator.js\";\n\nconst setupSiteSearchMenuButton = (siteSubmenuElement) => {\n  const button = siteSubmenuElement.querySelector(`button[aria-expanded]`);\n\n  button.addEventListener(\"click\", () => {\n    if (button.getAttribute(\"aria-expanded\") === \"false\") {\n      button.setAttribute(\"aria-expanded\", \"true\");\n    } else {\n      button.setAttribute(\"aria-expanded\", \"false\");\n    }\n  });\n};\n\ndocument.addEventListener(\"DOMContentLoaded\", () => {\n  // Find the site search submenu and add a click listener\n  // to toggle the aria-expanded attribute.\n  const siteSearchSubmenu = document.getElementById(\"site-search-submenu\");\n  if (siteSearchSubmenu) {\n    setupSiteSearchMenuButton(siteSearchSubmenu);\n  }\n});\n", "/** @file Code to show/hide a \"scroll to top\" button. */\n\nconst mobileButton = document.querySelector(\".ride-up-button--mobile\");\nconst tabletButton = document.querySelector(\".ride-up-button--tablet\");\nconst footerRegion = document.querySelector(\"footer\");\n\nconst prefersReducedMotion = window.matchMedia?.(\n  \"(prefers-reduced-motion: reduce)\",\n)?.matches;\n\nlet scrollBracket = 0;\nlet bottomY = 0;\nlet hideThreshold = window.innerHeight * 1.75;\n// Show after scrolling up a 1/5 of a viewport.\nlet minScrollThreshold = window.innerHeight * 0.2;\nlet protectedArea = false;\n\nwindow.addEventListener(\"resize\", () => {\n  hideThreshold = window.innerHeight * 1.75;\n  minScrollThreshold = window.innerHeight * 0.2;\n});\n\nwindow.addEventListener(\n  \"scroll\",\n  () => {\n    // has the user scrolled more than 128 units?\n    if (window.scrollY / 128 !== scrollBracket) {\n      scrollBracket = window.scrollY >> 7;\n      // never show the buttons in the top 200vh or when the user scrolls down\n      if (window.scrollY < hideThreshold || window.scrollY > bottomY) {\n        mobileButton.classList.remove(\"ride-up-button--visible\");\n        tabletButton.classList.remove(\"ride-up-button--visible\");\n        bottomY = window.scrollY;\n      } else if (bottomY - window.scrollY > minScrollThreshold) {\n        mobileButton.classList.add(\"ride-up-button--visible\");\n        tabletButton.classList.add(\"ride-up-button--visible\");\n        bottomY = window.scrollY;\n      }\n    }\n  },\n  { passive: true },\n);\n\nconst scrollUp = () => {\n  if (prefersReducedMotion) {\n    window.scrollTo(0, 0);\n  } else {\n    window.scrollTo({ top: 0, behavior: \"smooth\" });\n  }\n};\n\nmobileButton.addEventListener(\"click\", scrollUp);\ntabletButton.addEventListener(\"click\", scrollUp);\n", "/**\n * WCAG compliant listbox component\n * See https://www.w3.org/WAI/ARIA/apg/patterns/listbox/\n */\n\nexport default class Listbox extends HTMLElement {\n  constructor() {\n    super();\n\n    this.template = document.createElement(\"template\");\n    this.template.innerHTML = `\n        <slot></slot>`;\n    this.attachShadow({ mode: \"open\" });\n    this.shadowRoot.append(this.template.content.cloneNode(true));\n\n    // Maps a key name to a handler for\n    // key events by the name of the key\n    this.keyMapping = {\n      ArrowUp: this.moveUp,\n      ArrowDown: this.moveDown,\n      Enter: this.selectPseudoFocused,\n      Home: this.moveHome,\n      End: this.moveEnd,\n    };\n\n    // Bind methods\n    this.bindEventListeners = this.bindEventListeners.bind(this);\n    this.unbindEventListeners = this.unbindEventListeners.bind(this);\n    this.handleFocus = this.handleFocus.bind(this);\n    this.handleKeyDown = this.handleKeyDown.bind(this);\n    this.handleItemsChanged = this.handleItemsChanged.bind(this);\n    this.moveDown = this.moveDown.bind(this);\n    this.moveUp = this.moveUp.bind(this);\n    this.moveHome = this.moveHome.bind(this);\n    this.moveEnd = this.moveEnd.bind(this);\n    this.selectPseudoFocused = this.selectPseudoFocused.bind(this);\n    this.pseudoFocusItem = this.pseudoFocusItem.bind(this);\n    this.selectItem = this.selectItem.bind(this);\n\n    this.bindEventListeners();\n  }\n\n  connectedCallback() {\n    this.bindEventListeners();\n    this.setAttribute(\"role\", \"listbox\");\n  }\n\n  disconnectedCallback() {\n    this.unbindEventListeners();\n  }\n\n  bindEventListeners() {\n    this.addEventListener(\"focus\", this.handleFocus);\n    this.shadowRoot\n      .querySelector(\"slot\")\n      .addEventListener(\"slotchange\", this.handleItemsChanged);\n    this.addEventListener(\"keydown\", this.handleKeyDown);\n    this.addEventListener(\"click\", this.handleClick);\n  }\n\n  unbindEventListeners() {\n    this.removeEventListener(\"focus\", this.handleFocus);\n    this.removeEventListener(\"keydown\", this.handleKeyDown);\n    this.removeEventListener(\"click\", this.handleClick);\n  }\n\n  handleFocus(e) {\n    // Automatically pseudo-focus the\n    // selected item.\n    // If there is no selected item,\n    // use the first item.\n    const selected = this.selection;\n    if (selected) {\n      this.pseudoFocusItem(selected);\n    } else {\n      const first = this.querySelector(`[role=\"option\"]`);\n      if (first) {\n        this.pseudoFocusItem(first);\n      }\n    }\n  }\n\n  handleClick(event) {\n    // We check to see if one of the options is in\n    // the chain of the bubbled click event\n    const closestOption = event.target.closest(`[role=\"option\"]`);\n    if (closestOption) {\n      event.currentTarget.selectItem(closestOption);\n    }\n  }\n\n  /**\n   * Attempts to look up a bound event handler\n   * for the given key, and calls it.\n   * Does nothing if the given key is not in\n   * the component's keyMapping dictionary.\n   */\n  handleKeyDown(event) {\n    if (event.target.keyMapping) {\n      const handler = event.target.keyMapping[event.key];\n      if (handler) {\n        handler.bind(this)(event);\n        event.preventDefault();\n      }\n    }\n  }\n\n  /**\n   * Handler for when slotted elements change.\n   * This is where we configure our listbox option\n   * elements as they are attached/removed.\n   * In this case, we add the data-option-index\n   * attribute to specify an order of options as they\n   * are presented in the dom (even though they can\n   * be nested in different lists).\n   * We also give each option an id based on the\n   * current component's id, if there isn't one already\n   * present.\n   */\n  handleItemsChanged(event) {\n    const host = event.target.getRootNode().host;\n    Array.from(host.querySelectorAll(`[role=\"option\"]`)).forEach(\n      (option, idx) => {\n        option.setAttribute(\"data-option-index\", idx);\n\n        // If the listbox itself has an id set, use\n        // that as a base for setting unique ids on\n        // each option. Do not set any id on an option\n        // that already has an id value.\n        // These ids are necessary for other wrapping\n        // components -- like a combobox -- that need\n        // to use aria-activedescendant to manage assistive\n        // technology focus capabilities.\n        if (!option.id && host.id) {\n          option.id = `${host.id}-option-${idx}`;\n        }\n      },\n    );\n  }\n\n  /**\n   * Pseudo Focus is what we are calling screenreader\n   * focus that is separate from the browser's DOM focus.\n   * It is managed primarily by the use of aria-activedescendant\n   * and should also be visually indicated through styling.\n   * This method removes the pseudo-focus state from all elements\n   * and if an element is also passed in, adds the state to that element.\n   * @param HTMLElement element\n   */\n  pseudoFocusItem(element) {\n    // If the passed on object is null or falsy,\n    // we un-focus all options in this component\n    Array.from(this.querySelectorAll(`[role=\"option\"]`)).forEach((option) => {\n      option.removeAttribute(\"data-pseudo-focus\");\n    });\n\n    if (element) {\n      element.setAttribute(\"data-pseudo-focus\", \"true\");\n\n      // Some listboxes might be inside an overflowed\n      // or scrolling container. Be sure to scroll the\n      // focused item into view\n      if (element.offsetTop < this.scrollTop) {\n        // user has scrolled past the item, so go back up\n        this.scrollTop = element.offsetTop;\n      } else if (\n        element.offsetTop + element.offsetHeight >\n        this.scrollTop + this.offsetHeight\n      ) {\n        // user is above the item, so go down\n        this.scrollTop =\n          element.offsetTop - this.offsetHeight + element.offsetHeight;\n      }\n\n      // If this component as the attribute\n      // `selection-follows-focus` set to \"true\",\n      // we also select the element we are focusing\n      if (this.getAttribute(\"selection-follows-focus\") === \"true\") {\n        this.selectItem(element);\n      }\n    }\n  }\n\n  /**\n   * If there is an item that is currently pseudo-focused,\n   * this method will call selectItem on that element.\n   */\n  selectPseudoFocused() {\n    const element = this.pseudoFocus;\n    if (element) {\n      this.selectItem(element);\n    }\n  }\n\n  /**\n   * Select item marks the provided element as being\n   * selected, for the purposes of listbox selection.\n   * It will also remove selection on any previously\n   * selected element(s).\n   * If the fireEvent parameter is set to true (as is by default),\n   * a change event will be dispatched from this component.\n   * @param HTMLElement element\n   * @param boolean fireEvent - Whether or not to dispatch\n   * a change event after selection. True by default.\n   */\n  selectItem(element, fireEvent = true) {\n    // De-select any that are already selected\n    Array.from(this.querySelectorAll(`[aria-selected=\"true\"]`)).forEach(\n      (selectedEl) => {\n        selectedEl.removeAttribute(\"aria-selected\");\n      },\n    );\n\n    // If there is an incoming element, select that one.\n    // By moving this into a cased control flow,\n    // we ensure that passing a falsy value for the element\n    // has the effect of clearing the current selection only.\n    if (element) {\n      element.setAttribute(\"aria-selected\", \"true\");\n      this.value = element.getAttribute(\"value\");\n    }\n\n    if (fireEvent) {\n      this.dispatchEvent(\n        new Event(\"change\", {\n          bubbles: true,\n          cancelable: true,\n        }),\n      );\n    }\n  }\n\n  /**\n   * Moves the pseudo focus one option previous\n   * in the listbox, based on overall option order.\n   * Navigation triggers the custom event wx:popup-nav\n   */\n  moveUp(event) {\n    // Find the element with the pseudo-focus.\n    // If there isn't one, bail.\n    const current = this.pseudoFocus;\n    if (current) {\n      const options = Array.from(this.querySelectorAll(`[role=\"option\"]`));\n      const currentIndex = options.indexOf(current);\n      const prev = currentIndex > 0 ? options[currentIndex - 1] : null;\n      // If prev does not exist, the call to pseudoFocusItem\n      // will un-pseudo focus everything the component\n      this.pseudoFocusItem(prev);\n      this.dispatchEvent(\n        new CustomEvent(\"wx:popup-nav\", {\n          bubbles: true,\n          detail: {\n            previous: current,\n            next: prev,\n            beyondTop: !prev && !this.pseudoFocus,\n            navCommand: \"moveUp\",\n          },\n        }),\n      );\n    }\n  }\n\n  /**\n   * Moves the pseudo focus to the next option\n   * element in the listbox, based on overall option\n   * order.\n   * Navigation triggers the custom event wx:popup-nav\n   */\n  moveDown(event) {\n    const current = this.pseudoFocus;\n    const options = Array.from(this.querySelectorAll(`[role=\"option\"]`));\n    if (!options.length) {\n      return;\n    }\n    const firstOption = options[0];\n    const lastOption = options[options.length - 1];\n    if (current === lastOption) {\n      return;\n    }\n    const currentIndex = options.indexOf(current);\n    const next = currentIndex >= 0 ? options[currentIndex + 1] : firstOption;\n\n    if (next && next !== current) {\n      this.pseudoFocusItem(next);\n      this.dispatchEvent(\n        new CustomEvent(\"wx:popup-nav\", {\n          bubbles: true,\n          detail: {\n            previous: current,\n            next: next,\n            navCommand: \"moveDown\",\n          },\n        }),\n      );\n    }\n  }\n\n  /**\n   * Moves the pseudo focus to the last option overall.\n   * Navigation triggers the custom event wx:popup-nav\n   */\n  moveHome(event) {\n    const current = this.pseudoFocus;\n    const options = Array.from(this.querySelectorAll(`[role=\"option\"]`));\n    const firstOption = options.length ? options[0] : null;\n    if (current && firstOption && current !== firstOption) {\n      this.pseudoFocusItem(firstOption);\n\n      this.dispatchEvent(\n        new CustomEvent(\"wx:popup-nav\", {\n          bubbles: true,\n          detail: {\n            previous: current,\n            next: firstOption,\n          },\n        }),\n      );\n    }\n  }\n\n  /**\n   * Moves the pseudo focus to the first option overall.\n   * Navigation triggers the custom event wx:popup-nav\n   */\n  moveEnd(event) {\n    const current = this.pseudoFocus;\n    const options = Array.from(this.querySelectorAll(`[role=\"option\"]`));\n    const lastOption = options.length ? options[options.length - 1] : null;\n    if (current && lastOption && current !== lastOption) {\n      this.pseudoFocusItem(lastOption);\n\n      this.dispatchEvent(\n        new CustomEvent(\"wx:popup-nav\", {\n          bubbles: true,\n          detail: {\n            previous: current,\n            next: lastOption,\n          },\n        }),\n      );\n    }\n  }\n\n  get selection() {\n    return this.querySelector(`[role=\"option\"][aria-selected=\"true\"]`);\n  }\n\n  get pseudoFocus() {\n    return this.querySelector(`[data-pseudo-focus=\"true\"]`);\n  }\n\n  static get observedAttributes() {\n    return [\"selection-follows-focus\"];\n  }\n}\n\nwindow.customElements.define(\"wx-listbox\", Listbox);\n", "import \"./combobox/listbox.js\";\n\nexport function navigateToElement(combobox) {\n  const popup = combobox.querySelector('[slot=\"popup\"]');\n  const selected = popup && popup.selection;\n  const targetUrl = selected && selected.getAttribute(\"data-value\");\n\n  if (targetUrl) {\n    window.location.href = targetUrl;\n  }\n}\n\n// Make navigateToElement available globally for inline onchange handler\nwindow.navigateToElement = navigateToElement;\n\ndocument.addEventListener(\"DOMContentLoaded\", () => {\n  const sections = document.querySelectorAll(\".section-content h2[id]\");\n  const navLinks = document.querySelectorAll(\".usa-sidenav__item a\");\n\n  const observerOptions = {\n    root: null, // Uses the browser viewport\n    rootMargin: \"0px 0px -90% 0px\", // Triggers when section hits the upper-middle screen\n    threshold: 0,\n  };\n\n  const observerCallback = (entries) => {\n    entries.forEach((entry) => {\n      if (entry.isIntersecting) {\n        const id = entry.target.getAttribute(\"id\");\n\n        // Remove active class from all links\n        navLinks.forEach((link) => link.classList.remove(\"usa-current\"));\n\n        // Add active class to matching link\n        const activeLink = document.querySelector(\n          `.usa-sidenav__item a[href=\"#${id}\"]`,\n        );\n        if (activeLink) {\n          activeLink.classList.add(\"usa-current\");\n        }\n      }\n    });\n  };\n\n  // Set the first link as active on page load\n  if (navLinks.length > 0) {\n    navLinks[0].classList.add(\"usa-current\");\n  }\n\n  const observer = new IntersectionObserver(observerCallback, observerOptions);\n  sections.forEach((section) => observer.observe(section));\n});\n", "/** @file this is for the events to show and hide the wx-loader */\n\nconst hideNavigationLoader = () => {\n  document.querySelectorAll(\"wx-search-loading-indicator\").forEach((loader) => {\n    loader.setAttribute(\"aria-hidden\", true);\n  });\n};\n\n/**\n * If there is a navigation loader available on the page,\n * make sure that it is being displayed.\n *\n * Each loader is supposed to have a `loader-for` attribute\n * with one or more unique identifiers. Pick the desired loader\n * by passing the ID when emitting the event.\n */\nconst showNavigationLoader = (event) => {\n  const loaders = document.querySelectorAll(\"wx-search-loading-indicator\");\n  const activeNav = event.detail?.id;\n\n  loaders.forEach((loader) => {\n    const loaderIsFor = (loader.getAttribute(\"loader-for\") || \"\").split(\" \");\n    if (loaderIsFor.includes(activeNav)) {\n      loader.removeAttribute(\"aria-hidden\");\n    }\n  });\n  if (loaders.length) {\n    const text = gettext(\"js.loader.loading-text.01\");\n    window.dispatchEvent(new CustomEvent(\"wx-announce\", { detail: { text } }));\n  }\n};\n\nwindow.addEventListener(\"wx-hide-navigation-loader\", hideNavigationLoader);\nwindow.addEventListener(\"wx-show-navigation-loader\", showNavigationLoader);\n\n// When the page is shown, hide the navigation loader. This is the best we can\n// do to handle hiding it when the back button is clicked. This code is not\n// (necessarily) executed again when the back button is pressed. Instead, its\n// state may simply be popped from the history stack. The pageshow event is\n// fired any time this page is shown, regardless of source, and our event\n// listener would persist as part of the popped state. The downside is there's\n// a flash of the loader before it gets hidden.\n//\n// In the event that the browser has already unloaded this page's state from\n// the history stack (to recoup memory, for example), then the page will\n// reload entirely. In that case, the loader is already hidden.\nwindow.addEventListener(\"pageshow\", hideNavigationLoader);\n", "/** @file Set up browser geolocation and handle searching by it. */\n\n(() => {\n  const goToLocationPage = (latitude, longitude) => {\n    // Submit the form, so we get the same behavior regardless of how we end up\n    // navigating to the location page.\n    const form = document.querySelector(\"form[data-location-search]\");\n    form.setAttribute(\"action\", `/forecast/point/${latitude}/${longitude}`);\n\n    form.submit();\n  };\n\n  const removeBrowserLocationButtons = (buttons) => {\n    // make a copy and reverse so we don't accidentally clobber ourselves.\n    Array.from(buttons)\n      .reverse()\n      .forEach((button) => {\n        if (button) {\n          const sibling = button.previousElementSibling;\n          if (sibling) {\n            sibling.remove();\n          }\n          button.remove();\n        }\n      });\n  };\n\n  const setupBrowserGeolocation = async () => {\n    // There can be multiple buttons used for selecting the browser location.\n    // For example, one can be hidden away in the nav bar while another is\n    // present lower down on the page. Be sure to add the behavior to\n    // all buttons\n    const buttons = document.querySelectorAll(\n      \"button.weathergov-use-browser-location\",\n    );\n\n    // If the browser does not support the geolocation API, just bail out. Take\n    // the \"use my location\" button away too. Also bop out if we don't have a\n    // button for some reason. Just being safe.\n    if (!navigator.geolocation) {\n      removeBrowserLocationButtons(buttons);\n      return;\n    }\n\n    // Whether we should independently prompt the user prior to asking the browser\n    // for their location. IF we can detect existing permissions AND the user has\n    // not already granted or denied us, THEN we should prompt first. If we can't\n    // detect existing permissions, don't prompt because otherwise we end up\n    // putting up our prompt for that user every time they try to use their\n    // location.\n    let shouldPrompt = false;\n\n    if (navigator.permissions) {\n      try {\n        // Query for geolocation permissions.\n        const status = await navigator.permissions.query({\n          name: \"geolocation\",\n        });\n\n        // If the user has already denied location, we can go ahead and bail out.\n        // Changing browser settings is not detectable within the page, so they'll\n        // have to reload to get the option back anyway.\n        //\n        // Might need to reconsider this. It might be preferable to leave the\n        // button and show users a popup. There are several reasons we might get\n        // the \"denied\" state:\n        //\n        // 1. The web browser does not have permission from the operating system.\n        // 2. The web browser is configured to deny permission by default.\n        // 3. The user has denied access to our site in particular.\n        //\n        // In cases 1 and 2, users may not be aware of their settings. If we show\n        // the button and then popup a message when they click it letting them\n        // know they need to change their browser settings, maybe that's useful.\n        // The immediate drawback I can think of is we have no way of knowing\n        // whether it's a browser setting or an operating system setting, so we\n        // can't give them any more helpful advice than \"check your settings.\"\n        //\n        // In case 3, however, we should just leave the user alone. They have\n        // already said no, and that should be the end of it.\n        //\n        // Key important takeaway, though, is that \"denied\" means all of those\n        // things and it is impossible for us to know which.\n        if (status.state === \"denied\") {\n          removeBrowserLocationButtons(buttons);\n          return;\n        }\n\n        // If the user has not denied us permission, then we should show our own\n        // prompt if the user has not yet granted us permission.\n        shouldPrompt = status.state === \"prompt\";\n      } catch (_) {\n        // An exception in the permissions API likely indicates that the specific\n        // attribute we queried for isn't available. That doesn't mean the feature\n        // doesn't exist, though, so we should continue as if the permissions API\n        // doesn't exist at all and not use our prompt.\n      }\n    }\n\n    const buttonHandler = async (e) => {\n      // Stop any other event behavior, in case our button is inside a form\n      // or something.\n      e.preventDefault();\n      e.stopPropagation();\n\n      let proceed = true;\n\n      // If location is available and we know that the user has neither denied or\n      // granted us permission to use it, we will let them know before asking for\n      // it. It's kind of a double-opt-in.\n      if (shouldPrompt) {\n        const text = gettext(\"js.location-search.prompt.user-consent.01\");\n        proceed = window.confirm(text);\n      }\n\n      // If we don't know about the permission, we were already approved to use\n      // it, or the user has signaled that we can ask for it... ask for it!\n      if (proceed) {\n        // Show the loader animation, if available\n        window.dispatchEvent(\n          new CustomEvent(\"wx-show-navigation-loader\", {\n            detail: { id: e.currentTarget.getAttribute(\"id\") },\n          }),\n        );\n\n        navigator.geolocation.getCurrentPosition(\n          // Success callback\n          ({ coords: { latitude, longitude } }) => {\n            // Scale down the precision on these.\n            const lat = Math.round(latitude * 1_000) / 1_000;\n            const long = Math.round(longitude * 1_000) / 1_000;\n\n            // And navigate away!\n            goToLocationPage(lat, long);\n          },\n          // Error callback\n          ({ code, message }) => {\n            if (code > 1) {\n              // There was a problem getting the user's location. They allowed it,\n              // but the browser gave us an error.\n              // (Error code 1 is for when the user denies access to location, so\n              // for our purposes, that is not an error.)\n\n              const alertText = interpolate(\n                gettext(\"js.location-search.alert.geolocation-error.01\"),\n                [message],\n              );\n              alert(alertText);\n            }\n          },\n        );\n      }\n    };\n\n    Array.from(buttons).forEach((button) => {\n      button.addEventListener(\"click\", buttonHandler);\n    });\n  };\n  setupBrowserGeolocation();\n})();\n", "/**\n * WCAG compliant Combobox component\n */\nconst comboTemplate = `\n<div>\n  <slot name=\"input\"></slot>\n  <div>\n    <slot name=\"clear-button\"></slot>\n    <slot name=\"toggle-button\"></slot>\n  </div>\n</div>\n<slot name=\"popup\"></slot>\n`;\nexport default class Combobox extends HTMLElement {\n  constructor() {\n    super();\n    this.popup = null;\n\n    this.template = document.createElement(\"template\");\n    this.template.innerHTML = comboTemplate;\n    this.attachShadow({ mode: \"open\", delegatesFocus: true });\n    this.shadowRoot.append(this.template.content.cloneNode(true));\n    this.shadowRoot.addEventListener(\n      \"slotchange\",\n      this.handleSlotChange.bind(this),\n    );\n\n    // Bound methods\n    this.handleInput = this.handleInput.bind(this);\n    this.handleFocus = this.handleFocus.bind(this);\n    this.handleBlur = this.handleBlur.bind(this);\n    this.handleListboxMouseDown = this.handleListboxMouseDown.bind(this);\n    this.handleKeyDown = this.handleKeyDown.bind(this);\n    this.showPopup = this.showPopup.bind(this);\n    this.hidePopup = this.hidePopup.bind(this);\n    this.submit = this.submit.bind(this);\n    this.handlePopupChange = this.handlePopupChange.bind(this);\n    this.handleToggleClick = this.handleToggleClick.bind(this);\n    this.handleClearClick = this.handleClearClick.bind(this);\n  }\n\n  connectedCallback() {\n    // We need to ensure that the component has a unique id.\n    // This is used to compute popup option ids, which are necessary\n    // for the correct usage of aria-activedescendant and related\n    // pseudo-focus capabilites for assistive technologies.\n    if (!this.id) {\n      console.error(\n        `${this.tagName.toLowerCase()} requires an 'id' attribute to be set`,\n      );\n    }\n\n    // Keyboard and input based events will be listened for on\n    // the input element specifically, and handled on this component.\n    this.input = this.querySelector(`input[slot=\"input\"]`);\n    if (this.input) {\n      this.input.addEventListener(\"input\", this.handleInput);\n      this.input.addEventListener(\"keydown\", this.handleKeyDown);\n      this.input.addEventListener(\"focus\", this.handleFocus);\n      this.input.addEventListener(\"blur\", this.handleBlur);\n    }\n\n    this.addEventListener(\"focus\", this.handleFocus);\n    this.addEventListener(\"blur\", this.handleBlur);\n\n    // The wx:popup-nav is a custom event that will be fired by any\n    // element that is serving as the combobox's popup, such as a\n    // listbox, whenever a navigation event occurs in that element.\n    // In our most common use case, this is when the pseudoFocus\n    // is moved within a listbox that is slotted in this combobox.\n    this.addEventListener(\"wx:popup-nav\", this.handlePopupNav);\n\n    // Set up the appropriate event handlers for the clear button\n    // and the toggle button.\n    this.toggleButton = this.querySelector(`[slot=\"toggle-button\"]`);\n    if (this.toggleButton) {\n      this.toggleButton.addEventListener(\"click\", this.handleToggleClick);\n    }\n    this.clearButton = this.querySelector(`[slot=\"clear-button\"]`);\n    if (this.clearButton) {\n      this.clearButton.addEventListener(\"click\", this.handleClearClick);\n    }\n  }\n\n  /**\n   * Will attempt to show the popup child\n   * element for the combobox, while setting\n   * the appropriate aria attributes needed for\n   * both screenreading and styling.\n   */\n  showPopup() {\n    if (this.input) {\n      this.input.setAttribute(\"aria-expanded\", true);\n      this.setAttribute(\"expanded\", true);\n    }\n    if (this.popup) {\n      const target = this.popup.selection ?? this.popup.pseudoFocus;\n      if (target) {\n        this.popup.pseudoFocusItem(target);\n      }\n    }\n  }\n\n  /**\n   * Will hide the popup child element\n   * for the combobox, by setting the appropriate\n   * attributes needed for screenreading and styling\n   */\n  hidePopup() {\n    this.removeAttribute(\"expanded\");\n    this.input.removeAttribute(\"aria-expanded\");\n    this.input.removeAttribute(\"aria-activedescendant\");\n  }\n\n  /**\n   * Find the closest ancestor <form> element.\n   * If there is one, trigger its submit() method.\n   * Because we work with an input, it will be\n   * considered part of that form and its data will be\n   * used as part of the form action.\n   */\n  submit() {\n    this.closest(\"form\")?.submit();\n  }\n\n  /**\n   * Handle any changes to slotted elements.\n   * This is where we bind and/or remove listeners for\n   * the component that serves as the popup for the\n   * combobox (usually a listbox).\n   * We do it here instead of at component callback time\n   * because we want to leave open the possibility for\n   * popups to be dynamically swapped out if needed,\n   * and to still have all the appropriate event handling\n   * setup when that happens.\n   * This handler also sets ids on the popup itself if\n   * there isn't already one, as well as updating the\n   * combobox input aria-controls to map to the\n   * incoming popup element.\n   */\n  handleSlotChange(event) {\n    const name = event.target.getAttribute(\"name\");\n    const assigned = event.target.assignedElements();\n\n    if (name === \"popup\") {\n      // If there is an existing popup that was attached,\n      // remove any event listeners from it.\n      if (this.popup) {\n        this.popup.removeEventListener(\"change\", this.handlePopupChange);\n        this.popup.removeEventListener(\n          \"mousedown\",\n          this.handleListboxMouseDown,\n        );\n      }\n\n      // Now check if there is a new popup assigned or\n      // if the slot is empty. Either way assign the value\n      // to the stored popup\n      this.popup = assigned.length ? assigned[0] : null;\n      if (this.popup) {\n        this.popup.addEventListener(\"change\", this.handlePopupChange);\n        this.popup.addEventListener(\"mousedown\", this.handleListboxMouseDown);\n\n        // If the listbox element does not have an id set, use\n        // this component's id as a base for creating a unique id.\n        // The listbox options need to have their own unique ids\n        // for the use of aria-activedescendant, which handles pseudo\n        // focus in assistive technologies\n        if (!this.popup.id) {\n          this.popup.id = `${this.id}-popup`;\n\n          // Trigger slotchange event manually\n          this.popup.innerHTML = this.popup.innerHTML;\n        }\n        this.input.setAttribute(\"aria-controls\", this.popup.id);\n\n        this.handlePopupChange({ target: this.popup });\n      }\n    }\n  }\n\n  /**\n   * We need to stop the default behavior of mousedown\n   * on the listbox, so that the normal browser doesn't\n   * try to change focus/blur. This is what otherwise happens\n   * in FF and Safari (but not Chrome), where click events\n   * in the listbox will never be hit because by that time\n   * the input has already blurred and lost focus.\n   */\n  handleListboxMouseDown(event) {\n    event.preventDefault();\n  }\n\n  /**\n   * Handle specific popup navigation event cases.\n   * We want to open the popup if the user tries to\n   * navigate down and it's not already open.\n   * Likewise, if we are already at the top of the popup and\n   * we move up again, it should hide the component.\n   * An additional behavior that is crucial for accessibility\n   * is that any popup child that has pseudofocus will be mapped\n   * to the combobox input's aria-activedescendant, which is a\n   * way of mapping screenreader focus that is separate from\n   * browser element focus.\n   */\n  handlePopupNav(event) {\n    if (event.detail.beyondTop) {\n      // If the user has navigated beyond the top option in the list\n      // (usually a #moveUp when the first item is already selected),\n      // we hide the list\n      this.hidePopup();\n    } else if (\n      event.detail.navCommand === \"moveDown\" &&\n      !event.detail.previous\n    ) {\n      // If there was no previous focus element and we are moving down,\n      // we should attempt to open the popup. This scenario can occur if:\n      // 1. The user has focused the input, revelating the popup, then\n      // 2. The user navigated up past the first item, closing the popup, then\n      // 3. The user navigated down again\n      this.showPopup();\n    }\n\n    // If there is an item pseudoFocused, we update\n    // aria-activedescendant.\n    // Otherwise, remove the attribute entirely\n    if (event.target.pseudoFocus) {\n      this.input.setAttribute(\n        \"aria-activedescendant\",\n        event.target.pseudoFocus.id,\n      );\n    } else {\n      this.input.removeAttribute(\"aria-activedescendant\");\n    }\n  }\n\n  /**\n   * Popup elements can fire generic change events.\n   * In the case of a combobox, we expect that the target\n   * of the event can have a selection.\n   * Set the value of the combobox input to the provided selection.\n   */\n  handlePopupChange(event) {\n    if (event.target.selection) {\n      this.hidePopup();\n\n      const option = event.target.selection;\n      const value = option.getAttribute?.(\"data-value\");\n\n      // \"data-value-for\" is the id of a hidden input used to store the \"real\" value\n      const id = this.input.getAttribute(\"data-value-for\");\n\n      if (value && id) {\n        const element = this.querySelector(`input[name=${id}][type=hidden]`);\n        if (element) element.value = value;\n      }\n\n      this.input.value = event.target.selection.textContent || null;\n    } else {\n      this.input.value = null;\n    }\n\n    if (this.input.value) {\n      const clearButton = this.querySelector(`[slot=\"clear-button\"]`);\n      clearButton.classList.remove(\"empty\");\n    }\n  }\n\n  /**\n   * The combobox keydown event handler will attempt\n   * to find a keyMapping dictionary on its slotted popup\n   * component, such as is available for a listbox.\n   * This allows us to trigger the popup's handlers for the given\n   * keys, without needed to implement them all over again\n   * in this component.\n   */\n  handleKeyDown(event) {\n    const popupIsOpen = this.getAttribute(\"expanded\") === \"true\";\n    if (this.popup) {\n      if (event.key === \"Escape\") {\n        this.popup.pseudoFocusItem(null);\n        return this.hidePopup();\n      } else if (event.key === \"ArrowDown\" && !popupIsOpen) {\n        // We focus the first item\n        this.popup.pseudoFocusItem(\n          this.popup.querySelector(`[role=\"option\"][data-option-index=\"0\"]`),\n        );\n        return this.showPopup();\n      }\n\n      // Otherwise, let the listbox handle the event, so long\n      // as it has a keymapping defined.\n      if (this.popup.keyMapping) {\n        const handler = this.popup.keyMapping[event.key];\n        if (handler) {\n          const boundHandler = handler.bind(this.popup);\n          boundHandler(event);\n          event.preventDefault();\n        }\n      }\n    }\n  }\n\n  /**\n   * Cick handler for the toggle button.\n   * Will show or hide the popup depending\n   * on the state.\n   */\n  handleToggleClick(event) {\n    event.preventDefault();\n    if (this.getAttribute(\"expanded\") === \"true\") {\n      this.hidePopup();\n    } else {\n      this.showPopup();\n      this.input.focus();\n    }\n  }\n\n  /**\n   * Click handler for the clear button.\n   * Will clear the input and reset state on the\n   * popup.\n   */\n  handleClearClick(event) {\n    event.preventDefault();\n    this.popup.pseudoFocusItem(null);\n    this.input.value = \"\";\n    this.handleInput();\n    this.input.focus();\n    this.hidePopup();\n  }\n\n  /**\n   * Text input handler for the combobox input element.\n   * Will attempt to call the `filterText()` method of any\n   * slotted popup element using the input's current value.\n   * Will also update the presence of the clear button based\n   * on the input's new value.\n   */\n  handleInput(event) {\n    if (this.popup) {\n      if (!this.hasAttribute(\"expanded\")) {\n        this.showPopup();\n      }\n      if (this.popup.filterText) {\n        this.popup.filterText(this.input.value);\n      }\n    }\n\n    // Hide or show the clear button's slot\n    // based on the input value's presence\n    const clearButton = this.querySelector(`[slot=\"clear-button\"]`);\n    if (this.input.value && this.input.value !== \"\") {\n      clearButton.classList.remove(\"empty\");\n    } else {\n      clearButton.classList.add(\"empty\");\n    }\n  }\n\n  /**\n   * When gaining focus, show the popup but only\n   * if there are actual options available in the popup.\n   */\n  handleFocus(event) {\n    const hasItems = this.popup.querySelectorAll(`[role=\"option\"]`).length;\n    if (hasItems) {\n      this.showPopup();\n    }\n  }\n\n  /**\n   * Hide the popup when this element loses focus.\n   */\n  handleBlur(event) {\n    // Only perform blur operations if the target of the\n    // event is outside of the combobox component\n    const ancestor = event.relatedTarget?.closest(this.tagName);\n    if (ancestor !== this) {\n      this.popup.pseudoFocusItem(null);\n      this.hidePopup();\n      if (this.popup && this.popup.selection) {\n        this.input.value = this.popup.selection.textContent;\n        const clearButton = this.querySelector(`[slot=\"clear-button\"]`);\n        clearButton.classList.remove(\"empty\");\n      }\n    }\n  }\n\n  /**\n   * The only attribute we listen for changes on is 'disabled',\n   * which reacts by disabling (or re-enabling) all constinuent\n   * elements that can be disabled. This prevents any key or mouse\n   * events from triggering event handlers.\n   */\n  attributeChangedCallback(name, oldVal, newVal) {\n    if (name === \"disabled\" && newVal === \"true\") {\n      this.input.setAttribute(\"disabled\", true);\n      this.clearButton.setAttribute(\"disabled\", true);\n      this.toggleButton.setAttribute(\"disabled\", true);\n      this.hidePopup();\n    } else if (name === \"disabled\") {\n      this.input.removeAttribute(\"disabled\");\n      this.clearButton.removeAttribute(\"disabled\");\n      this.toggleButton.removeAttribute(\"disabled\");\n    }\n  }\n\n  get isExpanded() {\n    return this.getAttribute(\"expanded\") === \"true\";\n  }\n\n  static get observedAttributes() {\n    return [\"disabled\"];\n  }\n}\n\nif (!window.customElements.get(\"wx-combobox\")) {\n  window.customElements.define(\"wx-combobox\", Combobox);\n}\n", "/** @file Manage a visitor's recent locations in local storage. */\n\nconst RECENT_LOC_STORAGE = \"wxgov_recent_locations\";\n\n/**\n * @typedef {Object} RecentLocation from local storage\n * @property {string} url the point forecast url for the location\n * @property {string} text the human-readable location name\n */\n\n/**\n * Get the list of recent locations from local storage.\n *\n * @returns {RecentLocation}\n */\nexport function getRecentLocations() {\n  try {\n    const existing = localStorage.getItem(RECENT_LOC_STORAGE);\n    const parsed = JSON.parse(existing ?? \"[]\");\n\n    // Check if any saved locations still have the old /point/lat/long url format\n    const needsUpdate = parsed.filter(({ url }) => url.startsWith(\"/point\"));\n\n    if (needsUpdate.length > 0) {\n      // Prepend the forecast path to any URLs that need it\n      const updated = parsed.map(({ url, ...rest }) => ({\n        ...rest,\n        url: url.startsWith(\"/forecast\") ? url : `/forecast${url}`,\n      }));\n      localStorage.setItem(RECENT_LOC_STORAGE, JSON.stringify(updated));\n      return updated;\n    }\n    return parsed;\n  } catch (e) {\n    return [];\n  }\n}\n\n/**\n * Insert a recent location into local storage.\n * If the location already exists, move it to the top.\n *\n * @param {RecentLocation} obj - the recent location\n */\nexport function addRecentLocation(obj) {\n  try {\n    // First we need to see if there are any existing\n    // items already saved in the saved searches array\n    const existing = localStorage.getItem(RECENT_LOC_STORAGE);\n    const parsed = JSON.parse(existing ?? \"[]\");\n    // Now remove any items for the same URL. This way we don't\n    // end up having a whole list of the same place\n    const filtered = parsed.filter(({ url }) => url !== obj.url);\n    // Just keep the most recent ten.\n    const sliced = filtered.slice(0, 9);\n\n    // Put the new entry at the front of the list\n    sliced.unshift(obj);\n\n    // Now serialize and save\n    localStorage.setItem(RECENT_LOC_STORAGE, JSON.stringify(sliced));\n  } catch (e) {\n    /* do nothing */\n  }\n}\n", "import Listbox from \"./listbox.js\";\nimport { getRecentLocations, addRecentLocation } from \"../recent-locations.js\";\nimport Timer from \"../timer.js\";\n\nconst debouncer = new Timer();\n\nconst getRedirectUrlFromAddressCandidate = (addressCandidate) => {\n  const { type, lat, lon, abbr } = addressCandidate;\n  const typeLowercase = type.toLowerCase();\n  if (typeLowercase === \"county\") {\n    return `/wx/location-search/county/${lat}/${lon}`;\n  } else if (typeLowercase === \"state or province\" && abbr) {\n    return `/forecast/state/${abbr}`;\n  }\n  return `/forecast/point/${lat}/${lon}`;\n};\n\n/**\n * @typedef {Object} Suggestion from geocode.arcgis.com\n * @property {boolean} isCollection\n * @property {string} magicKey\n * @property {string} text the human-readable location name\n */\n\n/**\n * @typedef {Object} SavedLocation from local storage\n * @property {string} url the point forecast url for the location\n * @property {string} text the human-readable location name\n */\n\n/**\n * Helper function. Creates an `li` element for a given choice.\n *\n * @param {number} setSize the number of results in the list\n * @param {string|undefined} describedby the id of the element which describes the list (optional)\n * @param {Suggestion|SavedLocation} suggestion the data for this item\n * @param {number} idx the item's position in the list\n * */\nconst makeListItemFromResultItem = (setSize, describedby, suggestion, idx) => {\n  const item = document.createElement(\"li\");\n  item.innerText = suggestion.text;\n  item.setAttribute(\"role\", \"option\");\n  item.setAttribute(\"aria-setsize\", setSize);\n  item.setAttribute(\"posinset\", idx + 1);\n  item.setAttribute(\"aria-selected\", false);\n  if (describedby) {\n    item.setAttribute(\"aria-describedby\", describedby);\n  }\n  if (suggestion.magicKey) {\n    item.setAttribute(\"data-magic-key\", suggestion.magicKey);\n  } else if (suggestion.url) {\n    item.setAttribute(\"data-url\", suggestion.url);\n  } else {\n    return null;\n  }\n  return item;\n};\n\n/**\n * Given a `ul` for location search results, create all the child `li`s.\n *\n * @param {HTMLElement} resultListElement the container for the result list\n * @param {HTMLElement|undefined} ariaDescEl the element which describes the list (optional)\n * @param {Array<Suggestion|SavedLocation>} suggestions\n */\nconst makeListFromResult = (resultListElement, ariaDescEl, suggestions) => {\n  resultListElement.innerHTML = \"\";\n  const setSize = suggestions.length;\n  const describedby = ariaDescEl.id;\n  const newItems = suggestions.map((suggestion, idx) => {\n    return makeListItemFromResultItem(setSize, describedby, suggestion, idx);\n  });\n  resultListElement.append(...newItems);\n};\n\nexport default class LocationListbox extends Listbox {\n  constructor() {\n    super();\n\n    // Private property defaults\n    this.inputDelay = 250;\n\n    // Bound component methods\n    this.updateSavedSearches = this.updateSavedSearches.bind(this);\n    this.getSearchResults = this.getSearchResults.bind(this);\n    this.handlePopupNav = this.handlePopupNav.bind(this);\n  }\n\n  connectedCallback() {\n    super.connectedCallback();\n\n    this.addEventListener(\"wx:popup-nav\", this.handlePopupNav);\n\n    // If there is a place set via attribute, we add\n    // it to the saved search results\n    if (this.dataset.place) {\n      addRecentLocation({\n        text: this.dataset.place,\n        url: window.location.pathname,\n      });\n    }\n    this.updateSavedSearches();\n  }\n\n  /**\n   * Override selectItem to first fetch the location data\n   * (either from cache or live) for the option with the\n   * given magicKey\n   */\n  selectItem(element) {\n    // For consistency, let's force even the regular calls\n    // to selectItem to be wrapped as promises\n    const selectItemPromise = new Promise((resolve) => {\n      resolve(super.selectItem(element));\n    });\n\n    // If the incoming element is falsy, just return the\n    // promise to call the super version.\n    if (!element) {\n      return selectItemPromise;\n    }\n\n    // Otherwise, if the option's data-url attribute exists, use that.\n    if (element.getAttribute(\"data-url\")) {\n      return new Promise((resolve) => {\n        if (this.getAttribute(\"auto-submit\") === \"true\") {\n          addRecentLocation({\n            text: element.innerText,\n            url: element.getAttribute(\"data-url\"),\n          });\n          const form = this.closest(\"form[data-location-search]\");\n          form.setAttribute(\"action\", element.getAttribute(\"data-url\"));\n          form.submit();\n          // Show the loader animation, if available\n          window.dispatchEvent(\n            new CustomEvent(\"wx-show-navigation-loader\", {\n              detail: { id: this.getAttribute(\"id\") },\n            }),\n          );\n        }\n\n        resolve(super.selectItem(element));\n      });\n    }\n\n    // Otherwise, attempt to get cached/fetched\n    // geographic data and add that to the option element\n    // dataset/attributes.\n    // This is so consumers of the change event can see the result.\n    if (element.dataset.magicKey) {\n      return this.getGeodataForKey(element.dataset.magicKey).then((geoData) => {\n        if (geoData) {\n          element.setAttribute(\"data-lat\", geoData.lat);\n          element.setAttribute(\"data-lon\", geoData.lon);\n          if (this.getAttribute(\"auto-submit\") === \"true\") {\n            const formUrl = getRedirectUrlFromAddressCandidate(geoData);\n\n            addRecentLocation({\n              text: element.innerText,\n              url: formUrl,\n            });\n\n            const form = this.closest(\"form[data-location-search]\");\n            form.setAttribute(\"action\", formUrl);\n            form.submit();\n            // Show the loader animation, if available\n            window.dispatchEvent(\n              new CustomEvent(\"wx-show-navigation-loader\", {\n                detail: { id: this.getAttribute(\"id\") },\n              }),\n            );\n          }\n        }\n        super.selectItem(element);\n      });\n    }\n\n    return selectItemPromise;\n  }\n\n  /**\n   * For this subclass of the listbox, we want to\n   * prefetch and cache location data for the magicKey\n   * for any result list item. We speculatively do so\n   * whenever a given item receives the pseudoFocus.\n   */\n  handlePopupNav(event) {\n    if (this.pseudoFocus) {\n      const key = this.pseudoFocus.dataset.value;\n      this.cacheLocationGeodata(key);\n    }\n  }\n\n  /**\n   * Retrieve saved locations from local storage and\n   * insert them into the popup, filtering first by\n   * `filterTerm` if one is given.\n   */\n  updateSavedSearches(filterTerm) {\n    const savedSearchesGroup = this.querySelector(\n      '[role=\"group\"].saved-searches',\n    );\n    const savedSearchesLabel = this.querySelector(\n      '[role=\"heading\"].saved-searches',\n    );\n    if (savedSearchesGroup) {\n      let saved = getRecentLocations();\n\n      // Clear any existing search items in the element.\n      // We will regenerate them.\n      savedSearchesGroup.innerHTML = \"\";\n\n      if (filterTerm) {\n        const match = filterTerm.toLowerCase();\n        saved = saved.filter((option) =>\n          option.text.toLowerCase().includes(match),\n        );\n      }\n\n      // If there are no saved searches, we should hide\n      // the list and the label together\n      if (!saved.length) {\n        savedSearchesLabel?.classList?.add?.(\"hidden\");\n        savedSearchesGroup.classList.add(\"hidden\");\n      } else {\n        savedSearchesLabel?.classList?.remove?.(\"hidden\");\n        savedSearchesGroup.classList.remove(\"hidden\");\n        makeListFromResult(savedSearchesGroup, savedSearchesLabel, saved);\n      }\n    }\n  }\n\n  async getSearchResults(text) {\n    const response = await this.searchLocation(text);\n    if (response.ok) {\n      const data = await response.json();\n      return data;\n    }\n    return { suggestions: [] };\n  }\n\n  /** Announce updated search results in an Aria live region. */\n  announceResults() {\n    const numResults = this.querySelectorAll(\"li\").length;\n    const translation = ngettext(\n      \"js.location-combo-box.aria.search-updated.01\",\n      \"js.location-combo-box.aria.search-updated.01-plural\",\n      numResults,\n    );\n    const transWithCount = interpolate(translation, [numResults]);\n    window.dispatchEvent(\n      new CustomEvent(\"wx-announce\", {\n        detail: { text: transWithCount, delay: 0 },\n      }),\n    );\n  }\n\n  async filterText(text) {\n    debouncer.start(async () => {\n      const data = await this.getSearchResults(text);\n      const resultListElement = this.querySelector(\n        '[role=\"group\"].data-results',\n      );\n      const headerElement = this.querySelector('[role=\"heading\"].data-results');\n      if (resultListElement) {\n        resultListElement.remove();\n        makeListFromResult(resultListElement, headerElement, data.suggestions);\n        this.append(resultListElement);\n      }\n      this.updateSavedSearches(text);\n      this.announceResults();\n    }, this.inputDelay);\n  }\n\n  /**\n   * Asynchronously fetches specific location data\n   * for a given search result, stashing it away in\n   * the cache\n   */\n  async cacheLocationGeodata(magicKey) {\n    if (!window.sessionStorage.getItem(magicKey)) {\n      const result = await this.getLocationGeodata(magicKey);\n      window.sessionStorage.setItem(magicKey, JSON.stringify(result));\n    }\n  }\n\n  /**\n   * Attempts to retrieve location data for a search\n   * result by its magicKey from the cache.\n   * If not present, will make the Arc API call\n   * to fetch the data.\n   */\n  async getGeodataForKey(magicKey) {\n    const cached = window.sessionStorage.getItem(magicKey);\n    if (!cached) {\n      return this.getLocationGeodata(magicKey);\n    }\n    return JSON.parse(cached);\n  }\n\n  async getLocationGeodata(magicKey) {\n    const url = `https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/findAddressCandidates?magicKey=${magicKey}&f=json&_=1695666335115&outFields=Type,RegionAbbr`;\n    const response = await fetch(url, {\n      headers: { \"Content-Type\": \"application/json\" },\n    });\n    const results = await response.json();\n    return this.processLocationGeodata(results);\n  }\n\n  processLocationGeodata(results) {\n    if (\n      !results.error &&\n      Array.isArray(results.candidates) &&\n      results.candidates.length > 0\n    ) {\n      // Take the first available location (highest score)\n      const firstCandidate = results.candidates[0];\n      const { x, y } = firstCandidate.location;\n      const type = firstCandidate.attributes.Type;\n      const abbr = firstCandidate.attributes.RegionAbbr;\n\n      const lat = Math.round(y * 1_000) / 1_000;\n      const lon = Math.round(x * 1_000) / 1_000;\n      return { lat, lon, type, abbr };\n    }\n\n    return null;\n  }\n\n  async searchLocation(text) {\n    const url = `https://geocode.arcgis.com/arcgis/rest/services/World/GeocodeServer/suggest?f=json&countryCode=USA%2CPRI%2CVIR%2CGUM%2CASM&category=Land+Features%2CBay%2CChannel%2CCove%2CDam%2CDelta%2CGulf%2CLagoon%2CLake%2COcean%2CReef%2CReservoir%2CSea%2CSound%2CStrait%2CWaterfall%2CWharf%2CAmusement+Park%2CHistorical+Monument%2CLandmark%2CTourist+Attraction%2CZoo%2CCollege%2CBeach%2CCampground%2CGolf+Course%2CHarbor%2CNature+Reserve%2COther+Parks+and+Outdoors%2CPark%2CRacetrack%2CScenic+Overlook%2CSki+Resort%2CSports+Center%2CSports+Field%2CWildlife+Reserve%2CAirport%2CFerry%2CMarina%2CPier%2CPort%2CResort%2CPostal%2CPopulated+Place&maxSuggestions=10&_=1695666335097&text=${text}`;\n    return fetch(url, { headers: { \"Content-Type\": \"application/json\" } });\n  }\n}\n\nif (!window.customElements.get(\"wx-location-listbox\")) {\n  window.customElements.define(\"wx-location-listbox\", LocationListbox);\n}\n", "/** @file Manage a visitor's recent/favorite locations in local storage. */\n\nconst SAVED_LOC_STORAGE = \"wxgov_saved_locations\";\nconst RECENT_LOC_STORAGE = \"wxgov_recent_locations\";\nconst TAB_REGEX = new RegExp(\"\\/(?:alerts|today|7-day|maps|analysis).*\", \"i\");\n\n/**\n * @typedef {Object} SavedLocations from local storage\n * @property {Object.<string, string>} hashed object of saved location (lowercase-text : url)\n * @property {Array<SavedLocation>} sorted sorted list of saved locations\n */\n\n/**\n * @typedef {Object} SavedLocation from local storage\n * @property {string} text the human-readable location name\n * @property {string} url the point forecast url for the location\n */\n\n/**\n * Remove a trailing forecast tab while preserving the rest of the URL.\n * @param {string} url location URL\n * @returns {string} location URL without a tab suffix\n */\nfunction normalizeLocationUrl(url) {\n  if (typeof url !== \"string\") return url;\n\n  return url.replace(TAB_REGEX, \"\");\n}\n\n/**\n * Normalize both URL representations in a saved-location collection.\n * @param {SavedLocations} storage saved location collection\n * @returns {SavedLocations} normalized collection\n */\nfunction normalizeSavedLocationStorage(storage) {\n  if (storage?.hashed) {\n    storage.hashed = Object.fromEntries(\n      Object.entries(storage.hashed).map(([text, url]) => [\n        text,\n        normalizeLocationUrl(url),\n      ]),\n    );\n  }\n  if (storage?.sorted) {\n    storage.sorted = storage.sorted.map((location) => ({\n      ...location,\n      url: normalizeLocationUrl(location.url),\n    }));\n  }\n  return storage;\n}\n\n/**\n * Get JSON parsed local storage for saved locations\n * @returns {SavedLocations}\n */\nfunction getParsedSavedLocationStorage() {\n  const storage = localStorage.getItem(SAVED_LOC_STORAGE);\n  const parsedStorage = JSON.parse(storage ?? \"{}\");\n  return normalizeSavedLocationStorage(parsedStorage);\n}\n\n/**\n * Set saved location local storage to new JSON item\n * @param {SavedLocations} newStorage saved location collection to set\n */\nfunction setSavedLocationStorage(newStorage) {\n  localStorage.setItem(\n    SAVED_LOC_STORAGE,\n    JSON.stringify(normalizeSavedLocationStorage(newStorage)),\n  );\n}\n\n/**\n * Get the sorted list of saved locations from local storage\n * @returns {Array<SavedLocation>}\n */\nexport function getSavedLocations() {\n  const current = getParsedSavedLocationStorage();\n\n  return current?.sorted ? current.sorted : [];\n}\n\n/**\n * Returns if location is within the saved location local storage\n * @param {string} locText location to match if in saved location storage\n * @returns {boolean}\n */\nexport function hasSavedLocation(locText) {\n  let found = false;\n  if (locText?.length) {\n    const locLower = locText?.toLowerCase();\n    const existing = getParsedSavedLocationStorage();\n    found = existing?.hashed && Object.hasOwn(existing.hashed, locLower);\n  }\n  return found;\n}\n\n/**\n * Adds a new location to saved locations in local storage, maintaining sorted order\n * @param {SavedLocation} obj saved location object to add to storage\n */\nexport function addSavedLocation(obj) {\n  // Validate obj\n  if (!obj && !obj?.text?.toLowerCase() && !obj?.url) return;\n\n  const textLower = obj.text.toLowerCase();\n  const existing = getParsedSavedLocationStorage();\n  const hashed = existing?.hashed ?? {};\n  const sorted = existing?.sorted ?? [];\n\n  if (!Object.hasOwn(hashed, textLower)) {\n    if (sorted?.length) {\n      // Find the correct sorted location to insert new element based on text\n      const largerElemIndex = sorted.findIndex((item) => {\n        return item?.text?.toLowerCase() > textLower;\n      });\n      // Insert new element before the larger element\n      if (largerElemIndex === -1) {\n        sorted.push(obj);\n      } else {\n        sorted.splice(largerElemIndex, 0, obj);\n      }\n    } else {\n      sorted.push(obj);\n    }\n    hashed[textLower] = obj?.url;\n    setSavedLocationStorage({\n      hashed: hashed,\n      sorted: sorted,\n    });\n  }\n}\n\n/**\n * Removes the saved location from storage that matches the location string\n * @param {string} loc location string to remove from storage\n */\nexport function removeSavedLocation(loc) {\n  const locLower = loc?.toLowerCase();\n  const existing = getParsedSavedLocationStorage();\n  const existingSorted = existing?.sorted ?? [];\n  const existingHashed = existing?.hashed ?? {};\n  const existingElemIdx = existingSorted.findIndex((item) => {\n    return item?.text?.toLowerCase() === locLower;\n  });\n\n  if (existingElemIdx > -1) {\n    // Remove element in place and update storage with new collection\n    existingSorted.splice(existingElemIdx, 1);\n    delete existingHashed[loc.toLowerCase()];\n    setSavedLocationStorage({ sorted: existingSorted, hashed: existingHashed });\n  }\n}\n", "/**\n * Saved location section handler\n */\nimport {\n  getSavedLocations,\n  hasSavedLocation,\n  addSavedLocation,\n  removeSavedLocation,\n} from \"./saved-locations.js\";\n\nclass SavedLocationsSection extends HTMLElement {\n  constructor() {\n    super();\n\n    this.displayClass = \"\";\n    this.hideClass = \"display-none\";\n    this.buttonItemIdPrefix = \"saved-locations-section-btn-\";\n    this.ariaCheckedAttribute = \"aria-checked\";\n\n    this.savedLocations = {};\n\n    this.sectionType = this.dataset?.type ?? \"front\";\n    this.sectionCols = this.dataset?.columns ?? \"true\";\n    this.sectionEl = this.querySelector(\n      `#saved-locations-section-${this.sectionType}`,\n    );\n    this.templateLi = this.querySelector(\n      `#saved-locations-section-${this.sectionType}-li`,\n    );\n\n    this.bindEventListeners = this.bindEventListeners.bind(this);\n    this.unbindEventlisteners = this.unbindEventlisteners.bind(this);\n\n    this.initSection = this.initSection.bind(this);\n    this.hideList = this.hideList.bind(this);\n    this.showList = this.showList.bind(this);\n\n    this.addListButtonEvents = this.addListButtonEvents.bind(this);\n    this.createList = this.createList.bind(this);\n    this.createListItem = this.createListItem.bind(this);\n    this.getListColumnClass = this.getListColumnClassList.bind(this);\n\n    this.onListButtonClick = this.onListButtonClick.bind(this);\n    this.onSavedLocationsButtonAdd = this.onSavedLocationsButtonAdd.bind(this);\n    this.onSavedLocationsButtonRemove =\n      this.onSavedLocationsButtonRemove.bind(this);\n    this.onSectionLocationAdd = this.onSectionLocationAdd.bind(this);\n    this.onSectionLocationRemove = this.onSectionLocationRemove.bind(this);\n  }\n\n  connectedCallback() {\n    this.bindEventListeners();\n    this.initSection();\n  }\n\n  disconnectedCallback() {\n    this.unbindEventlisteners();\n  }\n\n  bindEventListeners() {\n    window.addEventListener(\n      \"wx-saved-locations:button-add\",\n      this.onSavedLocationsButtonAdd,\n    );\n    window.addEventListener(\n      \"wx-saved-locations:button-remove\",\n      this.onSavedLocationsButtonRemove,\n    );\n    window.addEventListener(\n      \"wx-saved-locations:section-add\",\n      this.onSectionLocationAdd,\n    );\n    window.addEventListener(\n      \"wx-saved-locations:section-remove\",\n      this.onSectionLocationRemove,\n    );\n  }\n  unbindEventlisteners() {\n    window.removeEventListener(\n      \"wx-saved-locations:button-add\",\n      this.onSavedLocationsButtonAdd,\n    );\n    window.removeEventListener(\n      \"wx-saved-locations:button-remove\",\n      this.onSavedLocationsButtonRemove,\n    );\n    window.removeEventListener(\n      \"wx-saved-locations:section-add\",\n      this.onSectionLocationAdd,\n    );\n    window.removeEventListener(\n      \"wx-saved-locations:section-remove\",\n      this.onSectionLocationRemove,\n    );\n  }\n\n  initSection() {\n    const currentLocations = getSavedLocations();\n    if (currentLocations?.length) {\n      this.createList(currentLocations);\n      this.showList();\n    } else {\n      this.hideList();\n    }\n  }\n\n  hideList() {\n    this.sectionEl?.classList?.add(this.hideClass);\n  }\n\n  showList() {\n    this.sectionEl?.classList?.remove(this.hideClass);\n  }\n\n  cleanString(str) {\n    return str?.trim()?.replace(/\\W/g, \"\")?.toLowerCase();\n  }\n\n  createList(locations) {\n    const listUl = this.querySelector(\"ul\");\n    const listColumnClass = this.getListColumnClassList(locations.length);\n    if (listColumnClass?.length) listUl.classList.add(...listColumnClass);\n\n    const newElems = [];\n\n    for (let index = 0; index < locations.length; index++) {\n      const { text, url } = locations[index];\n      const element = this.createListItem(text, url);\n      newElems.push(element);\n    }\n    listUl.replaceChildren();\n    listUl.append(...newElems);\n    this.addListButtonEvents();\n  }\n\n  createListItem(text, url) {\n    const cleanedText = this.cleanString(text);\n    this.savedLocations[text] = true;\n\n    // Clone the template\n    const templateLi = this.templateLi;\n    const clonedLi = document.importNode(templateLi.content, true);\n\n    // Update the template\n    const liButton = clonedLi.querySelector(\"button\");\n    liButton.id = `${liButton.id}${cleanedText}`;\n    liButton.setAttribute(\"data-loctext\", text);\n    liButton.setAttribute(\"data-locurl\", url);\n    liButton.setAttribute(\"aria-label\", `Saved location ${text}`);\n\n    const liAnchor = clonedLi.querySelector(\"a\");\n    const anchorId = `saved-locations-section-label-${cleanedText}`;\n    liAnchor.id = anchorId;\n    liAnchor.setAttribute(\"href\", url);\n    liAnchor.innerText = text;\n\n    return clonedLi;\n  }\n\n  getListColumnClassList(itemLength) {\n    if (this.sectionCols === \"false\") return \"\";\n    const columnBase = \"use-columns\",\n      classRange = [\n        { min: 25, class: \"--x4\" },\n        { min: 17, class: \"--x3\" },\n        { min: 9, class: \"--x2\" },\n      ];\n    let columnPostfix;\n\n    for (let index = 0; index < classRange.length; index++) {\n      if (itemLength >= classRange[index].min) {\n        columnPostfix = classRange[index].class;\n        break;\n      }\n    }\n\n    return columnPostfix ? [columnBase, `${columnBase}${columnPostfix}`] : [];\n  }\n\n  addListButtonEvents() {\n    const buttonElems = this.querySelectorAll(\"button.saved-locations-button\");\n    buttonElems.forEach((btn) => {\n      btn.addEventListener(\"click\", this.onListButtonClick);\n    });\n  }\n\n  onListButtonClick(e) {\n    const currentTarget = e.currentTarget;\n    const currentLoc = currentTarget.dataset.loctext;\n    const currentUrl = currentTarget.dataset.locurl;\n    if (this.savedLocations[currentLoc] === true) {\n      currentTarget.setAttribute(this.ariaCheckedAttribute, false);\n      this.savedLocations[currentLoc] = false;\n      removeSavedLocation(currentLoc);\n      window.dispatchEvent(\n        new CustomEvent(\"wx-saved-locations:section-remove\", {\n          detail: {\n            text: currentLoc,\n            url: currentUrl,\n            caller: this.sectionType,\n          },\n        }),\n      );\n    } else {\n      currentTarget.setAttribute(this.ariaCheckedAttribute, true);\n      this.savedLocations[currentLoc] = true;\n      addSavedLocation({ text: currentLoc, url: currentTarget.dataset.locurl });\n      window.dispatchEvent(\n        new CustomEvent(\"wx-saved-locations:section-add\", {\n          detail: {\n            text: currentLoc,\n            url: currentUrl,\n            caller: this.sectionType,\n          },\n        }),\n      );\n    }\n  }\n\n  onSavedLocationsButtonAdd(e) {\n    // If already in list, set the button to saved, otherwise add to the list\n    const detail = e.detail ?? {};\n    const addLocation = detail?.text ?? \"\";\n    if (addLocation in this.savedLocations) {\n      if (this.savedLocations[addLocation] === false) {\n        // Get the button\n        const buttonId = `${this.buttonItemIdPrefix}${this.cleanString(addLocation)}`;\n        const buttonElem = this.querySelector(`#${buttonId}`);\n        buttonElem.setAttribute(this.ariaCheckedAttribute, true);\n        this.savedLocations[addLocation] = true;\n      }\n    } else {\n      // Find where to insert new node\n      const currentSavedLocations = getSavedLocations();\n      const currentList = this.querySelectorAll(\"li\");\n      const currentListUl = this.querySelector(\"ul\");\n\n      const currentLocationIndex = currentSavedLocations.findIndex((loc) => {\n        return addLocation === loc.text;\n      });\n\n      if (currentLocationIndex !== -1) {\n        // Gather previous list's column class and get new class\n        const currentColumnClass = this.getListColumnClassList(\n          currentList.length,\n        );\n        const newColumnClass = this.getListColumnClassList(\n          currentList.length + 1,\n        );\n\n        // Create new DOM element\n        const currentLocationItem = currentSavedLocations[currentLocationIndex];\n        const newListItem = this.createListItem(\n          currentLocationItem.text,\n          currentLocationItem.url,\n        );\n\n        // Attach event listener to button\n        const newListButton = newListItem.querySelector(\n          \"button.saved-locations-button\",\n        );\n        newListButton.addEventListener(\"click\", this.onListButtonClick);\n\n        // Insert into the list\n        if (currentList?.length === 0) {\n          currentListUl.append(newListItem);\n        } else if (currentLocationIndex === 0) {\n          currentList[0].before(newListItem);\n        } else {\n          currentList[currentLocationIndex - 1].after(newListItem);\n        }\n        // Update column class\n        if (currentColumnClass?.length)\n          currentListUl.classList.remove(...currentColumnClass);\n        if (newColumnClass?.length)\n          currentListUl.classList.add(...newColumnClass);\n\n        // Update local tracking\n        this.savedLocations[addLocation] = true;\n\n        // If previously hidden, now show\n        if (currentList?.length === 0) {\n          this.showList();\n        }\n      }\n    }\n  }\n\n  onSavedLocationsButtonRemove(e) {\n    // Disable the necessary button but don't remove from the list yet\n    const detail = e.detail ?? {};\n\n    const addLocation = detail?.text ?? \"\";\n    if (addLocation in this.savedLocations) {\n      if (this.savedLocations[addLocation] === true) {\n        // Get the button and disable\n        const buttonId = `${this.buttonItemIdPrefix}${this.cleanString(addLocation)}`;\n        const buttonElem = this.querySelector(`#${buttonId}`);\n        buttonElem.setAttribute(this.ariaCheckedAttribute, false);\n        this.savedLocations[addLocation] = false;\n      }\n    }\n  }\n\n  onSectionLocationAdd(e) {\n    // Another section has set item to saved, now update this list also\n    const detail = e.detail ?? {};\n    const caller = detail?.caller;\n    if (caller === this.sectionType) return;\n\n    const addLocation = detail?.text ?? \"\";\n\n    if (addLocation in this.savedLocations) {\n      if (this.savedLocations[addLocation] === false) {\n        // Get the button\n        const buttonId = `${this.buttonItemIdPrefix}${this.cleanString(addLocation)}`;\n        const buttonElem = this.querySelector(`#${buttonId}`);\n        buttonElem.setAttribute(this.ariaCheckedAttribute, true);\n        this.savedLocations[addLocation] = true;\n      }\n    }\n  }\n\n  onSectionLocationRemove(e) {\n    // Another section has set item to unsaved, now update this list also\n    const detail = e.detail ?? {};\n    const caller = detail?.caller;\n    if (caller === this.sectionType) return;\n\n    const removeLocation = detail?.text ?? \"\";\n\n    if (removeLocation in this.savedLocations) {\n      if (this.savedLocations[removeLocation] === true) {\n        // Get the button and disable\n        const buttonId = `${this.buttonItemIdPrefix}${this.cleanString(removeLocation)}`;\n        const buttonElem = this.querySelector(`#${buttonId}`);\n        buttonElem.setAttribute(this.ariaCheckedAttribute, false);\n        this.savedLocations[removeLocation] = false;\n      }\n    }\n  }\n}\n\nif (!window.customElements.get(\"wx-saved-locations-section\")) {\n  window.customElements.define(\n    \"wx-saved-locations-section\",\n    SavedLocationsSection,\n  );\n}\n", "/**\n * Pull the application ID from a specific meta tag, if the tag is there.\n * If it is not present, the given environment is not set up for using RUM.\n */\nconst getRUMApplicationId = () => {\n  const tag = document.querySelector(`meta[data-name=\"aws-rum-app-id\"]`);\n  if (!tag || !tag.getAttribute(\"content\")) {\n    console.warn(`No valid RUM application id found in markup.`);\n    return null;\n  }\n  return tag.getAttribute(\"content\");\n};\n\n/**\n * General configuration for our environment(s)\n */\nconst config = {\n  sessionSampleRate: 1.0,\n  identityPoolId: \"us-east-1:d53843c8-350a-4c14-a929-8c0b2844cf62\",\n  endpoint: \"https://dataplane.rum.us-east-1.amazonaws.com\",\n  telemetries: [\"performance\", \"errors\", \"http\"],\n  allowCookies: true,\n  enableXRay: false,\n  signing: true, // If you have a public resource policy and wish to send unsigned requests please set this to false\n  disableAutoPageView: true,\n  customEvents: { enabled: true },\n};\n\n/**\n * Extracted version of the anonymous function in snippet used for creating\n * the RUM client and attaching it to the window as a global.\n */\nconst createAwsRumClient = (name, id, version, region, scriptSrc, config) => {\n  window.AwsRumClient = {\n    q: [],\n    n: name,\n    i: id,\n    v: version,\n    r: region,\n    c: config,\n  };\n\n  window[name] = function (config, p) {\n    window.AwsRumClient.q.push({ c: config, p });\n  };\n\n  const scriptTag = document.createElement(\"script\");\n  scriptTag.async = true;\n  scriptTag.src = scriptSrc;\n  document.head.insertBefore(\n    scriptTag,\n    document.getElementsByTagName(\"script\")[0],\n  );\n};\n\n/**\n * Helper function for determining page groups based on the\n * provided path. Used for giving stable labels to different kinds\n * of URLs.\n */\nconst pageGroups = (path) => {\n  const match = path.match(\n    /^\\/(forecast\\/county|forecast\\/state|cms|forecast\\/point|place)/,\n  );\n  if (!match) {\n    // this pathname is not part of a RUM page group\n    return null;\n  }\n  const what = match[1];\n  // rename endpoints for clarity on the RUM side\n  switch (what) {\n    case \"forecast/point\":\n      return \"forecast\";\n    case \"forecast/county\":\n      return \"county\";\n    case \"forecast/state\":\n      return \"state\";\n    default:\n      return what;\n  }\n};\n\nconst isUsingHTMX = () => {\n  // We determine if we are using HTMX by checking that the\n  // HTMX script element is on the page\n  const script = document.querySelector(`script[src*=\"point-htmx\"]`);\n  if (script) {\n    return true;\n  }\n  return false;\n};\n\nconst getPointForecastPageName = (path) => {\n  const match = path.match(\n    /^\\/forecast\\/point\\/[0-9-.]+\\/[0-9-.]+\\/(alerts|analysis|7-day|today|maps)/,\n  );\n  if (!match) {\n    return null;\n  }\n  return match[1];\n};\n\n/**\n * Sets up the various page views and custom events\n * that we want to record.\n * This function should be run after the RUM client is\n * successfully initialized, as it expects there to be a\n * global (window) function named 'cwr'\n */\nconst setupRecording = () => {\n  // Add event listeners for TabbedNavigator interactions.\n  // If we are using HTMX, we will also want to add listeners\n  // for when the tab content loads\n\n  // When a user switches to another tab\n  // in any TabbedNavigator\n  document.addEventListener(\"wx:tab-switched\", (event) => {\n    const rumEventData = {\n      path: window.location.pathname,\n      isPointPage: !!window.location.pathname.match(/\\/forecast\\/point/),\n      usingHTMX: isUsingHTMX(),\n      tabId: event.detail.tabId,\n    };\n    window.cwr(\"recordEvent\", { type: \"tabbed_nav_click\", data: rumEventData });\n  });\n\n  // When tab contents have loaded behind the scenes\n  // via HTMX-like functionality\n  document.addEventListener(\"wx:tab-content-loaded\", (event) => {\n    const rumEventData = {\n      path: window.location.pathname,\n      isPointPage: !!window.location.pathname.match(/\\/forecast\\/point/),\n      usingHTMX: isUsingHTMX(),\n      tabId: event.detail.tabId,\n    };\n    window.cwr(\"recordEvent\", {\n      type: \"tab_content_loaded\",\n      data: rumEventData,\n    });\n  });\n\n  // When there was an error loading tab contents in the background\n  // using HTMX like functionality\n  document.addEventListener(\"wx:tab-content-error\", (event) => {\n    const rumEventData = {\n      path: window.location.pathname,\n      isPointPage: !!window.location.pathname.match(/\\/forecast\\/point/),\n      usingHTMX: isUsingHTMX(),\n      tabId: event.detail.tabId,\n      errorCode: event.detail.status,\n    };\n    window.cwr(\"recordEvent\", {\n      type: \"tab_content_error\",\n      data: rumEventData,\n    });\n  });\n\n  const pathname = window.location.pathname;\n  const pageTags = [];\n\n  // Get the initial \"page name\" tag.\n  // This will be the type of page, ie\n  // 'forecast', 'county', 'state' or the literal\n  // url in all other cases\n  const pageTypeTag = pageGroups(pathname);\n  if (pageTypeTag) {\n    pageTags.push(pageTypeTag);\n  }\n\n  // Next, check to see if this is a point forecast page or\n  // not. If so, add the 'point-forecast' tag, as well as the\n  // specific tab page name tag for point forecasts\n  const pointForecastTabPageName = getPointForecastPageName(pathname);\n  if (pointForecastTabPageName) {\n    pageTags.push(\"point-forecast\", pointForecastTabPageName);\n  }\n\n  // If we are in 'HTMX' mode, lets add that as a tag\n  // as well\n  if (isUsingHTMX()) {\n    pageTags.push(\"using-htmx\");\n  }\n\n  // Finally, record the pageView\n  if (pageTags.length) {\n    window.cwr(\"recordPageView\", { pageId: pathname, pageTags });\n  } else {\n    window.cwr(\"recordPageView\", { pageId: pathname });\n  }\n};\n\n/**\n * Initialize the RUM client if there is a valid application id,\n * then set up the kinds of page views and custom events\n * we want to record.\n * Note that an invalid or missing application id will return early\n */\n(function () {\n  // If there is not a valid application id, immediately\n  // return to prevent initialization of RUM.\n  const APPLICATION_ID = getRUMApplicationId();\n  if (!APPLICATION_ID) {\n    return;\n  }\n  const APPLICATION_VERSION = \"1.0.0\";\n  const APPLICATION_REGION = \"us-east-1\";\n\n  // Initialize the RUM client on the window\n  createAwsRumClient(\n    \"cwr\",\n    APPLICATION_ID,\n    APPLICATION_VERSION,\n    APPLICATION_REGION,\n    \"https://client.rum.us-east-1.amazonaws.com/1.x/cwr.js\",\n    config,\n  );\n\n  // Set up the page views and custom events for recording\n  setupRecording();\n})();\n", "import Timer from \"./timer.js\";\n\n// Store a reference to the original fetch function\nwindow._fetch = window.fetch;\n\nconst replaceFetch = () => {\n  const banner = document.querySelector(\"#wx-offline-banner__container\");\n  const template = document.querySelector(\"#wx-offline-banner__template\");\n  const importantHosts = JSON.parse(\n    document.getElementById(\"third-party-site-list\").textContent,\n  );\n  importantHosts.push(window.location.host);\n  const maxDelay = 1800000; // 30 minutes\n\n  const debouncer = {\n    banner: new Timer(),\n    ariaLive: new Timer(),\n  };\n  const metronome = {\n    ping: new Timer(),\n  };\n\n  const hideOfflineBanner = () => {\n    try {\n      banner.innerHTML = \"\";\n      metronome.ping.stop();\n      const text = gettext(\"js.offline-banner.aria.you-are-back-online.01\");\n      window.dispatchEvent(\n        new CustomEvent(\"wx-announce\", { detail: { text } }),\n      );\n    } catch (_) {\n      /* do nothing */\n    }\n  };\n\n  const checkOffline = () => {\n    if (!navigator.onLine) {\n      metronome.ping.reset();\n    } else {\n      window._fetch\n        .apply(this, [\"/health/\"])\n        .then((_) => hideOfflineBanner())\n        .catch((_) => metronome.ping.reset());\n    }\n  };\n\n  const showOfflineBanner = () => {\n    try {\n      if (!banner.children.length) {\n        debouncer.ariaLive.start(() => {\n          banner.appendChild(template.content.cloneNode(true));\n          banner.scrollIntoView();\n        }, 1000);\n      }\n      metronome.ping.start(checkOffline);\n    } catch (_) {\n      /* do nothing */\n    }\n  };\n\n  const wait = (delay) => new Promise((resolve) => setTimeout(resolve, delay));\n\n  /**\n   * This is a wrapper around the original window.fetch, to provide\n   * automatic retry and offline banners.\n   *\n   * By default, it retries 10 times, but you can pass `wxMaxRetries`:\n   *\n   *     fetch(\"url\", {..}, {wxMaxRetries: 5})\n   *\n   * The original fetch is at window._fetch.\n   */\n  window.fetch = (resource, options = {}) => {\n    const maxRetries = options.wxMaxRetries || 10;\n    const tries = options.wxTries || 1;\n    let requestedHost;\n    try {\n      requestedHost = new URL(resource).host;\n    } catch (error) {\n      /* do nothing */\n    }\n\n    if (importantHosts.includes(requestedHost)) {\n      return window._fetch(resource, options).catch((error) => {\n        showOfflineBanner();\n        if (tries <= maxRetries) {\n          options.wxTries = tries + 1;\n          options.wxMaxRetries = maxRetries;\n          const array = new Uint32Array(1);\n          const rand = crypto.getRandomValues(array)[0];\n          const jitter = (rand % 100) + 1;\n          const delay = Math.min(500 * 2 ** tries + jitter, maxDelay);\n          return wait(delay).then(() => window.fetch(resource, options));\n        } else {\n          throw error;\n        }\n      });\n    } else {\n      return window._fetch(resource, options);\n    }\n  };\n};\n\nif (document.readyState === \"loading\") {\n  document.addEventListener(\"DOMContentLoaded\", replaceFetch, {\n    once: true,\n  });\n} else {\n  replaceFetch();\n}\n", "import Timer from \"./timer.js\";\n\nconst debouncer = new Timer();\n/**\n * Cache the text here to compare text between calls.\n *\n * This is needed because some screenreaders will not announce \"repeat\" messages.\n */\nlet text = \"\";\n\n/**\n * Adds a span of screenreader only text to\n * a page-wide aria-live region,\n * which is itself also hidden.\n * The update is on a 1 second delay, which is preferred\n * based on convos with USWDS.\n *\n * To use:\n *   const text = gettext(\"js.<keyFromDjangojs.po>.01\"));\n *   window.dispatchEvent(new CustomEvent(\"wx-announce\", { detail: { text }}));\n */\nconst updateAriaLive = (e) => {\n  const delay = Number.isFinite(e.detail?.delay) ? e.detail?.delay : 1000;\n  // check if this is a repeat message\n  if (text === e.detail?.text) {\n    // if so, append a non-breaking space\n    text += \"\\u00A0\";\n  } else {\n    // otherwise, use the new text\n    text = e.detail?.text;\n  }\n  debouncer.start(() => {\n    const span = document.createElement(\"span\");\n    span.innerText = text;\n    const liveRegion = document.querySelector(\"#sr-only\");\n    liveRegion.innerHTML = \"\";\n    liveRegion.append(span);\n  }, delay);\n};\n\nwindow.addEventListener(\"wx-announce\", updateAriaLive);\n", "import Listbox from \"./listbox.js\";\n\nexport default class FilterableListbox extends Listbox {\n  constructor() {\n    super();\n    this._cachedItems = null;\n\n    // A selector specifying which options should be considered for filtering.\n    // There are cases, such as in grouped options, where were would like\n    // certain options to _never_ be filtered out. This gives us that affordance, via a\n    // special data-filter-ignore attribute\n    this.filterOptionsSelector = `*:not([data-filter-ignore=\"true\"]) > [role=\"option\"]:not([data-filter-ignore=\"true\"])`;\n\n    this.filterText = this.filterText.bind(this);\n    this.clearFilter = this.clearFilter.bind(this);\n    this.getFilterSource = this.getFilterSource.bind(this);\n    this.handleItemsChanges = this.handleItemsChanged.bind(this);\n  }\n\n  /**\n   * Filters the currently displayed options in the listbox\n   * by the given string, selecting only those options whose\n   * textContent is a fuzzy match for the incoming string.\n   * This method relies on the existence of a \"filter source\" element\n   * attached to the component, which can be used for both filtering\n   * and restoring the original contents of the listbox whenever a filter\n   * is cleared.\n   * This method fires the custom event wx:popup-filter\n   * @param String aString - The term to fuzzy filter on\n   */\n  filterText(aString) {\n    // We need to determine if the current inner content of this\n    // component represents a \"master\" list, from which we will filter.\n    // If it does, we need to cache it so that it is always what gets\n    // filtered against, otherwise we would lose information permanently\n    // each filter when swapping out elements.\n    const source = this.getFilterSource();\n    if (aString && aString !== \"\") {\n      const filtered = Array.from(\n        source.querySelectorAll(this.filterOptionsSelector),\n      ).filter((option) => {\n        return !option.textContent\n          .toLowerCase()\n          .includes(aString.toLowerCase());\n      });\n\n      filtered.forEach((option) => option.remove());\n\n      // Next, determine if there are groups whose\n      // options have all been ignored, ie they have none\n      Array.from(source.querySelectorAll(`[role=\"group\"]`)).forEach(\n        (groupElement) => {\n          if (!groupElement.querySelectorAll(`[role=\"option\"]`).length) {\n            groupElement.remove();\n          }\n        },\n      );\n      this.setAttribute(\"filtered\", true);\n    } else {\n      this.removeAttribute(\"filtered\");\n    }\n\n    this.innerHTML = source.innerHTML;\n\n    this.dispatchEvent(\n      new CustomEvent(\"wx:popup-filter\", {\n        bubbles: true,\n        cancelable: true,\n      }),\n    );\n  }\n\n  /**\n   * Clear the filter, and restore the listbox options to\n   * their initial unfiltered/full state.\n   * We first check to see if there is in fact any existing cache\n   * and a corresponding hidden input specifying that the listbox\n   * is currently being filtered.\n   * If present, then we restore from the cached filter source.\n   */\n  clearFilter() {\n    const inputSelector = `input[type=\"hidden\"][name=\"filtered\"][value=\"true\"]`;\n    if (this._cachedItems && this._cachedItems.querySelector(inputSelector)) {\n      this.innerHTML = this.getFilterSource().innerHTML;\n    }\n    this.removeAttribute(\"filtered\");\n  }\n\n  /**\n   * Get the full list of filterable items as HTML from a cache.\n   *\n   * This also creates the cache if it does not exist. In order to prevent\n   * overwriting the cache with filtered items, we use a hidden input,\n   * added to the root of the cache, as a flag.\n   *\n   * Returns a cloned element or document fragment corresponding\n   * to the original, unfiltered content of the listbox. Useful for filtering\n   * the options displayed in the listbox.\n   */\n  getFilterSource() {\n    const inputSelector = `input[type=\"hidden\"][name=\"filtered\"][value=\"true\"]`;\n    if (this._cachedItems && this._cachedItems.querySelector(inputSelector)) {\n      // If we get to this point, that means that the current innerHTML of the\n      // listbox already represents filtered data, and that the _cachedItems\n      // are the source of truth for further filtering\n      return this._cachedItems.cloneNode(true);\n    } else {\n      // Otherwise, we assume that the current innerHTML of the component\n      // is the full (not filtered) source of truth for the list.\n      // We need to add the hidden input to it and then cache the content\n      const temp = document.createElement(\"div\");\n      temp.innerHTML = this.innerHTML;\n      const input = document.createElement(\"input\");\n      input.setAttribute(\"type\", \"hidden\");\n      input.setAttribute(\"name\", \"filtered\");\n      input.setAttribute(\"value\", \"true\");\n      temp.append(input);\n      this._cachedItems = temp;\n      return this._cachedItems.cloneNode(true);\n    }\n  }\n\n  /**\n   * We only want to re-initialize elements if the listbox\n   * is currently being filtered (because the options will\n   * be newly cloned elements from the filter source)\n   */\n  handleItemsChanged(event) {\n    if (!this.isFiltered) {\n      super.handleItemsChanged(event);\n    }\n  }\n\n  /**\n   * When calling selectItem on filtered options,\n   * we also need to update the corresponding option element\n   * that lives in the cached filter source. If we don't do this,\n   * selection will disappear on further filtering, even if the\n   * aforementioned selected item is not filtered out.\n   */\n  selectItem(element) {\n    if (!element) {\n      return super.selectItem(element);\n    }\n    if (this._cachedItems) {\n      const selectionIndex = element.dataset.optionIndex;\n      Array.from(this._cachedItems.querySelectorAll(`[role=\"option\"]`)).forEach(\n        (option) => {\n          if (\n            option.matches(\n              `[role=\"option\"][data-option-index=\"${selectionIndex}\"]`,\n            )\n          ) {\n            option.setAttribute(\"aria-selected\", true);\n          } else {\n            option.removeAttribute(\"aria-selected\");\n          }\n        },\n      );\n    }\n\n    super.selectItem(element);\n    this.clearFilter();\n  }\n\n  get isFiltered() {\n    return this.getAttribute(\"filtered\") === \"true\";\n  }\n}\n\nif (!window.customElements.get(\"wx-filterable-listbox\")) {\n  window.customElements.define(\"wx-filterable-listbox\", FilterableListbox);\n}\n", "/**\n * Generic WCAG Tabs component\n * ------------------------------------------\n * This is a progressively enhanced component.\n * tab, tablist, and tabpanel elements are expected\n * to have the correct `role` attributes and other\n * aria references.\n * See\n * https://www.w3.org/WAI/ARIA/apg/patterns/tabs/\n */\nclass Tabs extends HTMLElement {\n  constructor() {\n    super();\n\n    // Bound methods\n    this.handleTabClick = this.handleTabClick.bind(this);\n    this.handleKeyDown = this.handleKeyDown.bind(this);\n  }\n\n  connectedCallback() {\n    Array.from(this.querySelectorAll('[role=\"tab\"]')).forEach((tabElement) => {\n      tabElement.addEventListener(\"click\", this.handleTabClick);\n    });\n    this.addEventListener(\"keydown\", this.handleKeyDown);\n  }\n\n  disconnectedCallback() {\n    this.removeEventListener(\"keydown\", this.handleKeyDown);\n    Array.from(this.querySelectorAll('[role=\"tab\"]')).forEach((tabElement) => {\n      tabElement.removeEventListener(\"click\", this.handleTabClick);\n    });\n  }\n\n  /**\n   * The click handler should update the tab's\n   * aria-selected attribute, and also update the\n   * data-tabpanel-selected attribute on its corresponding\n   * tabpanel.\n   * Any hiding/showing of tabpanel content should be\n   * handled by implementor's CSS\n   */\n  handleTabClick(event) {\n    const tab = event.target.closest('[role=\"tab\"]');\n    const panelId = tab.getAttribute(\"aria-controls\");\n    const panel = document.getElementById(panelId);\n    if (panel) {\n      this.tabs.forEach((tabElement) => {\n        tabElement.setAttribute(\"aria-selected\", false);\n      });\n      tab.setAttribute(\"aria-selected\", true);\n      this.tabpanels.forEach((tabpanelElement) => {\n        tabpanelElement.setAttribute(\"data-tabpanel-selected\", false);\n      });\n      panel.setAttribute(\"data-tabpanel-selected\", true);\n      panel.setAttribute(\"aria-labelledby\", tab.id);\n      this.setAttribute(\"data-selected\", panelId);\n    }\n\n    window.dispatchEvent(new CustomEvent(\"wx-tab-focused\", { detail: tab }));\n  }\n\n  /**\n   * Binds key handling events as specified in\n   * the WCAG recommendations\n   */\n  handleKeyDown(event) {\n    const currentFocus = this.querySelector(\n      '[role=\"tab\"]:focus,[role=\"tab\"]:focus-within',\n    );\n    const firstItemInFocus = currentFocus.matches(\n      '[role=\"tab\"]:first-child:focus, [role=\"tab\"]:first-child:focus-within',\n    );\n    const lastItemInFocus = currentFocus.matches(\n      '[role=\"tab\"]:last-child:focus, [role=\"tab\"]:last-child:focus-within',\n    );\n    let handled = false;\n    if (event.key === \"ArrowLeft\") {\n      if (firstItemInFocus) {\n        this.focusTab(this.querySelector('[role=\"tab\"]:last-child'));\n      } else {\n        this.focusTab(currentFocus.previousElementSibling);\n      }\n      handled = true;\n    } else if (event.key === \"ArrowRight\") {\n      if (lastItemInFocus) {\n        this.focusTab(this.querySelector('[role=\"tab\"]:first-child'));\n      } else {\n        this.focusTab(currentFocus.nextElementSibling);\n      }\n      handled = true;\n    } else if (event.key === \"Space\" || event.key === \"Enter\") {\n      currentFocus.click();\n      handled = true;\n    } else if (event.key === \"Home\") {\n      this.focusTab(this.querySelector('[role=\"tab\"]:first-child'));\n      handled = true;\n    } else if (event.key === \"End\") {\n      this.focusTab(this.querySelector('[role=\"tab\"]:last-child'));\n      handled = true;\n    }\n\n    if (handled) {\n      event.stopPropagation();\n      event.preventDefault();\n    }\n  }\n\n  focusTab(anElement) {\n    // It is not required that the element with the role tab\n    // be a focusable element. In such cases, we need to\n    // check its children for elements that can receive focus.\n    // We do this in the simplest possible way, limiting ourselves\n    // to a, button, or any element with a tabindex\n    const matchString = \"a, button, [tabindex]\";\n    if (anElement.matches(matchString)) {\n      anElement.focus();\n    } else {\n      const childFocusElement = anElement.querySelector(matchString);\n      if (childFocusElement) {\n        childFocusElement.focus();\n      }\n    }\n  }\n\n  get tabs() {\n    return Array.from(this.querySelectorAll('[role=\"tab\"]'));\n  }\n\n  get tabpanels() {\n    return this.tabs.map((tabElement) => {\n      const panelId = tabElement.getAttribute(\"aria-controls\");\n      return document.getElementById(panelId);\n    });\n  }\n}\n\nif (!window.customElements.get(\"wx-tabs\")) {\n  window.customElements.define(\"wx-tabs\", Tabs);\n}\n", "const getRelevantDOMNodes = () => ({\n  alerts: [...document.querySelectorAll(\"wx-alerts > div[data-alert]\")],\n  legends: [\n    ...document.querySelectorAll(\n      \".wx_alert_map_legend > [data-alert-map-legend-level]\",\n    ),\n  ],\n  emptyState: [...document.querySelectorAll(\"[data-no-alerts-day]\")],\n});\n\nconst all = () => {\n  const { alerts, emptyState, legends } = getRelevantDOMNodes();\n\n  // Display all alerts\n  alerts.forEach((node) => {\n    node.classList.remove(\"display-none\");\n  });\n\n  // Display all relevant alert map legends\n  legends.forEach((node) => node.classList.remove(\"display-none\"));\n\n  // Hide all empty state text except for day 0.\n  emptyState.forEach((node) => {\n    if (node.dataset.noAlertsDay === \"0\") {\n      node.classList.remove(\"display-none\");\n    } else {\n      node.classList.add(\"display-none\");\n    }\n  });\n};\n\nconst specificDay = (day, dayLevels) => {\n  const { alerts, emptyState, legends } = getRelevantDOMNodes();\n\n  // Start by hiding everything\n  alerts.forEach((node) => {\n    node.classList.add(\"display-none\");\n  });\n  legends.forEach((node) => node.classList.add(\"display-none\"));\n\n  // And then un-hide the relevant alerts.\n  const dayAlerts = [...document.querySelectorAll(`[data-alert-day-${day}]`)];\n  dayAlerts.forEach((node) => node.classList.remove(\"display-none\"));\n\n  // As well as alert map legends that are appropriate for the day.\n  legends.forEach((node) => {\n    if (dayLevels.includes(node.dataset.alertMapLegendLevel)) {\n      node.classList.remove(\"display-none\");\n    }\n  });\n\n  // Hide all empty state text except the relevant day.\n  emptyState.forEach((node) => {\n    if (node.dataset.noAlertsDay === day) {\n      node.classList.remove(\"display-none\");\n    } else {\n      node.classList.add(\"display-none\");\n    }\n  });\n};\n\nwindow.addEventListener(\"wx-tab-focused\", (e) => {\n  const day = e.detail?.dataset?.alertDay;\n\n  // \"All\" is a special case.\n  if (day === \"all\") {\n    all();\n  }\n  // Otherwise, we just want to make sure we have a value. If we don't, then\n  // we didn't get here from focusing a county alert tab, and we don't need\n  // to do anything else. Huzzah!\n  else if (day) {\n    const dayLevels =\n      e.detail?.dataset?.alertLevels\n        ?.split(\" \")\n        .filter((i) => i.trim().length > 0) ?? [];\n\n    specificDay(day, dayLevels);\n  }\n});\n", "/**\n * State Index Filter component\n * ------------------------------------------------\n * This component handles the events from a text input\n * field. It uses a fuzzy match to hide or show state links\n * from a list of state names.\n * Unlike its more complex County variant, it has no\n * in memory DOM and purely hides/shows the\n * constituent links using the display-none class.\n */\nclass StateIndexFilter extends HTMLElement {\n  constructor() {\n    super();\n\n    // Bound methods\n    this.handleInput = this.handleInput.bind(this);\n  }\n\n  connectedCallback() {\n    this.input = document.getElementById(\"state-filter-input\");\n    this.list = document.getElementById(\"state-index-list\");\n\n    this.addEventListener(\"input\", this.handleInput);\n  }\n\n  disconnectedCallback() {\n    if (this.input) {\n      this.input.removeEventListener(\"input\", this.handleInput);\n    }\n  }\n\n  handleInput(event) {\n    if (!this.input.value || this.input.value === \"\") {\n      return this.list.querySelectorAll(\"li\").forEach((li) => {\n        li.classList.remove(\"display-none\");\n      });\n    }\n\n    const term = this.input.value.toLowerCase();\n    return this.list.querySelectorAll(\"li\").forEach((element) => {\n      if (element.textContent.toLowerCase().includes(term)) {\n        element.classList.remove(\"display-none\");\n      } else {\n        element.classList.add(\"display-none\");\n      }\n    });\n  }\n}\n\nwindow.customElements.define(\"wx-state-index-filter\", StateIndexFilter);\n"],
  "mappings": "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",
  "names": ["Timer", "callback", "delay", "TabbedNavigator", "pointTablist", "tab", "alertAnchor", "button", "tablist", "maxScroll", "hash", "matchedTabButton", "childElement", "tabContainer", "tabId", "element", "tabButton", "event", "currentPath", "matchingTab", "anchorEl", "accordionEl", "accordionElement", "on", "content", "currentElement", "isFirst", "isLast", "accordionTop", "buttonAreaHeight", "scrollY", "setupSiteSearchMenuButton", "siteSubmenuElement", "button", "siteSearchSubmenu", "mobileButton", "tabletButton", "footerRegion", "prefersReducedMotion", "scrollBracket", "bottomY", "hideThreshold", "minScrollThreshold", "hideThreshold", "minScrollThreshold", "scrollBracket", "bottomY", "mobileButton", "tabletButton", "scrollUp", "prefersReducedMotion", "Listbox", "e", "selected", "first", "event", "closestOption", "handler", "host", "option", "idx", "element", "fireEvent", "selectedEl", "current", "options", "currentIndex", "prev", "firstOption", "lastOption", "next", "navigateToElement", "combobox", "popup", "selected", "targetUrl", "sections", "navLinks", "observerOptions", "observerCallback", "entries", "entry", "id", "link", "activeLink", "observer", "section", "hideNavigationLoader", "loader", "showNavigationLoader", "event", "loaders", "activeNav", "text", "goToLocationPage", "latitude", "longitude", "form", "removeBrowserLocationButtons", "buttons", "button", "sibling", "shouldPrompt", "status", "buttonHandler", "e", "proceed", "text", "lat", "long", "code", "message", "alertText", "comboTemplate", "Combobox", "target", "event", "name", "assigned", "value", "id", "element", "popupIsOpen", "handler", "clearButton", "oldVal", "newVal", "RECENT_LOC_STORAGE", "getRecentLocations", "existing", "parsed", "url", "updated", "rest", "addRecentLocation", "obj", "sliced", "debouncer", "Timer", "getRedirectUrlFromAddressCandidate", "addressCandidate", "type", "lat", "lon", "abbr", "typeLowercase", "makeListItemFromResultItem", "setSize", "describedby", "suggestion", "idx", "item", "makeListFromResult", "resultListElement", "ariaDescEl", "suggestions", "newItems", "LocationListbox", "Listbox", "addRecentLocation", "element", "selectItemPromise", "resolve", "form", "geoData", "formUrl", "event", "key", "filterTerm", "savedSearchesGroup", "savedSearchesLabel", "saved", "getRecentLocations", "match", "option", "text", "response", "numResults", "translation", "transWithCount", "data", "headerElement", "magicKey", "result", "cached", "url", "results", "firstCandidate", "x", "y", "SAVED_LOC_STORAGE", "TAB_REGEX", "normalizeLocationUrl", "url", "normalizeSavedLocationStorage", "storage", "text", "location", "getParsedSavedLocationStorage", "SAVED_LOC_STORAGE", "parsedStorage", "setSavedLocationStorage", "newStorage", "getSavedLocations", "current", "addSavedLocation", "obj", "textLower", "existing", "getParsedSavedLocationStorage", "hashed", "sorted", "largerElemIndex", "item", "setSavedLocationStorage", "removeSavedLocation", "loc", "locLower", "existingSorted", "existingHashed", "existingElemIdx", "SavedLocationsSection", "currentLocations", "getSavedLocations", "str", "locations", "listUl", "listColumnClass", "newElems", "index", "text", "url", "element", "cleanedText", "templateLi", "clonedLi", "liButton", "liAnchor", "anchorId", "itemLength", "columnBase", "classRange", "columnPostfix", "btn", "e", "currentTarget", "currentLoc", "currentUrl", "removeSavedLocation", "addSavedLocation", "addLocation", "buttonId", "currentSavedLocations", "currentList", "currentListUl", "currentLocationIndex", "loc", "currentColumnClass", "newColumnClass", "currentLocationItem", "newListItem", "detail", "removeLocation", "getRUMApplicationId", "tag", "config", "createAwsRumClient", "name", "id", "version", "region", "scriptSrc", "p", "scriptTag", "pageGroups", "path", "match", "what", "isUsingHTMX", "getPointForecastPageName", "setupRecording", "event", "rumEventData", "pathname", "pageTags", "pageTypeTag", "pointForecastTabPageName", "APPLICATION_ID", "replaceFetch", "banner", "template", "importantHosts", "maxDelay", "debouncer", "Timer", "metronome", "hideOfflineBanner", "text", "checkOffline", "_", "showOfflineBanner", "wait", "delay", "resolve", "resource", "options", "maxRetries", "tries", "requestedHost", "error", "array", "jitter", "debouncer", "Timer", "text", "updateAriaLive", "e", "delay", "span", "liveRegion", "FilterableListbox", "Listbox", "aString", "source", "option", "groupElement", "temp", "input", "event", "element", "selectionIndex", "Tabs", "tabElement", "event", "tab", "panelId", "panel", "tabpanelElement", "currentFocus", "firstItemInFocus", "lastItemInFocus", "handled", "anElement", "matchString", "childFocusElement", "getRelevantDOMNodes", "all", "alerts", "emptyState", "legends", "node", "specificDay", "day", "dayLevels", "e", "i", "StateIndexFilter", "event", "li", "term", "element"]
}
