// src/internal/tabbable.ts var computedStyleMap = /* @__PURE__ */ new WeakMap(); function getCachedComputedStyle(el) { let computedStyle = computedStyleMap.get(el); if (!computedStyle) { computedStyle = window.getComputedStyle(el, null); computedStyleMap.set(el, computedStyle); } return computedStyle; } function isVisible(el) { if (typeof el.checkVisibility === "function") { return el.checkVisibility({ checkOpacity: false, checkVisibilityCSS: true }); } const computedStyle = getCachedComputedStyle(el); return computedStyle.visibility !== "hidden" && computedStyle.display !== "none"; } function isOverflowingAndTabbable(el) { const computedStyle = getCachedComputedStyle(el); const { overflowY, overflowX } = computedStyle; if (overflowY === "scroll" || overflowX === "scroll") { return true; } if (overflowY !== "auto" || overflowX !== "auto") { return false; } const isOverflowingY = el.scrollHeight > el.clientHeight; if (isOverflowingY && overflowY === "auto") { return true; } const isOverflowingX = el.scrollWidth > el.clientWidth; if (isOverflowingX && overflowX === "auto") { return true; } return false; } function isTabbable(el) { const tag = el.tagName.toLowerCase(); const tabindex = Number(el.getAttribute("tabindex")); const hasTabindex = el.hasAttribute("tabindex"); if (hasTabindex && (isNaN(tabindex) || tabindex <= -1)) { return false; } if (el.hasAttribute("disabled")) { return false; } if (el.closest("[inert]")) { return false; } if (tag === "input" && el.getAttribute("type") === "radio" && !el.hasAttribute("checked")) { return false; } if (!isVisible(el)) { return false; } if ((tag === "audio" || tag === "video") && el.hasAttribute("controls")) { return true; } if (el.hasAttribute("tabindex")) { return true; } if (el.hasAttribute("contenteditable") && el.getAttribute("contenteditable") !== "false") { return true; } const isNativelyTabbable = [ "button", "input", "select", "textarea", "a", "audio", "video", "summary", "iframe" ].includes(tag); if (isNativelyTabbable) { return true; } return isOverflowingAndTabbable(el); } function getTabbableBoundary(root) { var _a, _b; const tabbableElements = getTabbableElements(root); const start = (_a = tabbableElements[0]) != null ? _a : null; const end = (_b = tabbableElements[tabbableElements.length - 1]) != null ? _b : null; return { start, end }; } function getSlottedChildrenOutsideRootElement(slotElement, root) { var _a; return ((_a = slotElement.getRootNode({ composed: true })) == null ? void 0 : _a.host) !== root; } function getTabbableElements(root) { const walkedEls = /* @__PURE__ */ new WeakMap(); const tabbableElements = []; function walk(el) { if (el instanceof Element) { if (el.hasAttribute("inert") || el.closest("[inert]")) { return; } if (walkedEls.has(el)) { return; } walkedEls.set(el, true); if (!tabbableElements.includes(el) && isTabbable(el)) { tabbableElements.push(el); } if (el instanceof HTMLSlotElement && getSlottedChildrenOutsideRootElement(el, root)) { el.assignedElements({ flatten: true }).forEach((assignedEl) => { walk(assignedEl); }); } if (el.shadowRoot !== null && el.shadowRoot.mode === "open") { walk(el.shadowRoot); } } for (const e of el.children) { walk(e); } } walk(root); return tabbableElements.sort((a, b) => { const aTabindex = Number(a.getAttribute("tabindex")) || 0; const bTabindex = Number(b.getAttribute("tabindex")) || 0; return bTabindex - aTabindex; }); } export { getTabbableBoundary, getTabbableElements };