{ "version": 3, "sources": ["../../../src/ob-disclosure-nav/index.js"], "sourcesContent": ["let style = document.createElement(\"style\");\nstyle.innerHTML = `\nob-disclosure-nav * ul,\n.ob-disclosure-nav__list {\n background-color: var(--disclosure-nav-bg, #fafafa);\n box-shadow: 0 6px 12px rgba(0,0,0,0.175);\n\n display: block;\n list-style-type: none;\n\n margin: 0;\n max-height: 90vh;\n min-width: 12.5rem;\n overflow-y: auto;\n padding: 0.5em 0;\n\n position: absolute;\n z-index: 1;\n}\n\nob-disclosure-nav ul a,\n.ob-disclosure-nav__link {\n border: 0;\n color: var(--disclosure-nav-item-color, #666);\n display: block;\n margin: 0;\n padding: 1.25em 1em;\n text-decoration: none;\n}\n\nob-disclosure-nav ul a:focus,\n.ob-disclosure-nav__link:focus,\nob-disclosure-nav ul a:hover,\n.ob-disclosure-nav__link:hover {\n background-color: var(--brand-secondary, #666);\n color: var(--brand-secondary-contrast, white);\n}\n\nob-disclosure-nav ul a:focus,\n.ob-disclosure-nav__link:focus {\n position: relative;\n outline: 0.125rem solid rgba(0, 0, 0, 0.5);\n}\n\nob-disclosure-nav button,\n.ob-disclosure-nav__button {\n appearance: none;\n background-color: transparent;\n border: none;\n color: inherit;\n}\n\nob-disclosure-nav button::after,\n.ob-disclosure-nav__button::after {\n display: inline-block;\n content: \"\";\n border-bottom: 0.125rem solid white;\n border-right: 0.125rem solid white;\n height: 0.5em;\n margin-left: 0.75em;\n width: 0.5em;\n transform: rotate(45deg);\n transform-origin: center;\n transition: transform 200ms ease-out;\n}\n\nob-disclosure-nav button[aria-expanded=true]::after,\n.ob-disclosure-nav__button[aria-expanded=true]::after {\n transform: rotate(-135deg);\n}\n\nob-disclosure-nav button:hover,\n.ob-disclosure-nav__button:hover,\nob-disclosure-nav button[aria-expanded=true],\n.ob-disclosure-nav__button[aria-expanded=true] {\n background-color: var(--disclosure-item-hover-bg, #005a9c);\n color: var(--disclosure-item-hover-color, #fff);\n}\n\nob-disclosure-nav button:hover::after,\n.ob-disclosure-nav__button:hover::after,\nob-disclosure-nav button[aria-expanded=true]::after,\n.ob-disclosure-nav__button[aria-expanded=true]::after {\n border-color: #fff;\n color: var(--disclosure-item-hover-color, #fff);\n}\n`;\n\ndocument.head.appendChild(style);\n\nexport default class DisclosureNav extends HTMLElement {\n constructor() {\n super();\n this.triggerNodes = [];\n this.controlledNodes = [];\n this.openIndex = null;\n this.useArrowKeys = true;\n\n let buttons = this.querySelectorAll(\"button[aria-expanded][aria-controls]\");\n\n for (let button of buttons) {\n let menu = button.parentNode.querySelector(\n \".ob-disclosure-nav__list, ul\"\n );\n if (menu) {\n // save ref to button and controlled menu\n this.triggerNodes.push(button);\n this.controlledNodes.push(menu);\n\n // collapse menus\n button.setAttribute(\"aria-expanded\", \"false\");\n this.toggleMenu(menu, false);\n\n // attach event listeners\n menu.addEventListener(\"keydown\", this.handleMenuKeyDown.bind(this));\n button.addEventListener(\"click\", this.handleButtonClick.bind(this));\n button.addEventListener(\"keydown\", this.handleButtonKeyDown.bind(this));\n }\n }\n\n this.addEventListener(\"focusout\", this.handleBlur.bind(this));\n }\n\n toggleMenu(domNode, show) {\n if (domNode) {\n domNode.style.display = show ? \"block\" : \"none\";\n if (show) {\n let clientRect = domNode.getBoundingClientRect();\n let rootClientRect = this.getBoundingClientRect();\n let clientX2 = clientRect.x + clientRect.width;\n let rootX2 = rootClientRect.x + rootClientRect.width;\n if (clientX2 > rootX2) {\n domNode.style.left = rootX2 - clientX2 + \"px\";\n }\n domNode.scrollIntoView({ block: \"nearest\", behavior: \"smooth\" });\n } else {\n domNode.style.left = null;\n }\n }\n }\n\n toggleExpand(index, expanded) {\n // close open menu, if applicable\n if (this.openIndex !== index) {\n this.toggleExpand(this.openIndex, false);\n }\n\n // handle menu at called index\n if (this.triggerNodes[index]) {\n this.openIndex = expanded ? index : null;\n this.triggerNodes[index].setAttribute(\"aria-expanded\", expanded);\n this.toggleMenu(this.controlledNodes[index], expanded);\n }\n }\n\n controlFocusByKey(event, nodeList, currentIndex) {\n let handledKeys = [\n \"ArrowLeft\",\n \"ArrowUp\",\n \"ArrowRight\",\n \"ArrowDown\",\n \"Home\",\n \"End\",\n ];\n\n if (handledKeys.includes(event.key)) {\n event.preventDefault();\n event.stopPropagation();\n }\n\n switch (event.key) {\n case \"ArrowLeft\":\n if (this.triggerNodes.length > 0) {\n let index =\n this.openIndex <= 0\n ? this.triggerNodes.length - 1\n : this.openIndex - 1;\n this.triggerNodes[index].focus();\n this.toggleExpand(index, true);\n this.controlledNodes[index]\n .querySelector(\"a, .ob-disclosure-nav__link\")\n .focus();\n }\n break;\n case \"ArrowUp\":\n if (currentIndex > -1) {\n let prevIndex =\n currentIndex <= 0 ? nodeList.length - 1 : currentIndex - 1;\n nodeList[prevIndex].focus();\n }\n break;\n case \"ArrowRight\":\n if (this.triggerNodes.length > 0) {\n let index =\n this.openIndex >= this.triggerNodes.length - 1\n ? 0\n : this.openIndex + 1;\n this.triggerNodes[index].focus();\n this.toggleExpand(index, true);\n this.controlledNodes[index]\n .querySelector(\"a, .ob-disclosure-nav__link\")\n .focus();\n }\n break;\n case \"ArrowDown\":\n if (currentIndex > -1) {\n let nextIndex =\n currentIndex >= nodeList.length - 1 ? 0 : currentIndex + 1;\n nodeList[nextIndex].focus();\n }\n break;\n case \"Home\":\n nodeList[0].focus();\n break;\n case \"End\":\n nodeList[nodeList.length - 1].focus();\n break;\n }\n }\n\n handleBlur(event) {\n let menuContainsFocus = this.contains(event.relatedTarget);\n if (!menuContainsFocus && this.openIndex !== null) {\n this.toggleExpand(this.openIndex, false);\n }\n }\n\n handleButtonKeyDown(event) {\n let targetButtonIndex = this.triggerNodes.indexOf(document.activeElement);\n\n // close on escape\n if (event.key === \"Escape\") {\n this.toggleExpand(this.openIndex, false);\n }\n\n // move focus into the related menu and opens it if necessary\n else if (this.useArrowKeys && event.key === \"ArrowDown\") {\n event.preventDefault();\n if (this.openIndex !== targetButtonIndex) {\n this.toggleExpand(targetButtonIndex, true);\n }\n this.controlledNodes[this.openIndex]\n .querySelector(\"a, .ob-disclosure-nav__link\")\n .focus();\n }\n\n // handle arrow key navigation between top-level buttons, if set\n else if (this.useArrowKeys) {\n this.controlFocusByKey(event, this.triggerNodes, targetButtonIndex);\n }\n }\n\n handleButtonClick(event) {\n let button = event.currentTarget;\n let buttonIndex = this.triggerNodes.indexOf(button);\n let buttonExpanded = button.getAttribute(\"aria-expanded\") === \"true\";\n this.toggleExpand(buttonIndex, !buttonExpanded);\n }\n\n handleMenuKeyDown(event) {\n if (this.openIndex === null) {\n return;\n }\n\n let menuLinks = Array.prototype.slice.call(\n this.controlledNodes[this.openIndex].querySelectorAll(\"a\")\n );\n let currentIndex = menuLinks.indexOf(document.activeElement);\n\n // close on escape\n if (event.key === \"Escape\") {\n this.triggerNodes[this.openIndex].focus();\n this.toggleExpand(this.openIndex, false);\n }\n\n // handle arrow key navigation within menu links, if set\n else if (this.useArrowKeys) {\n this.controlFocusByKey(event, menuLinks, currentIndex);\n }\n }\n\n // switch on/off arrow key navigation\n updateKeyControls(useArrowKeys) {\n this.useArrowKeys = useArrowKeys;\n }\n}\n\nwindow.customElements.define(\"ob-disclosure-nav\", DisclosureNav);\n"], "mappings": "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", "names": [] }