11import React , {
2- useEffect , forwardRef , useCallback , MouseEventHandler
2+ useEffect , useCallback , MouseEventHandler , useState
33} from 'react' ;
44import { css } from '@emotion/react' ;
5+ import throttle from 'lodash/throttle' ;
56import { useOvermindEffects } from '../store' ;
67
78type IframeProps = {
@@ -10,7 +11,7 @@ type IframeProps = {
1011 html : string ;
1112 width ?: string ;
1213 cssCode ?: string ;
13- onResize ?: ( ) => void ;
14+ onResize ?: ( iframe : HTMLIFrameElement | null ) => void ;
1415}
1516
1617const styles = {
@@ -20,27 +21,43 @@ const styles = {
2021 `
2122} ;
2223
23- const Iframe = forwardRef < HTMLIFrameElement , IframeProps > ( ( {
24+ const Iframe = ( {
2425 className, html, cssCode, onResize, name, width
25- } : IframeProps , ref ) => {
26+ } : IframeProps ) => {
2627 const effects = useOvermindEffects ( ) ;
28+ const [ iframe , setIframe ] = useState < HTMLIFrameElement | null > ( null ) ;
29+ const [ isLoaded , setLoaded ] = useState ( false ) ;
2730
28- const handleResize = useCallback ( ( ) => {
29- if ( ref . current ) {
30- ref . current . height = ref . current . contentDocument . body . scrollHeight || 0 ;
31- ref . current . width = width ? width : ref . current . contentDocument . body . scrollWidth || 0 ;
31+ const handleResize = useCallback ( throttle ( ( ) => {
32+ if ( iframe ) {
33+ iframe . height = iframe . contentDocument . body . scrollHeight + 30 ;
34+ iframe . width = width ? width : iframe . contentDocument . body . scrollWidth || 0 ;
3235 }
3336
3437 if ( onResize ) {
35- onResize ( ) ;
38+ onResize ( iframe ) ;
3639 }
37- } , [ onResize , width ] ) ;
40+ } , 300 ) , [ onResize , width , html , iframe ] ) ;
3841
39- useEffect ( ( ) => ( ) => {
40- window . removeEventListener ( 'resize' , handleResize ) ;
41- } , [ handleResize ] ) ;
42+ const handleFocus = useCallback ( ( ) => {
43+ if ( iframe ) {
44+ iframe . contentWindow ?. getSelection ( ) ?. empty ( ) ;
45+ }
46+ } , [ iframe ] ) ;
47+
48+ useEffect ( ( ) => {
49+ if ( isLoaded ) {
50+ handleResize ( ) ;
51+ window . addEventListener ( 'resize' , handleResize ) ;
52+ }
53+
54+ return ( ) => {
55+ window . removeEventListener ( 'resize' , handleResize ) ;
56+ } ;
57+ } , [ isLoaded , handleResize ] ) ;
4258
4359 const onLoad = useCallback ( ( ) => {
60+ setLoaded ( true ) ;
4461 const interceptIframeInternalRedirect : MouseEventHandler < HTMLElement > = ( e ) => {
4562 e . preventDefault ( ) ;
4663 e . stopPropagation ( ) ;
@@ -57,37 +74,41 @@ const Iframe = forwardRef<HTMLIFrameElement, IframeProps>(({
5774 }
5875 } ;
5976
60- if ( ref . current ) {
61- for ( const elem of ref . current . contentDocument ?. body . querySelectorAll ( [ 'a' , 'img' , 'button' , 'input' ] ) ?? [ ] ) {
77+ if ( iframe ) {
78+ for ( const elem of iframe . contentDocument ?. body . querySelectorAll ( [ 'a' , 'img' , 'button' , 'input' ] ) ?? [ ] ) {
6279 elem . removeEventListener ( 'click' , interceptIframeInternalRedirect ) ;
6380 elem . addEventListener ( 'click' , interceptIframeInternalRedirect ) ;
6481 }
6582
83+ iframe . contentWindow ?. addEventListener ( 'blur' , handleFocus ) ;
84+ iframe . contentWindow ?. onbeforeunload = ( ) => {
85+ iframe . contentWindow ?. removeEventListener ( 'blur' , handleFocus ) ;
86+ } ;
87+
6688 if ( cssCode ) {
6789 const cssContainer = document . createElement ( 'style' ) ;
6890 // styles.type = 'text/css';
6991 cssContainer . innerText = cssCode ;
70- ref . current . contentDocument ?. head . appendChild ( cssContainer ) ;
92+ iframe . contentDocument ?. head . appendChild ( cssContainer ) ;
7193 }
94+
7295 handleResize ( ) ;
73- window . addEventListener ( 'resize' , handleResize ) ;
7496 }
75- } , [ cssCode , handleResize ] ) ;
97+ } , [ cssCode , setLoaded , handleResize , handleFocus ] ) ;
7698
7799 return (
78100 < iframe
79101 css = { styles . iframe }
80102 title = { name }
81103 frameBorder = "0"
82104 width = { width }
83- height = { html ? undefined : 20 }
84- ref = { ref }
105+ ref = { setIframe }
85106 className = { className }
86107 srcDoc = { html }
87108 onLoad = { onLoad }
88109 />
89110 ) ;
90- } ) ;
111+ } ;
91112
92113export {
93114 Iframe
0 commit comments