UNPKG

@primer/react

Version:

An implementation of GitHub's Primer Design System using React

43 lines (42 loc) 1.61 kB
//#region src/internal/utils/hasInteractiveNodes.ts const nonValidSelectors = { disabled: "[disabled]", hidden: "[hidden]", inert: "[inert]", negativeTabIndex: "[tabindex=\"-1\"]" }; const interactiveSelector = [ `a[href]`, `button`, "summary", "select", "input:not([type=hidden])", "textarea", "[tabindex=\"0\"]", `audio[controls]`, `video[controls]`, `[contenteditable]` ].map((selector) => `${selector}:not(${Object.values(nonValidSelectors).join("):not(")})`).join(", "); /** * Finds interactive nodes within the passed node. * If the node itself is interactive, or children within are, it will return true. * * @param node - The HTML element to search for interactive nodes in. * @param ignoreSelectors - A string of selectors to ignore when searching for interactive nodes. This is useful for * ignoring nodes that are conditionally interactive based on the return value of the function. * @returns {boolean | undefined} */ function hasInteractiveNodes(node, ignoreNodes) { if (!node || isNonValidInteractiveNode(node)) return false; const nodesToIgnore = ignoreNodes ? [node, ...ignoreNodes] : [node]; const candidates = node.querySelectorAll(interactiveSelector); for (const candidate of candidates) if (!nodesToIgnore.includes(candidate) && !isNonValidInteractiveNode(candidate)) return true; return false; } function isNonValidInteractiveNode(node) { if (node.matches("[disabled], [hidden], [inert]")) return true; const nodeStyle = getComputedStyle(node); return nodeStyle.display === "none" || nodeStyle.visibility === "hidden"; } //#endregion export { hasInteractiveNodes };