|
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