(function () { "use strict"; if (document.querySelector("[data-editor-form]")) { return; } var browser = document.querySelector(".miller-browser"); if (!browser) { return; } var documentShell = document.querySelector(".document-shell[data-document-path]"); var markdownBody = document.querySelector(".markdown-body"); var mode = "browser"; var selectedColumnIndex = 0; var selectedLink = null; var selectedParagraphIndex = -1; function getColumns() { return Array.prototype.slice.call(browser.querySelectorAll(".miller-column")); } function getColumnLinks(columnIndex) { var columns = getColumns(); if (!columns[columnIndex]) { return []; } return Array.prototype.slice.call(columns[columnIndex].querySelectorAll("a[href]")); } function getParagraphTargets() { if (!markdownBody) { return []; } return Array.prototype.slice.call( markdownBody.querySelectorAll(".commentable, p, h1, h2, h3, h4, h5, h6, li, blockquote, pre") ).filter(function (el) { return (el.textContent || "").trim().length > 0; }); } function clamp(value, min, max) { return Math.max(min, Math.min(max, value)); } function isEditableTarget(target) { if (!target) { return false; } return Boolean(target.closest( "input, textarea, select, [contenteditable='true'], [contenteditable=''], [role='textbox'], .monaco-editor" )); } function isKeyboardNavigationTarget(target) { if (!target) { return false; } return Boolean(target.closest(".miller-browser a[href], .markdown-body .is-keyboard-selected")); } function shouldIgnoreTarget(target) { if (isEditableTarget(target)) { return true; } if (isKeyboardNavigationTarget(target)) { return false; } return Boolean(target && target.closest("a[href], button, summary, details, [role='button'], [role='menuitem']")); } function showKeyboardUI() { document.body.classList.add("keyboard-navigation-active"); } function clearBrowserSelection() { browser.querySelectorAll(".is-keyboard-selected").forEach(function (node) { node.classList.remove("is-keyboard-selected"); node.removeAttribute("aria-selected"); }); } function clearParagraphSelection() { getParagraphTargets().forEach(function (node) { node.classList.remove("is-keyboard-selected"); node.removeAttribute("tabindex"); node.removeAttribute("aria-selected"); }); } function scrollBrowserColumnIntoView(column) { if (!column) { return; } var leftEdge = column.offsetLeft; var rightEdge = leftEdge + column.offsetWidth; var targetLeft = browser.scrollLeft; if (leftEdge < browser.scrollLeft) { targetLeft = leftEdge - 8; } else if (rightEdge > browser.scrollLeft + browser.clientWidth) { targetLeft = rightEdge - browser.clientWidth + 8; } if (targetLeft !== browser.scrollLeft) { browser.scrollTo({ left: Math.max(0, targetLeft), behavior: "smooth" }); } } function expandColumnForKeyboard(column) { getColumns().forEach(function (candidate) { if (candidate !== column) { candidate.classList.remove("is-preview-expanded"); candidate.style.removeProperty("--expanded-column-width"); } }); if (!column || !column.matches(".miller-column:not(:first-child):not(:last-child)")) { return; } var expandedWidth = Math.min(Math.max(column.scrollWidth + 12, 192), 384); column.style.setProperty("--expanded-column-width", expandedWidth + "px"); column.classList.add("is-preview-expanded"); } function updateBrowserSelection(focusSelected) { clearBrowserSelection(); var columns = getColumns(); var column = columns[selectedColumnIndex]; if (!column) { return; } expandColumnForKeyboard(column); scrollBrowserColumnIntoView(column); if (!selectedLink || !column.contains(selectedLink)) { selectedLink = column.querySelector("a.is-active[href]") || column.querySelector("a[href]"); } if (!selectedLink) { return; } selectedLink.classList.add("is-keyboard-selected"); selectedLink.setAttribute("aria-selected", "true"); if (focusSelected) { selectedLink.focus({ preventScroll: true }); } } function selectBrowserColumn(columnIndex, focusSelected) { var columns = getColumns(); if (!columns.length) { return; } mode = "browser"; selectedColumnIndex = clamp(columnIndex, 0, columns.length - 1); var links = getColumnLinks(selectedColumnIndex); selectedLink = links.find(function (link) { return link.classList.contains("is-active"); }) || links[0] || null; clearParagraphSelection(); updateBrowserSelection(focusSelected); } function moveBrowserVertical(delta) { var links = getColumnLinks(selectedColumnIndex); if (!links.length) { return; } var currentIndex = links.indexOf(selectedLink); if (currentIndex < 0) { currentIndex = links.findIndex(function (link) { return link.classList.contains("is-active"); }); } if (currentIndex < 0) { currentIndex = 0; } selectedLink = links[clamp(currentIndex + delta, 0, links.length - 1)]; updateBrowserSelection(true); } function navigateTo(link) { if (!link || !link.href) { return; } window.location.href = link.href; } function moveBrowserRight() { var columns = getColumns(); if (!columns.length) { return; } if (selectedColumnIndex < columns.length - 1 && selectedLink && selectedLink.classList.contains("is-active")) { selectBrowserColumn(selectedColumnIndex + 1, true); return; } if (selectedColumnIndex < columns.length - 1 && !selectedLink) { selectBrowserColumn(selectedColumnIndex + 1, true); return; } if (selectedLink && !selectedLink.classList.contains("is-active")) { navigateTo(selectedLink); return; } if (markdownBody && getParagraphTargets().length) { enterParagraphMode(0); } else if (selectedLink) { navigateTo(selectedLink); } } function nearestParagraphIndex() { var targets = getParagraphTargets(); if (!targets.length) { return -1; } if (selectedParagraphIndex >= 0 && selectedParagraphIndex < targets.length) { return selectedParagraphIndex; } var shellRect = documentShell ? documentShell.getBoundingClientRect() : null; var targetY = shellRect ? shellRect.top + shellRect.height * 0.35 : window.innerHeight * 0.35; var bestIndex = 0; var bestDistance = Number.POSITIVE_INFINITY; targets.forEach(function (el, index) { var distance = Math.abs(el.getBoundingClientRect().top - targetY); if (distance < bestDistance) { bestDistance = distance; bestIndex = index; } }); return bestIndex; } function selectParagraph(index) { var targets = getParagraphTargets(); if (!targets.length) { return; } clearBrowserSelection(); clearParagraphSelection(); mode = "paragraph"; selectedParagraphIndex = clamp(index, 0, targets.length - 1); var target = targets[selectedParagraphIndex]; target.classList.add("is-keyboard-selected"); target.setAttribute("aria-selected", "true"); target.setAttribute("tabindex", "-1"); target.focus({ preventScroll: true }); target.scrollIntoView({ block: "nearest", behavior: "smooth" }); } function enterParagraphMode(offset) { var index = nearestParagraphIndex(); if (index < 0) { return; } selectParagraph(index + offset); } function moveParagraphVertical(delta) { var targets = getParagraphTargets(); if (!targets.length) { return; } var currentIndex = selectedParagraphIndex; if (currentIndex < 0 || currentIndex >= targets.length) { currentIndex = nearestParagraphIndex(); } selectParagraph(currentIndex + delta); } function openSelectedParagraphInEditor() { var editLink = document.querySelector(".document-actions-dropdown__item[href$='/edit']"); if (editLink) { navigateTo(editLink); return; } var path = documentShell ? documentShell.getAttribute("data-document-path") : ""; if (!path) { return; } window.location.href = "/docs/" + path.replace(/\.md$/, "") + "/edit"; } function focusSearch() { var search = document.querySelector(".site-search input[type='search'], .site-search input[name='q']"); if (!search) { return; } clearBrowserSelection(); clearParagraphSelection(); search.focus(); search.select(); } function focusCommentsSidebar() { var desktopToggle = document.querySelector("[data-comment-toggle]"); if (desktopToggle && desktopToggle.getAttribute("aria-pressed") === "false") { desktopToggle.click(); } var mobileToggle = document.querySelector("[data-toggle-comments]"); if (mobileToggle && window.matchMedia("(max-width: 760px)").matches && mobileToggle.getAttribute("aria-expanded") === "false") { mobileToggle.click(); } var focusTarget = document.querySelector("[data-comments-aside-list] .comments-aside-item") || document.querySelector("[data-comments-aside-list]") || document.querySelector("[data-comments-aside]"); if (!focusTarget) { return; } clearBrowserSelection(); clearParagraphSelection(); focusTarget.setAttribute("tabindex", "-1"); focusTarget.focus({ preventScroll: false }); } function focusDocumentActions() { var dropdown = document.querySelector(".document-actions-dropdown"); if (!dropdown) { return; } dropdown.open = true; var focusTarget = dropdown.querySelector(".document-actions-dropdown__item[href], .document-actions-dropdown__item:not([disabled])") || dropdown.querySelector("summary"); if (!focusTarget) { return; } clearBrowserSelection(); clearParagraphSelection(); focusTarget.focus(); } function closeDocumentActions() { var dropdown = document.querySelector(".document-actions-dropdown[open]"); if (dropdown) { dropdown.open = false; var summary = dropdown.querySelector("summary"); if (summary) { summary.focus(); } return true; } return false; } function handleEnter() { if (mode === "paragraph") { openSelectedParagraphInEditor(); return; } navigateTo(selectedLink); } function handleKeydown(event) { if (event.defaultPrevented || event.ctrlKey || event.metaKey || event.altKey || shouldIgnoreTarget(event.target)) { return; } var key = event.key; var normalized = key.length === 1 ? key.toLowerCase() : key; if (event.code === "Backslash" || key === "\\") { event.preventDefault(); focusSearch(); return; } if (normalized === "c") { event.preventDefault(); focusCommentsSidebar(); return; } if (normalized === "e") { event.preventDefault(); focusDocumentActions(); return; } if (key === "Escape" && closeDocumentActions()) { event.preventDefault(); return; } if (key === "ArrowUp" || normalized === "k") { event.preventDefault(); showKeyboardUI(); if (mode === "paragraph") { moveParagraphVertical(-1); } else { moveBrowserVertical(-1); } return; } if (key === "ArrowDown" || normalized === "j") { event.preventDefault(); showKeyboardUI(); if (mode === "paragraph") { moveParagraphVertical(1); } else { moveBrowserVertical(1); } return; } if (key === "ArrowLeft" || normalized === "h") { event.preventDefault(); showKeyboardUI(); if (mode === "paragraph") { selectBrowserColumn(getColumns().length - 1, true); } else { selectBrowserColumn(selectedColumnIndex - 1, true); } return; } if (key === "ArrowRight" || normalized === "l") { event.preventDefault(); showKeyboardUI(); if (mode === "paragraph") { return; } moveBrowserRight(); return; } if (key === "Enter") { event.preventDefault(); showKeyboardUI(); handleEnter(); } } function initSelection() { var columns = getColumns(); if (!columns.length) { return; } var activeLinks = Array.prototype.slice.call(browser.querySelectorAll("a.is-active[href]")); var activeLink = activeLinks[activeLinks.length - 1] || browser.querySelector("a[href]"); selectedLink = activeLink; if (activeLink) { var activeColumn = activeLink.closest(".miller-column"); selectedColumnIndex = Math.max(0, columns.indexOf(activeColumn)); } } initSelection(); document.addEventListener("keydown", handleKeydown); })();