1- import React from 'react' ;
2- import { createRoot } from 'react-dom/client' ;
3- import PropTypes from 'prop-types' ;
1+ import React , { PropsWithChildren } from 'react' ;
2+ import { createRoot , Root } from 'react-dom/client' ;
43
54const DEFAULT_OPTIONS = {
65 toolbar : 'no' ,
@@ -12,44 +11,47 @@ const DEFAULT_OPTIONS = {
1211 resizable : 'yes' ,
1312 width : 500 ,
1413 height : 400 ,
15- top : ( o , w ) => ( w . innerHeight - o . height ) / 2 + w . screenY ,
16- left : ( o , w ) => ( w . innerWidth - o . width ) / 2 + w . screenX
14+ top : ( o : any , w : any ) => ( w . innerHeight - o . height ) / 2 + w . screenY ,
15+ left : ( o : any , w : any ) => ( w . innerWidth - o . width ) / 2 + w . screenX ,
1716} ;
1817
1918const ABOUT_BLANK = 'about:blank' ;
2019
20+ interface PopoutWindowProps extends PropsWithChildren < any > {
21+ options : object ;
22+ url : string ;
23+ containerId : string ;
24+ containerClassName ?: string ;
25+ onError : ( ) => void ;
26+ window ?: Window ;
27+ title ?: string ;
28+ }
29+
30+ interface PopoutWindowState {
31+ popoutWindow : Window | null ;
32+ container : HTMLDivElement | null ;
33+ openedWindowComponent : React . Component | null ;
34+ }
35+
2136/**
2237 * @class PopoutWindow
2338 */
24- export default class PopoutWindow extends React . Component {
39+ export default class PopoutWindow extends React . Component < PopoutWindowProps , PopoutWindowState > {
40+ private interval ! : number ;
41+ private root ! : Root ;
42+
2543 static defaultProps = {
2644 url : ABOUT_BLANK ,
2745 containerId : 'popout-content-container' ,
2846 containerClassName : '' ,
29- onError : ( ) => { }
30- } ;
31-
32- /**
33- *
34- * @type {{title: *, url: *, onClosing: *, options: *, window: *, containerId: *} }
35- */
36- static propTypes = {
37- title : PropTypes . string . isRequired ,
38- url : PropTypes . string ,
39- onClosing : PropTypes . func ,
40- options : PropTypes . object ,
41- window : PropTypes . object ,
42- containerId : PropTypes . string ,
43- containerClassName : PropTypes . string ,
44- children : PropTypes . oneOfType ( [ PropTypes . element , PropTypes . func ] ) ,
45- onError : PropTypes . func
47+ onError : ( ) => { } ,
4648 } ;
4749
4850 /**
4951 * @constructs PopoutWindow
5052 * @param props
5153 */
52- constructor ( props ) {
54+ constructor ( props : PopoutWindowProps ) {
5355 super ( props ) ;
5456
5557 this . mainWindowClosed = this . mainWindowClosed . bind ( this ) ;
@@ -59,21 +61,24 @@ export default class PopoutWindow extends React.Component {
5961 this . state = {
6062 openedWindowComponent : null ,
6163 popoutWindow : null ,
62- container : null
64+ container : null ,
6365 } ;
6466 }
6567
66- createOptions ( ownerWindow ) {
68+ createOptions ( ownerWindow : Window ) {
6769 const mergedOptions = Object . assign ( { } , DEFAULT_OPTIONS , this . props . options ) ;
6870
6971 return Object . keys ( mergedOptions )
7072 . map (
71- key =>
73+ ( key ) =>
7274 key +
7375 '=' +
76+ // @ts -ignore
7477 ( typeof mergedOptions [ key ] === 'function'
75- ? mergedOptions [ key ] . call ( this , mergedOptions , ownerWindow )
76- : mergedOptions [ key ] )
78+ ? // @ts -ignore
79+ mergedOptions [ key ] . call ( this , mergedOptions , ownerWindow )
80+ : // @ts -ignore
81+ mergedOptions [ key ] ) ,
7782 )
7883 . join ( ',' ) ;
7984 }
@@ -90,44 +95,45 @@ export default class PopoutWindow extends React.Component {
9095 }
9196 }
9297
93- componentWillReceiveProps ( newProps ) {
98+ componentWillReceiveProps ( newProps : PopoutWindowProps ) {
9499 if ( newProps . title !== this . props . title && this . state . popoutWindow ) {
95- this . state . popoutWindow . document . title = newProps . title ;
100+ this . state . popoutWindow . document . title = newProps . title ! ;
96101 }
97102 }
98103
99104 componentDidUpdate ( ) {
100- this . renderToContainer ( this . state . container , this . state . popoutWindow , this . props . children ) ;
105+ this . renderToContainer ( this . state . container ! , this . state . popoutWindow ! , this . props . children ) ;
101106 }
102107
103108 componentWillUnmount ( ) {
104109 this . mainWindowClosed ( ) ;
105110 }
106111
107- popoutWindowLoaded ( popoutWindow ) {
112+ popoutWindowLoaded ( popoutWindow : Window ) {
108113 if ( ! this . state . container ) {
109114 // Popout window is passed from openPopoutWindow if no url is specified.
110115 // In this case this.state.popoutWindow will not yet be set, so use the argument.
111116 popoutWindow = this . state . popoutWindow || popoutWindow ;
112- popoutWindow . document . title = this . props . title ;
117+ popoutWindow . document . title = this . props . title ! ;
113118 let container = popoutWindow . document . createElement ( 'div' ) ;
114119 container . id = this . props . containerId ;
115- container . className = this . props . containerClassName ;
120+ container . className = this . props . containerClassName ! ;
116121 popoutWindow . document . body . appendChild ( container ) ;
117122
118123 this . setState ( { container } ) ;
119124 this . renderToContainer ( container , popoutWindow , this . props . children ) ;
120125 }
121126 }
122127
123- openPopoutWindow ( ownerWindow ) {
128+ openPopoutWindow ( ownerWindow : Window ) {
124129 const popoutWindow = ownerWindow . open ( this . props . url , this . props . name || this . props . title , this . createOptions ( ownerWindow ) ) ;
125130 if ( ! popoutWindow ) {
126131 this . props . onError ( ) ;
127132 return ;
128133 }
129134 this . setState ( { popoutWindow } ) ;
130135
136+ // @ts -ignore
131137 popoutWindow . addEventListener ( 'load' , this . popoutWindowLoaded ) ;
132138 popoutWindow . addEventListener ( 'unload' , this . popoutWindowUnloading ) ;
133139
@@ -153,8 +159,8 @@ export default class PopoutWindow extends React.Component {
153159 *
154160 * @param popoutWindow
155161 */
156- checkForPopoutWindowClosure ( popoutWindow ) {
157- this . interval = setInterval ( ( ) => {
162+ checkForPopoutWindowClosure ( popoutWindow : Window ) {
163+ this . interval = window . setInterval ( ( ) => {
158164 if ( popoutWindow . closed ) {
159165 clearInterval ( this . interval ) ;
160166 this . props . onClosing && this . props . onClosing ( popoutWindow ) ;
@@ -170,18 +176,15 @@ export default class PopoutWindow extends React.Component {
170176 popoutWindowUnloading ( ) {
171177 if ( this . state . container ) {
172178 clearInterval ( this . interval ) ;
173- this . root . unmount ( this . state . container ) ;
179+ this . root . unmount ( ) ;
174180 this . props . onClosing && this . props . onClosing ( this . state . popoutWindow ) ;
175181 }
176182 }
177183
178- renderToContainer ( container , popoutWindow , children ) {
184+ renderToContainer ( container : HTMLDivElement , popoutWindow : Window , children : React . ReactNode | ( ( window : Window ) => React . ReactNode ) ) {
179185 // For SSR we might get updated but there will be no container.
180186 if ( container ) {
181- let renderedComponent = children ;
182- if ( typeof children === 'function' ) {
183- renderedComponent = children ( popoutWindow ) ;
184- }
187+ const renderedComponent = typeof children === 'function' ? children ( popoutWindow ) : children ;
185188
186189 if ( ! this . root ) {
187190 this . root = createRoot ( container ) ;
0 commit comments