import React, { HTMLAttributes, useCallback, useEffect, useRef, useState } from 'react'; import { createPortal } from 'react-dom'; import { SilkeIframeContext, SilkeIframeContextModel } from './silke-iframe-context'; type SilkeIframePortalProps = Omit, 'sandbox'> & { children: React.ReactNode; /** Override default srcDoc */ srcDoc?: string; autoResize?: boolean; bodyStyle?: React.CSSProperties; }; const DEFAULT_SRC_DOC = ''; export function SilkeIframePortal({ bodyStyle, children, style, srcDoc, autoResize, onLoad, ...rest }: SilkeIframePortalProps) { const iframeRef = useRef(null); const [innerElement, setInnerElement] = useState(); const [context, setContext] = useState({}); const handleLoad: React.ReactEventHandler = useCallback((e) => { const iframe = e.currentTarget; const doc = iframe.contentDocument; const win = iframe.contentWindow; if (doc && win) { const innerElement = doc.createElement('div'); doc.body.appendChild(innerElement); setInnerElement(innerElement); setContext({ doc, win }); } onLoad?.(e); }, []); const body = context.doc?.body; useEffect(() => { if (body) { Object.assign(body.style, bodyStyle); } }, [bodyStyle, body]); useEffect(() => { const iframe = iframeRef.current; if (iframe && body && autoResize) { const handleResize = () => { const { height } = body.getBoundingClientRect(); iframe.style.height = `${height}px`; }; const resizeObserver = new ResizeObserver(handleResize); handleResize(); resizeObserver.observe(body); return () => resizeObserver.disconnect(); } }, [body, autoResize]); return (