mirror of
https://github.com/langgenius/webapp-conversation.git
synced 2025-12-08 17:32:27 +08:00
- Replace .eslintrc.json with eslint.config.mjs - Simplify configuration using @antfu/eslint-config - Add necessary ESLint plugin dependencies - Disable overly strict style rules - Set package.json type to module for ESM support - Fix ESLint disable comment format 🤖 Generated with [Claude Code](https://claude.ai/code) Co-Authored-By: Claude <noreply@anthropic.com>
72 lines
1.9 KiB
TypeScript
72 lines
1.9 KiB
TypeScript
import { forwardRef, useEffect, useRef } from 'react'
|
|
import cn from 'classnames'
|
|
|
|
interface IProps {
|
|
placeholder?: string
|
|
value: string
|
|
onChange: (e: React.ChangeEvent<HTMLTextAreaElement>) => void
|
|
className?: string
|
|
minHeight?: number
|
|
maxHeight?: number
|
|
autoFocus?: boolean
|
|
controlFocus?: number
|
|
onKeyDown?: (e: React.KeyboardEvent<HTMLTextAreaElement>) => void
|
|
onKeyUp?: (e: React.KeyboardEvent<HTMLTextAreaElement>) => void
|
|
}
|
|
|
|
const AutoHeightTextarea = forwardRef(
|
|
(
|
|
{ value, onChange, placeholder, className, minHeight = 36, maxHeight = 96, autoFocus, controlFocus, onKeyDown, onKeyUp }: IProps,
|
|
outerRef: any,
|
|
) => {
|
|
// eslint-disable-next-line react-hooks/rules-of-hooks
|
|
const ref = outerRef || useRef<HTMLTextAreaElement>(null)
|
|
|
|
const doFocus = () => {
|
|
if (ref.current) {
|
|
ref.current.setSelectionRange(value.length, value.length)
|
|
ref.current.focus()
|
|
return true
|
|
}
|
|
return false
|
|
}
|
|
|
|
const focus = () => {
|
|
if (!doFocus()) {
|
|
let hasFocus = false
|
|
const runId = setInterval(() => {
|
|
hasFocus = doFocus()
|
|
if (hasFocus) { clearInterval(runId) }
|
|
}, 100)
|
|
}
|
|
}
|
|
|
|
useEffect(() => {
|
|
if (autoFocus) { focus() }
|
|
}, [])
|
|
useEffect(() => {
|
|
if (controlFocus) { focus() }
|
|
}, [controlFocus])
|
|
|
|
return (
|
|
<div className='relative'>
|
|
<div className={cn(className, 'invisible whitespace-pre-wrap break-all overflow-y-auto')} style={{ minHeight, maxHeight }}>
|
|
{!value ? placeholder : value.replace(/\n$/, '\n ')}
|
|
</div>
|
|
<textarea
|
|
ref={ref}
|
|
autoFocus={autoFocus}
|
|
className={cn(className, 'absolute inset-0 resize-none overflow-hidden')}
|
|
placeholder={placeholder}
|
|
onChange={onChange}
|
|
onKeyDown={onKeyDown}
|
|
onKeyUp={onKeyUp}
|
|
value={value}
|
|
/>
|
|
</div>
|
|
)
|
|
},
|
|
)
|
|
|
|
export default AutoHeightTextarea
|