diff --git a/docs/pages/experiments/textarea-ro.tsx b/docs/pages/experiments/textarea-ro.tsx new file mode 100644 index 00000000000000..c878cd2d223fba --- /dev/null +++ b/docs/pages/experiments/textarea-ro.tsx @@ -0,0 +1,32 @@ +import * as React from 'react'; +import TextField from '@mui/material/TextField'; + +export default function App() { + const [value, setValue] = React.useState( + 'some long text that makes the input start with multiple rows', + ); + + const wrapperRef: React.MutableRefObject = + React.useRef(null); + + React.useEffect(() => { + setTimeout(() => { + if (wrapperRef.current != null) { + wrapperRef.current.style.width = '200px'; + } + }, 5000); + }, []); + + return ( +
+
+ setValue(ev.target.value)} + /> +
+
+ ); +} diff --git a/docs/pages/experiments/textarea-ro2.js b/docs/pages/experiments/textarea-ro2.js new file mode 100644 index 00000000000000..e60b199b494043 --- /dev/null +++ b/docs/pages/experiments/textarea-ro2.js @@ -0,0 +1,29 @@ +import TextField from '@mui/material/TextField'; +import { useState, useRef, useEffect } from 'react'; + +export default function App() { + const [value, setValue] = useState( + 'some long text that makes the input start with multiple rows', + ); + + const wrapper = useRef(); + + useEffect(() => { + setTimeout(() => { + wrapper.current.style.width = '200px'; + }, 2000); + }, []); + + return ( +
+
+ setValue(e.target.value)} + /> +
+
+ ); +} diff --git a/packages/mui-material/src/TextareaAutosize/TextareaAutosize.tsx b/packages/mui-material/src/TextareaAutosize/TextareaAutosize.tsx index 37529fa37873c5..54a020481f78f3 100644 --- a/packages/mui-material/src/TextareaAutosize/TextareaAutosize.tsx +++ b/packages/mui-material/src/TextareaAutosize/TextareaAutosize.tsx @@ -45,6 +45,8 @@ function isEmpty(obj: TextareaStyles) { ); } +const supportsResizeObserver = typeof ResizeObserver !== 'undefined'; + /** * * Demos: @@ -139,21 +141,22 @@ const TextareaAutosize = React.forwardRef(function TextareaAutosize( input.style.overflow = textareaStyles.overflowing ? 'hidden' : ''; }, [calculateTextareaStyles]); + const frameRef = React.useRef(-1); + useEnhancedEffect(() => { - const handleResize = () => { + function handleResize() { syncHeight(); - }; + } // Workaround a "ResizeObserver loop completed with undelivered notifications" error // in test. // Note that we might need to use this logic in production per https://github.com/WICG/resize-observer/issues/38 // Also see https://github.com/mui/mui-x/issues/8733 - let rAF: any; - const rAFHandleResize = () => { - cancelAnimationFrame(rAF); - rAF = requestAnimationFrame(() => { - handleResize(); - }); - }; + // const rAFHandleResize = () => { + // cancelAnimationFrame(frameRef.current); + // frameRef.current = requestAnimationFrame(() => { + // handleResize(); + // }); + // }; const debounceHandleResize = debounce(handleResize); const input = inputRef.current!; const containerWindow = ownerWindow(input); @@ -162,16 +165,22 @@ const TextareaAutosize = React.forwardRef(function TextareaAutosize( let resizeObserver: ResizeObserver; - if (typeof ResizeObserver !== 'undefined') { - resizeObserver = new ResizeObserver( - process.env.NODE_ENV === 'test' ? rAFHandleResize : handleResize, - ); + if (supportsResizeObserver) { + resizeObserver = new ResizeObserver(([firstEntry]) => { + if (firstEntry && firstEntry.target === input) { + resizeObserver.unobserve(input); + cancelAnimationFrame(frameRef.current); + frameRef.current = requestAnimationFrame(() => { + resizeObserver.observe(input); + }); + } + }); resizeObserver.observe(input); } return () => { debounceHandleResize.clear(); - cancelAnimationFrame(rAF); + cancelAnimationFrame(frameRef.current); containerWindow.removeEventListener('resize', debounceHandleResize); if (resizeObserver) { resizeObserver.disconnect();