{"version":3,"file":"useKeepBrowserExtensionsInteractive.mjs","names":[],"sources":["../../../../../../../../src/lib/hooks/dom/useKeepBrowserExtensionsInteractive.ts"],"sourcesContent":["import { useEffect } from \"react\";\n\n/**\n * Attribute react-aria checks to keep a node out of the `inert` / `aria-hidden`\n * isolation it applies to everything outside an open modal overlay.\n *\n * @see `isAlwaysVisibleNode` in `@react-aria/overlays` (`ariaHideOutside`)\n */\nconst keepInteractiveAttribute = \"data-react-aria-top-layer\";\n\nconst extensionUrlSchemes = [\n  \"chrome-extension:\",\n  \"moz-extension:\",\n  \"safari-web-extension:\",\n  \"safari-extension:\",\n];\n\nexport const isBrowserExtensionNode = (element: Element): boolean => {\n  if (element.tagName.includes(\"-\")) {\n    return true;\n  }\n  if (element.shadowRoot !== null) {\n    return true;\n  }\n  if (element instanceof HTMLIFrameElement) {\n    const source = element.getAttribute(\"src\") ?? \"\";\n    return extensionUrlSchemes.some((scheme) => source.startsWith(scheme));\n  }\n  return false;\n};\n\nconst keepInteractive = (element: Element): void => {\n  if (!element.hasAttribute(keepInteractiveAttribute)) {\n    element.setAttribute(keepInteractiveAttribute, \"\");\n  }\n  if (element instanceof HTMLElement && element.inert) {\n    element.inert = false;\n  }\n  if (element.getAttribute(\"aria-hidden\") === \"true\") {\n    element.removeAttribute(\"aria-hidden\");\n  }\n};\n\n/**\n * While a modal overlay is open, react-aria isolates the rest of the document\n * by setting `inert` on every sibling of the modal (see `ariaHideOutside`) —\n * and it keeps doing so for nodes that appear afterwards via a\n * `MutationObserver`. That also catches UI a browser extension injects while\n * the modal is open, e.g. a password manager's autofill dropdown on a field, or\n * its \"save credentials\" popover. An `inert` node stays visible but cannot be\n * clicked, so the user sees the extension UI but cannot interact with it.\n *\n * This hook watches the document while `isActive` and re-enables such\n * extension-injected, document-level nodes, so browser extensions keep working\n * on top of modals. It targets the structural fingerprint of extension UI (see\n * {@link isBrowserExtensionNode}) rather than a fixed list of vendors.\n */\nexport const useKeepBrowserExtensionsInteractive = (\n  isActive: boolean,\n): void => {\n  useEffect(() => {\n    if (!isActive || typeof MutationObserver === \"undefined\") {\n      return;\n    }\n\n    const root = document.body;\n\n    const process = (node: Node): void => {\n      if (node instanceof Element && isBrowserExtensionNode(node)) {\n        keepInteractive(node);\n      }\n    };\n\n    for (const child of Array.from(root.children)) {\n      process(child);\n    }\n\n    const observer = new MutationObserver((mutations) => {\n      for (const mutation of mutations) {\n        for (const node of Array.from(mutation.addedNodes)) {\n          process(node);\n        }\n      }\n    });\n    observer.observe(root, { childList: true });\n\n    return () => observer.disconnect();\n  }, [isActive]);\n};\n\nexport default useKeepBrowserExtensionsInteractive;\n"],"mappings":";;;;;;;;;;AAQA,IAAM,2BAA2B;AAEjC,IAAM,sBAAsB;CAC1B;CACA;CACA;CACA;AACF;AAEA,IAAa,0BAA0B,YAA8B;CACnE,IAAI,QAAQ,QAAQ,SAAS,GAAG,GAC9B,OAAO;CAET,IAAI,QAAQ,eAAe,MACzB,OAAO;CAET,IAAI,mBAAmB,mBAAmB;EACxC,MAAM,SAAS,QAAQ,aAAa,KAAK,KAAK;EAC9C,OAAO,oBAAoB,MAAM,WAAW,OAAO,WAAW,MAAM,CAAC;CACvE;CACA,OAAO;AACT;AAEA,IAAM,mBAAmB,YAA2B;CAClD,IAAI,CAAC,QAAQ,aAAa,wBAAwB,GAChD,QAAQ,aAAa,0BAA0B,EAAE;CAEnD,IAAI,mBAAmB,eAAe,QAAQ,OAC5C,QAAQ,QAAQ;CAElB,IAAI,QAAQ,aAAa,aAAa,MAAM,QAC1C,QAAQ,gBAAgB,aAAa;AAEzC;;;;;;;;;;;;;;;AAgBA,IAAa,uCACX,aACS;CACT,gBAAgB;EACd,IAAI,CAAC,YAAY,OAAO,qBAAqB,aAC3C;EAGF,MAAM,OAAO,SAAS;EAEtB,MAAM,WAAW,SAAqB;GACpC,IAAI,gBAAgB,WAAW,uBAAuB,IAAI,GACxD,gBAAgB,IAAI;EAExB;EAEA,KAAK,MAAM,SAAS,MAAM,KAAK,KAAK,QAAQ,GAC1C,QAAQ,KAAK;EAGf,MAAM,WAAW,IAAI,kBAAkB,cAAc;GACnD,KAAK,MAAM,YAAY,WACrB,KAAK,MAAM,QAAQ,MAAM,KAAK,SAAS,UAAU,GAC/C,QAAQ,IAAI;EAGlB,CAAC;EACD,SAAS,QAAQ,MAAM,EAAE,WAAW,KAAK,CAAC;EAE1C,aAAa,SAAS,WAAW;CACnC,GAAG,CAAC,QAAQ,CAAC;AACf"}