common.tsx 1.5 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152
  1. import { forwardRef, useEffect, useRef } from 'react'
  2. import cn from '@/utils/classnames'
  3. type AutoHeightTextareaProps =
  4. & React.DetailedHTMLProps<React.TextareaHTMLAttributes<HTMLTextAreaElement>, HTMLTextAreaElement>
  5. & { outerClassName?: string }
  6. const AutoHeightTextarea = forwardRef<HTMLTextAreaElement, AutoHeightTextareaProps>(
  7. (
  8. {
  9. outerClassName,
  10. value,
  11. className,
  12. placeholder,
  13. autoFocus,
  14. disabled,
  15. ...rest
  16. },
  17. outRef,
  18. ) => {
  19. const innerRef = useRef<HTMLTextAreaElement>(null)
  20. const ref = outRef || innerRef
  21. useEffect(() => {
  22. if (autoFocus && !disabled && value) {
  23. if (typeof ref !== 'function') {
  24. ref.current?.setSelectionRange(`${value}`.length, `${value}`.length)
  25. ref.current?.focus()
  26. }
  27. }
  28. }, [autoFocus, disabled, ref])
  29. return (
  30. <div className={outerClassName}>
  31. <div className='relative'>
  32. <div className={cn(className, 'invisible whitespace-pre-wrap break-all')}>
  33. {!value ? placeholder : `${value}`.replace(/\n$/, '\n ')}
  34. </div>
  35. <textarea
  36. ref={ref}
  37. placeholder={placeholder}
  38. className={cn(className, 'disabled:bg-transparent absolute inset-0 outline-none border-none appearance-none resize-none w-full h-full')}
  39. value={value}
  40. disabled={disabled}
  41. {...rest}
  42. />
  43. </div>
  44. </div>
  45. )
  46. },
  47. )
  48. export default AutoHeightTextarea