{
  "version": 3,
  "sources": ["/cdn/shop/t/6/assets/s-nav-dropdown.js?bust=20147"],
  "sourcesContent": ["/**\n * <s-nav-dropdown> \u2014 header navigation dropdown for a nav item that has a submenu.\n *\n * Each nav item that has children renders a plain link next to a separate toggle\n * button (`[data-nav-disclosure]`). The link goes to the item's page; the button\n * shows/hides the submenu. Keeping them separate means a keyboard or screen-reader\n * user who wants to open the submenu presses the button instead of accidentally\n * following the link.\n *\n * Required child markup:\n *   button[data-nav-disclosure] \u2014 the toggle button. Its `aria-controls` holds the\n *                                 `id` of the submenu it shows/hides; this component\n *                                 keeps its `aria-expanded` in sync with open state.\n *   .nav-dropdown               \u2014 top-level dropdown panel; `id` matches the top-level\n *                                 button's `aria-controls`.\n *   .nav-dropdown-submenu       \u2014 nested submenu panel; `id` matches its group's button\n *                                 `aria-controls`.\n *\n * How a submenu opens:\n *   - Mouse: hovering the item shows the submenu (handled entirely in CSS via `:hover`).\n *     This component only copies that hover state into `aria-expanded`.\n *   - Keyboard / click: pressing the toggle button sets `data-open` on the item's\n *     container, which the stylesheet uses to show the submenu.\n *   Moving keyboard focus onto an item never opens its submenu on its own \u2014 the button\n *   must be pressed. Escape closes the innermost open submenu and moves focus back to\n *   its button. Moving focus out of the component closes any submenus opened by button.\n */\nclass SNavDropdown extends HTMLElement {\n  #ac;\n  /** @type {Array<{ button: HTMLElement, container: HTMLElement, hovered: boolean, open: boolean }>} */\n  #disclosures = [];\n\n  connectedCallback() {\n    // Reset instance collections to support reconnect (DOM move)\n    this.#disclosures = [];\n    this.#ac = new AbortController();\n    const opts = { signal: this.#ac.signal };\n\n    for (const button of this.querySelectorAll('[data-nav-disclosure]')) {\n      if (!(button instanceof HTMLElement)) continue;\n      const panelId = button.getAttribute('aria-controls');\n      const panel = panelId ? this.querySelector(`[id=\"${panelId}\"]`) : null;\n      if (!panel) continue;\n\n      // Nested disclosures live in a `.nav-dropdown-group`; the level-1 disclosure\n      // toggles the whole component, so its container is the element itself.\n      const container = button.closest('.nav-dropdown-group') ?? this;\n      const disclosure = { button, container, hovered: false, open: false };\n      this.#disclosures.push(disclosure);\n\n      button.setAttribute('aria-expanded', 'false');\n      button.addEventListener('click', () => this.#toggle(disclosure), opts);\n      container.addEventListener('mouseenter', () => this.#setHovered(disclosure, true), opts);\n      container.addEventListener('mouseleave', () => this.#setHovered(disclosure, false), opts);\n\n      // Match the mobile menu: any title that has options under it (e.g. \"Shop By Shape\",\n      // \"Raw & Specimens\") opens its options on click instead of navigating.\n      {\n        const sibling = button.previousElementSibling;\n        const titleLink = sibling instanceof HTMLAnchorElement ? sibling : null;\n        if (titleLink) {\n          titleLink.setAttribute('aria-controls', panelId);\n          titleLink.setAttribute('role', 'button');\n          titleLink.addEventListener(\n            'click',\n            (event) => {\n              event.preventDefault();\n              this.#toggle(disclosure);\n            },\n            opts\n          );\n        }\n      }\n    }\n\n    // Close open dropdowns when the shopper clicks or taps anywhere outside this menu item\n    // (touch browsers don't always move focus, so focusout alone isn't enough).\n    document.addEventListener(\n      'pointerdown',\n      (event) => {\n        if (event.target instanceof Node && this.contains(event.target)) return;\n        for (const disclosure of this.#disclosures) {\n          if (!disclosure.open) continue;\n          disclosure.open = false;\n          this.#sync(disclosure);\n        }\n      },\n      opts\n    );\n\n    this.addEventListener('keydown', this.#onKeyDown, opts);\n    this.addEventListener('focusout', this.#onFocusOut, opts);\n  }\n\n  disconnectedCallback() {\n    this.#ac?.abort();\n  }\n\n  #toggle(disclosure) {\n    disclosure.open = !disclosure.open;\n    if (disclosure.open) {\n      // Only one column open per level: close sibling groups that aren't ancestors of this one.\n      for (const other of this.#disclosures) {\n        if (other === disclosure || !other.open) continue;\n        if (other.container.contains(disclosure.container)) continue;\n        other.open = false;\n        this.#sync(other);\n      }\n    }\n    this.#sync(disclosure);\n  }\n\n  #setHovered(disclosure, hovered) {\n    disclosure.hovered = hovered;\n    this.#sync(disclosure);\n    // Clear hover suppression when the pointer leaves.\n    if (!hovered) {\n      disclosure.container.removeAttribute('data-suppress-hover');\n    }\n  }\n\n  /**\n   * Reflect the current state onto the DOM. `aria-expanded` tracks whether the panel\n   * is visible (hover or explicit open); `data-open` drives the keyboard/click reveal\n   * that CSS honors alongside `:hover`.\n   */\n  #sync(disclosure) {\n    disclosure.button.setAttribute('aria-expanded', disclosure.open || disclosure.hovered ? 'true' : 'false');\n    disclosure.container.toggleAttribute('data-open', disclosure.open);\n  }\n\n  /**\n   * Escape closes the innermost open panel and returns focus to its button.\n   * If no panels are button-opened but some are hover-revealed, suppress the\n   * hovered panel instead so pointer users can dismiss without moving the mouse.\n   * @param {KeyboardEvent} event\n   */\n  #onKeyDown = (event) => {\n    if (event.key !== 'Escape') return;\n\n    const open = this.#disclosures.filter((disclosure) => disclosure.open);\n    if (open.length > 0) {\n      // Prefer the open panel that currently holds focus, then pick the innermost.\n      const focused = open.filter((disclosure) => disclosure.container.contains(document.activeElement));\n      const candidates = focused.length > 0 ? focused : open;\n      const target = candidates.reduce((innermost, disclosure) =>\n        innermost.container.contains(disclosure.container) ? disclosure : innermost\n      );\n\n      target.open = false;\n      this.#sync(target);\n      target.button.focus();\n      event.stopPropagation();\n      return;\n    }\n\n    // No button-opened panels; check for hover-revealed panels.\n    const hovered = this.#disclosures.filter((disclosure) => disclosure.hovered);\n    if (hovered.length === 0) return;\n\n    // Prefer the hovered panel that currently holds focus, then pick the innermost.\n    const focused = hovered.filter((disclosure) => disclosure.container.contains(document.activeElement));\n    const candidates = focused.length > 0 ? focused : hovered;\n    const target = candidates.reduce((innermost, disclosure) =>\n      innermost.container.contains(disclosure.container) ? disclosure : innermost\n    );\n\n    // Suppress the hover reveal; it will be restored on mouseleave.\n    target.container.setAttribute('data-suppress-hover', '');\n    target.button.focus();\n    event.stopPropagation();\n  };\n\n  /**\n   * Close any button-opened panels once focus leaves the component entirely.\n   * @param {FocusEvent} event\n   */\n  #onFocusOut = (event) => {\n    if (event.relatedTarget instanceof Node && this.contains(event.relatedTarget)) return;\n    for (const disclosure of this.#disclosures) {\n      if (!disclosure.open) continue;\n      disclosure.open = false;\n      this.#sync(disclosure);\n    }\n  };\n}\n\ncustomElements.define('s-nav-dropdown', SNavDropdown);\n"],
  "mappings": "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",
  "names": ["focused", "target"]
}
