import React from "react"; export const PortalContainerContext = React.createContext(undefined); function findOrCreatePortalContainer(root: ShadowRoot | Document, id = "plugin-portal-container") { // Determine the actual parent element to search and append to const parentElement = root instanceof Document ? root.body : root; // look only at direct children for (const child of Array.from(parentElement.children)) { if (child instanceof HTMLElement && child.id === id) { return child; } } // not found → create const container = document.createElement("div"); container.id = id; parentElement.appendChild(container); return container; } export function PortalContainerProvider({ children, id = "plugin-portal-container", }: { children: React.ReactNode; id?: string; }) { const inherited = React.useContext(PortalContainerContext); const ref = React.useRef(null); const [container, setContainer] = React.useState( inherited || undefined ); React.useEffect(() => { // If a parent already provides a portal container, inherit it if (inherited) { setContainer(inherited); return; } if (ref.current) { const root = ref.current.getRootNode(); if (root instanceof ShadowRoot || root instanceof Document) { const container = findOrCreatePortalContainer(root, id); setContainer(container); } else { setContainer(null); } } }, [id, inherited]); // If container not discovered yet → render hidden marker only if (container === undefined) { return
; } // Once container is resolved (null or HTMLElement) → provide it return ( {children} ); } export function usePortalContainer() { return React.useContext(PortalContainerContext); }