fileOverview import classNames from 'classnames' ; import _ from 'lodash' ; import React , { ReactElement , forwardRef , cloneElement , useState , useImperativeHandle , useRef , useEffect } from 'react' ; import ReactResizeDetector from 'react-resize-detector/build/withPolyfill' ; import { isPercent } from '../util/DataUtils' ; import { warn } from '../util/LogUtils' ; export interface Props { aspect ? : number ; width ? : string | number ; height ? : string | number ; minWidth ? : string | number ; minHeight ? : string | number ; maxHeight ? : number ; children : ReactElement ; debounce ? : number ; id ? : string | number ; className ? : string | number ; } interface State { containerWidth : number ; containerHeight : number ; } export const ResponsiveContainer = forwardRef ( ( { aspect , width = '100%' , height = '100%' , minWidth , minHeight , maxHeight , children , debounce = 0 , id , className , } , ref ) => { const [ sizes , setSizes ] = useState < State > ( { containerWidth : - 1 , containerHeight : - 1 , } ) ; const containerRef = useRef < HTMLDivElement > ( null ) ; useImperativeHandle ( ref , ( ) => containerRef , [ containerRef ] ) ; const [ mounted , setMounted ] = useState < boolean > ( false ) ; const getContainerSize = ( ) => { if ( ! containerRef . current ) { return null ; } return { containerWidth : containerRef . current . clientWidth , containerHeight : containerRef . current . clientHeight , } ; } ; const updateDimensionsImmediate = ( ) => { if ( ! mounted ) { return ; } const newSize = getContainerSize ( ) ; if ( newSize ) { const { containerWidth : oldWidth , containerHeight : oldHeight } = sizes ; const { containerWidth , containerHeight } = newSize ; if ( containerWidth !== oldWidth || containerHeight !== oldHeight ) { setSizes ( { containerWidth , containerHeight } ) ; } } } ; const handleResize = debounce > 0 ? _ . debounce ( updateDimensionsImmediate , debounce ) : updateDimensionsImmediate ; const renderChart = ( ) => { const { containerWidth , containerHeight } = sizes ; if ( containerWidth < 0 || containerHeight < 0 ) { return null ; } warn ( isPercent ( width ) || isPercent ( height ) , `The width(%s) and height(%s) are both fixed numbers,
       maybe you don't need to use a ResponsiveContainer.` , width , height ) ; warn ( ! aspect || aspect > 0 , 'The aspect(%s) must be greater than zero.' , aspect ) ; let calculatedWidth = isPercent ( width ) ? containerWidth : ( width as number ) ; let calculatedHeight = isPercent ( height ) ? containerHeight : ( height as number ) ; if ( aspect && aspect > 0 ) { if ( calculatedWidth ) { calculatedHeight = calculatedWidth / aspect ; } else if ( calculatedHeight ) { calculatedWidth = calculatedHeight * aspect ; } if ( maxHeight && calculatedHeight > maxHeight ) { calculatedHeight = maxHeight ; } } warn ( calculatedWidth > 0 || calculatedHeight > 0 , `The width(%s) and height(%s) of chart should be greater than 0,
       please check the style of container, or the props width(%s) and height(%s),
       or add a minWidth(%s) or minHeight(%s) or use aspect(%s) to control the
       height and width.` , calculatedWidth , calculatedHeight , width , height , minWidth , minHeight , aspect ) ; return cloneElement ( children , { width : calculatedWidth , height : calculatedHeight , } ) ; } ; useEffect ( ( ) => { if ( mounted ) { const size = getContainerSize ( ) ; if ( size ) { setSizes ( size ) ; } } } , [ mounted ] ) ; useEffect ( ( ) => { setMounted ( true ) ; } , [ ] ) ; const style = { width , height , minWidth , minHeight , maxHeight } ; return ( < ReactResizeDetector handleWidth handleHeight onResize = { handleResize } targetRef = { containerRef } > < div { ... ( id != null ? { id : `${ id }` } : { } ) } className = { classNames ( 'recharts-responsive-container' , className ) } style = { style } ref = { containerRef } > { renderChart ( ) } < /div> < /ReactResizeDetector>); } ) ;