import React , { Component } from 'react' ; export interface FitTextProps { compressor ? : number ; minFontSize ? : number ; maxFontSize ? : number ; children : React . ReactNode ; } class FitText extends Component < FitTextProps > { private updateQueued : boolean = false ; private _childRef : React . ReactNode ; private nodes = new Map ( ) ; static defaultProps = { compressor : 1 , minFontSize : Number . NEGATIVE_INFINITY , maxFontSize : Number . POSITIVE_INFINITY } ; componentWillMount ( ) { if ( ! this . updateQueued ) { window . requestAnimationFrame ( this . handleBodyResize ) ; } window . addEventListener ( 'resize' , this . handleBodyResize ) ; window . addEventListener ( 'load' , this . handleBodyResize ) ; } componentDidUpdate ( ) { this . handleBodyResize ( ) ; } componentWillUnmount ( ) { window . removeEventListener ( 'resize' , this . handleBodyResize ) ; window . removeEventListener ( 'load' , this . handleBodyResize ) ; } updateElementStyle = ( element , options , width ) => { element . style . fontSize = `${ Math . min ( Math . max ( width / ( options . compressor * 10 ) , options . minFontSize ) , options . maxFontSize ) }px` ; } ; handleBodyResize = ( ) => { this . updateQueued = true ; const widths = [ ] ; this . nodes . forEach ( ( options , element ) => { widths . push ( element . offsetWidth ) ; } ) ; let i = 0 ; this . nodes . forEach ( ( options , element ) => { this . updateElementStyle ( element , options , widths [ i ] ) ; i += 1 ; } ) ; } ; _renderChildren = ( ) => { const { children } = this . props ; return React . Children . map ( children , ( child ) => { return React . cloneElement ( child as any , { ref : ( c ) => { if ( c ) { this . nodes . set ( c , this . props ) ; } this . _childRef = c ; } } ) ; } ) ; } ; render ( ) { return this . _renderChildren ( ) [ 0 ] ; } } export default FitText ;