import * as React from 'react' ; import calculateNodeHeight from './calculateNodeHeight' ; import getSizingData , { SizingData } from './getSizingData' ; import { useComposedRef , useWindowResizeListener } from './hooks' ; import { noop } from './utils' ; type TextareaProps = React . TextareaHTMLAttributes < HTMLTextAreaElement > ; type Style = Omit < NonNullable < TextareaProps [ 'style' ] > , 'maxHeight' | 'minHeight' > & { height ? : number ; } ; export type TextareaHeightChangeMeta = { rowHeight : number ; } ; export interface TextareaAutosizeProps extends Omit < TextareaProps , 'style' > { maxRows ? : number ; minRows ? : number ; onHeightChange ? : ( height : number , meta : TextareaHeightChangeMeta ) => void ; cacheMeasurements ? : boolean ; style ? : Style ; } const TextareaAutosize = ( { cacheMeasurements , maxRows , minRows , onChange = noop , onHeightChange = noop , ... props } , userRef ) => { if ( process . env . NODE_ENV !== 'production' && props . style ) { if ( 'maxHeight' in props . style ) { throw new Error ( 'Using `style.maxHeight` for <TextareaAutosize/> is not supported. Please use `maxRows`.' ) ; } if ( 'minHeight' in props . style ) { throw new Error ( 'Using `style.minHeight` for <TextareaAutosize/> is not supported. Please use `minRows`.' ) ; } } const isControlled = props . value !== undefined ; const libRef = React . useRef < HTMLTextAreaElement | null > ( null ) ; const ref = useComposedRef ( libRef , userRef ) ; const heightRef = React . useRef ( 0 ) ; const measurementsCacheRef = React . useRef < SizingData > ( ) ; const resizeTextarea = ( ) => { const node = libRef . current ! ; const nodeSizingData = cacheMeasurements && measurementsCacheRef . current ? measurementsCacheRef . current : getSizingData ( node ) ; if ( ! nodeSizingData ) { return ; } measurementsCacheRef . current = nodeSizingData ; const [ height , rowHeight ] = calculateNodeHeight ( nodeSizingData , node . value || node . placeholder || 'x' , minRows , maxRows ) ; if ( heightRef . current !== height ) { heightRef . current = height ; node . style . setProperty ( 'height' , `${ height }px` , 'important' ) ; onHeightChange ( height , { rowHeight } ) ; } } ; const handleChange = ( event ) => { if ( ! isControlled ) { resizeTextarea ( ) ; } onChange ( event ) ; } ; if ( typeof document !== 'undefined' ) { React . useLayoutEffect ( resizeTextarea ) ; useWindowResizeListener ( resizeTextarea ) ; } return < textarea { ... props } onChange = { handleChange } ref = { ref } / > ; } ; export default React . forwardRef ( TextareaAutosize ) ;