UNPKG

@adyen/adyen-platform-experience-web

Version:

![Platform Experience header](https://github.com/Adyen/adyen-platform-experience-web/assets/7926613/18094965-9e01-450e-8dc9-ea84e6b22c2b)

120 lines (119 loc) 3.98 kB
import { some as h } from "../../../utils/collection/main.js"; import { isUndefined as R, isNullish as N, isNumber as m } from "../../../utils/value/is.js"; import { mod as x } from "../../../utils/value/number.js"; const k = `:scope ${` a[href], audio[controls], video[controls], button, input, select, textarea, [contenteditable], [tabindex] `.replace(/\s+/g, "")}`, I = ["contenteditable", "controls", "disabled", "hidden", "href", "inert", "tabindex"], p = /* @__PURE__ */ new Map(), E = (t) => t.tagName === "INPUT", T = (t) => E(t) && t.type === "radio", A = (t) => { const e = t.name, n = t.form, r = p.get(n); let c = r?.get(e); return R(c) && n && (c = n.querySelector(`:scope input[type=radio][name='${e}']:checked`) || null, p.set(n, (r || /* @__PURE__ */ new Map()).set(e, c))), c === t; }, g = (t = document) => { let e = t.activeElement; for (; e && e.shadowRoot && e.shadowRoot.activeElement; ) e = e.shadowRoot.activeElement; return e; }, w = (t = document.body, e) => { if (R(t)) return !1; if (N(e)) { const r = g(); return !!r && w(t, r); } let n = e.parentNode; for (; n; ) { if (n === t) return !0; n = n instanceof ShadowRoot ? n.host : n?.parentNode || null; } return !1; }, C = (t) => !// [TODO]: Include all of these checks // (1) matches focusable elements selector // (2) is disabled element // (3) is inert or inert subtree child // (4) is hidden input // (5) with visibility: hidden // (6) is summary of open details element // (7) is details with summary element // (8) is disabled fieldset subtree child /* (1) */ (!t.matches(k) || /* (2) */ t?.disabled || /* (3) */ /^(true)?$/.test(t.getAttribute("inert")) || /* (4) */ E(t) && t.hidden), b = (t) => !(T(t) && !A(t) || // (1) is not checked radio button t?.tabIndex < 0 || // (2) has negative tabindex !C(t)), L = () => { const t = new MutationObserver((o) => v(o) && l()), e = []; let n = -1, r = null; const c = (o) => { if (o < 0) return; const s = Math.min(o, e.length - 1); n !== s && (n = s), e[n]?.focus(); }, l = () => { if (e.length = 0, !r) return; const o = { attributeFilter: I, attributes: !0, childList: !0, subtree: !0 }; t.observe(r, o); const s = (i) => { const a = document.createTreeWalker(i, NodeFilter.SHOW_ELEMENT, { acceptNode: () => NodeFilter.FILTER_ACCEPT }); let u = a.nextNode(); for (; u; ) { const d = u; b(d) && e.push(d), d.shadowRoot && (t.observe(d.shadowRoot, o), s(d.shadowRoot)), u = a.nextNode(); } }; s(r), w(r) && (f.current = g()); }, v = (o) => { let s = !1; for (const i of o) if (i.type === "attributes" ? s ||= i.target instanceof Element && // Target is a tabbable element (possibly due to attribute changes) // For example, disabled set to false, tabindex set to a number, etc. (b(i.target) || // Target is already contained in the list of tabbables // Attribute changes could make it no longer tabbable (e.g. disabled set to true) e.includes(i.target)) : s ||= // At least one element was added or removed from the DOM tree of the root element h(i.addedNodes, (a) => a instanceof Element) || h(i.removedNodes, (a) => a instanceof Element), s) break; return s; }, f = Object.create(null, { current: { get: () => e[n] ?? null, set: (o) => { if (o) { if (!m(o)) return c(e.indexOf(o)); if (o === ~~o) return c(x(n + o, e.length)); } } }, root: { get: () => r, set: (o) => { o !== r && (r && t.disconnect(), r = o instanceof Element ? o : null, l()); } }, tabbables: { value: e } }); return f; }; export { k as SELECTORS, L as default, w as focusIsWithin, g as getDeepActiveElement, C as isFocusable, b as isTabbable, L as withTabbableRoot };