Newer
Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
import React from 'react'
import styled from 'styled-components'
import { BaseProps } from '../types'
type Props = BaseProps &
Omit<React.InputHTMLAttributes<HTMLInputElement>, 'onChange'> & {
onChange: (value: string) => void
}
const AutosizeInput: React.FC<Props> = ({
className,
value,
placeholder,
onChange,
...rest
}) => {
const [content, setContent] = React.useState<string>(value?.toString() || '')
const [width, setWidth] = React.useState(0)
const span = React.useRef<HTMLSpanElement>(null)
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) =>
setContent(e.currentTarget.value)
React.useEffect(() => {
setWidth(span.current?.offsetWidth || 0)
onChange(content)
}, [content])
return (
<div className={className}>
<span className='spacer' ref={span}>
{content || placeholder}
</span>
<input
value={content}
placeholder={placeholder}
style={{ width }}
onChange={handleChange}
{...rest}
/>
<span className='border' />
</div>
)
}
export default styled(AutosizeInput)`
display: inline-block;
position: relative;
input {
all: unset;
position: relative;
max-width: 16rem;
border-radius: 0.2rem 0.2rem 0 0;
transition: background var(--transition);
}
.spacer {
opacity: 0;
position: absolute;
white-space: nowrap;
pointer-events: none;
}
.border {
position: absolute;
right: 0;
bottom: 0;
left: 0;
width: 100%;
height: 1px;