12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788 |
- // Reference to https://github.com/andreypopp/react-textarea-autosize/
- let hiddenTextarea: any = null;
- const HIDDEN_TEXTAREA_STYLE = {
- 'min-height': '0',
- 'max-height': 'none',
- height: '0',
- visibility: 'hidden',
- overflow: 'hidden',
- position: 'absolute',
- 'z-index': '-1000',
- top: '0',
- right: '0',
- };
- const forceHiddenStyles = (node: any) => {
- Object.keys(HIDDEN_TEXTAREA_STYLE).forEach(key => {
- node.style.setProperty(
- key,
- HIDDEN_TEXTAREA_STYLE[key],
- 'important'
- );
- });
- };
- const getContentHeight = (
- node: any,
- sizingData: any
- ) => {
- const height = node.scrollHeight;
- if (sizingData.sizingStyle.boxSizing === 'border-box') {
- // border-box: add border, since height = content + padding + border
- return height + sizingData.borderSize;
- }
- // remove padding, since height = content
- return height - sizingData.paddingSize;
- };
- export default function calculateNodeHeight(
- sizingData: any,
- value: string,
- minRows = 1,
- maxRows = Infinity
- ) {
- if (!hiddenTextarea) {
- hiddenTextarea = document.createElement('textarea');
- hiddenTextarea.setAttribute('tab-index', '-1');
- hiddenTextarea.setAttribute('aria-hidden', 'true');
- forceHiddenStyles(hiddenTextarea);
- }
- if (hiddenTextarea.parentNode === null) {
- document.body.appendChild(hiddenTextarea);
- }
- const { paddingSize, borderSize, sizingStyle } = sizingData;
- const { boxSizing } = sizingStyle;
- Object.keys(sizingStyle).forEach(key => {
- hiddenTextarea.style[key] = sizingStyle[key];
- });
- forceHiddenStyles(hiddenTextarea);
- hiddenTextarea.value = value;
- let height = getContentHeight(hiddenTextarea, sizingData);
- // measure height of a textarea with a single row
- hiddenTextarea.value = 'x';
- // calc single row need to remove padding and border to avoid duplicated calc
- const rowHeight = getContentHeight(hiddenTextarea, sizingData) - paddingSize - borderSize;
- let minHeight = rowHeight * minRows;
- if (boxSizing === 'border-box') {
- minHeight = minHeight + paddingSize + borderSize;
- }
- height = Math.max(minHeight, height);
- let maxHeight = rowHeight * maxRows;
- if (boxSizing === 'border-box') {
- maxHeight = maxHeight + paddingSize + borderSize;
- }
- height = Math.min(maxHeight, height);
- return height;
- }
|