import React, { forwardRef, useCallback, useEffect, useRef, useState, } from "react"; import classnames from "classnames"; import { ControlsProps } from "../../common/controls.type"; import { useCombinedRefs } from "../../hooks/combinedrefs"; type P = Omit, "size"> & ControlsProps; interface Props extends P { value?: string; autosize?: boolean | { minRows?: number; maxRows?: number }; } const Textarea = forwardRef( ( { value, onChange, disabled, success, warning, error, size = "default", autosize = { minRows: 2, maxRows: 5 }, ...restProps }, ref ) => { const textareaElement = useRef(null); const combinedRef = useCombinedRefs( textareaElement, ref ); useEffect(() => { if (textareaElement.current) { updateSize(); } }, []); useEffect(() => { updateSize(); }, [value, autosize, textareaElement]); const handleChange = (e: React.ChangeEvent) => { if (onChange) { onChange(e); } updateSize(); }; const updateSize = () => { if (!autosize) { return; } if (!textareaElement.current) { return; } setupHeightLimits(); const styles = getComputedStyle(textareaElement.current); const borderTopWidth = parseInt(styles.borderTopWidth); const borderBottomWidth = parseInt(styles.borderBottomWidth); const borderVeritalWidth = borderTopWidth + borderBottomWidth; textareaElement.current.style.height = "0"; textareaElement.current.style.height = `${ textareaElement.current.scrollHeight + borderVeritalWidth }px`; }; const setupHeightLimits = () => { if (!autosize || typeof autosize == "boolean") { return; } if (!textareaElement.current) { return; } const styles = getComputedStyle(textareaElement.current); const lineHeight = parseInt(styles.lineHeight); const borderTopWidth = parseInt(styles.borderTopWidth); const borderBottomWidth = parseInt(styles.borderBottomWidth); const borderVeritalWidth = borderTopWidth + borderBottomWidth; const paddingTop = parseInt(styles.paddingTop); const paddingBottom = parseInt(styles.paddingBottom); const verticalPadding = paddingTop + paddingBottom; let { minRows, maxRows } = autosize; if (minRows) { textareaElement.current.style.minHeight = `${ lineHeight * minRows + verticalPadding + borderVeritalWidth }px`; } if (maxRows) { textareaElement.current.style.maxHeight = `${ lineHeight * maxRows + verticalPadding + borderVeritalWidth }px`; } }; return ( ); } ); export default Textarea;