/* eslint-disable no-param-reassign */ import { RefObject, useLayoutEffect, useState } from 'react'; const getComputedStyles = (node?: HTMLTextAreaElement) => { if (!node) { return null; } const refStyle = window.getComputedStyle(node); if (refStyle.paddingTop && refStyle.lineHeight && refStyle.fontSize) { const fontSize = parseInt(refStyle.fontSize, 10); const lineHeightPx = parseFloat(refStyle.lineHeight); return { padding: parseInt(refStyle.paddingTop, 10), lineHeight: ((lineHeightPx / fontSize) - 0.05) * fontSize }; } return null; }; type DynamicRowsInput = { min?: number; max?: number; value?: string; enable?: boolean; } export const useDynamicRows = (node: RefObject, inputs: DynamicRowsInput) => { const [ rows, setRows ] = useState(inputs.min); useLayoutEffect( () => { if (!node.current || !inputs.enable) { return; } const style = getComputedStyles(node.current); if (!style) { return; } const previousRows = node.current.rows; node.current.rows = inputs.min || 3; const currentRows = Math.round((node.current.scrollHeight - (style.padding * 2)) / style.lineHeight); if (currentRows === previousRows) { node.current.rows = currentRows; } if (inputs.max) { if (currentRows >= inputs.max) { node.current.rows = inputs.max; node.current.scrollTop = node.current.scrollHeight; } setRows(currentRows < inputs.max ? currentRows : inputs.max); } else { setRows(currentRows); } }, [ inputs.max, inputs.min, inputs.value, inputs.enable, node ] ); return rows; };