|
1 | | -import React, { useMemo } from 'react'; |
| 1 | +import React, { useMemo, useRef, useState } from 'react'; |
| 2 | +import ReactDOM from 'react-dom'; |
2 | 3 |
|
3 | 4 | export interface RunWebProps extends React.IframeHTMLAttributes<HTMLIFrameElement> { |
4 | 5 | css?: string; |
5 | 6 | js?: string; |
6 | 7 | html?: string; |
7 | 8 | title?: string; |
| 9 | + head?: React.ReactNode; |
8 | 10 | } |
9 | 11 |
|
10 | 12 | export default React.forwardRef<HTMLIFrameElement, RunWebProps>((props, ref) => { |
11 | | - const { html = '', css, js, title = 'Demo Title', ...other } = props; |
12 | | - |
| 13 | + const { html = '', css, js, title = 'Demo Title', head, onLoad, ...other } = props; |
| 14 | + const [isLoaded, setIsLoaded] = useState(false); |
| 15 | + const frameRef = useRef<HTMLIFrameElement>(null); |
13 | 16 | const srcDoc = useMemo(() => { |
| 17 | + setIsLoaded(false); |
14 | 18 | const jsString = js ? `<script type="text/javascript">${js}</script>` : ''; |
15 | 19 | const cssString = css ? `<style>${css}</style>` : ''; |
16 | 20 | return `<!DOCTYPE html><html><head>${cssString}</head><body>${html}</body>${jsString}</html>`; |
17 | 21 | }, [css, html, js]); |
18 | 22 |
|
19 | | - return <iframe title={title} width="100%" height="100%" style={{ border: 0 }} {...other} ref={ref} srcDoc={srcDoc} />; |
| 23 | + function renderFrameContents() { |
| 24 | + if (!frameRef.current || !frameRef.current.contentDocument || !frameRef.current.contentWindow) return null; |
| 25 | + return [ReactDOM.createPortal(head, frameRef.current.contentDocument.head)]; |
| 26 | + } |
| 27 | + |
| 28 | + return ( |
| 29 | + <iframe |
| 30 | + title={title} |
| 31 | + width="100%" |
| 32 | + height="100%" |
| 33 | + style={{ border: 0 }} |
| 34 | + {...other} |
| 35 | + onLoad={(evn) => { |
| 36 | + setIsLoaded(true); |
| 37 | + onLoad && onLoad(evn); |
| 38 | + }} |
| 39 | + ref={frameRef} |
| 40 | + srcDoc={srcDoc} |
| 41 | + > |
| 42 | + {isLoaded && renderFrameContents()} |
| 43 | + </iframe> |
| 44 | + ); |
20 | 45 | }); |
0 commit comments