mirror of
https://github.com/overleaf/overleaf.git
synced 2024-11-21 20:47:08 -05:00
98a847ae75
React review panel: fix regression that made animation jerky on Chrome GitOrigin-RevId: c1d9fa00d478fa71d94ff705ddfcc12bab0b2767
78 lines
2 KiB
TypeScript
78 lines
2 KiB
TypeScript
import { useEffect, useRef } from 'react'
|
|
import { callFnsInSequence } from '../../utils/functions'
|
|
import { MergeAndOverride } from '../../../../types/utils'
|
|
|
|
export const resetHeight = (
|
|
e:
|
|
| React.ChangeEvent<HTMLTextAreaElement>
|
|
| React.KeyboardEvent<HTMLTextAreaElement>
|
|
) => {
|
|
const el = e.target as HTMLTextAreaElement
|
|
|
|
window.requestAnimationFrame(() => {
|
|
const curHeight = el.offsetHeight
|
|
const fitHeight = el.scrollHeight
|
|
// clear height if text area is empty
|
|
if (!el.value.length) {
|
|
el.style.removeProperty('height')
|
|
}
|
|
// otherwise expand to fit text
|
|
else if (fitHeight > curHeight) {
|
|
el.style.height = `${fitHeight}px`
|
|
}
|
|
})
|
|
}
|
|
|
|
type AutoExpandingTextAreaProps = MergeAndOverride<
|
|
React.ComponentProps<'textarea'>,
|
|
{
|
|
onResize?: () => void
|
|
}
|
|
>
|
|
|
|
function AutoExpandingTextArea({
|
|
onChange,
|
|
onResize,
|
|
...rest
|
|
}: AutoExpandingTextAreaProps) {
|
|
const ref = useRef<HTMLTextAreaElement>(null)
|
|
const isFirstResizeRef = useRef(true)
|
|
|
|
useEffect(() => {
|
|
if (!ref.current || !onResize || !('ResizeObserver' in window)) {
|
|
return
|
|
}
|
|
|
|
const resizeObserver = new ResizeObserver(() => {
|
|
// Ignore the resize that is triggered when the element is first
|
|
// inserted into the DOM
|
|
if (isFirstResizeRef.current) {
|
|
isFirstResizeRef.current = false
|
|
} else {
|
|
// Prevent errors like "ResizeObserver loop completed with undelivered
|
|
// notifications" that occur if onResize does something complicated.
|
|
// The cost of this is that onResize lags one frame behind, but it's
|
|
// unlikely to matter.
|
|
|
|
// Wrap onResize to prevent extra parameters being passed
|
|
window.requestAnimationFrame(() => onResize())
|
|
}
|
|
})
|
|
|
|
resizeObserver.observe(ref.current)
|
|
|
|
return () => {
|
|
resizeObserver.disconnect()
|
|
}
|
|
}, [onResize])
|
|
|
|
return (
|
|
<textarea
|
|
onChange={callFnsInSequence(onChange, resetHeight)}
|
|
{...rest}
|
|
ref={ref}
|
|
/>
|
|
)
|
|
}
|
|
|
|
export default AutoExpandingTextArea
|