import * as React from 'react' import { cn } from '@/lib/utils' type TextareaProps = React.TextareaHTMLAttributes & { className?: string value?: string onChange?: (e: React.ChangeEvent) => void } const MIN_HEIGHT = 40 const MAX_HEIGHT = 96 const TextArea = React.forwardRef( ({ className, value, onChange, ...props }, forwardedRef) => { const [showScroll, setShowScroll] = React.useState(false) const textareaRef = React.useRef(null) const adjustHeight = React.useCallback(() => { const textarea = textareaRef.current if (!textarea) return textarea.style.height = `${MIN_HEIGHT}px` const { scrollHeight } = textarea const newHeight = Math.min(Math.max(scrollHeight, MIN_HEIGHT), MAX_HEIGHT) textarea.style.height = `${newHeight}px` setShowScroll(scrollHeight > MAX_HEIGHT) }, []) const handleChange = React.useCallback( (e: React.ChangeEvent) => { const cursorPosition = e.target.selectionStart onChange?.(e) requestAnimationFrame(() => { adjustHeight() if (textareaRef.current) { textareaRef.current.setSelectionRange( cursorPosition, cursorPosition ) } }) }, [onChange, adjustHeight] ) const handleRef = React.useCallback( (node: HTMLTextAreaElement | null) => { const ref = forwardedRef as | React.MutableRefObject | ((instance: HTMLTextAreaElement | null) => void) | null if (typeof ref === 'function') { ref(node) } else if (ref) { ref.current = node } textareaRef.current = node }, [forwardedRef] ) React.useEffect(() => { if (textareaRef.current) { adjustHeight() } }, [value, adjustHeight]) return (