Files
react/components/input/password.tsx
2020-04-28 11:31:52 +08:00

52 lines
1.6 KiB
TypeScript

import React, { useImperativeHandle, useMemo, useRef, useState } from 'react'
import withDefaults from '../utils/with-defaults'
import { Props, defaultProps } from './input-props'
import PasswordIcon from './password-icon'
import Input from './input'
interface PasswordProps extends Props {
hideToggle?: boolean
}
const passwordDefaultProps = {
...defaultProps,
hideToggle: false,
}
type NativeAttrs = Omit<React.InputHTMLAttributes<any>, keyof PasswordProps>
export type InputPasswordProps = PasswordProps & typeof passwordDefaultProps & NativeAttrs
const InputPassword = React.forwardRef<HTMLInputElement, React.PropsWithChildren<InputPasswordProps>>(({
hideToggle, children, ...props
}, ref: React.Ref<HTMLInputElement | null>) => {
const inputRef = useRef<HTMLInputElement>(null)
const [visible, setVisible] = useState<boolean>(false)
useImperativeHandle(ref, () => inputRef.current)
const iconClickHandler = () => {
setVisible(v => !v)
/* istanbul ignore next */
if (inputRef && inputRef.current) {
inputRef.current.focus()
}
}
const inputProps = useMemo(() => ({
...props,
ref: inputRef,
iconClickable: true,
onIconClick: iconClickHandler,
type: visible ? 'text' : 'password',
}), [props, iconClickHandler, visible, inputRef])
const icon = useMemo(() => {
if (hideToggle) return null
return <PasswordIcon visible={visible} />
}, [hideToggle, visible])
return (
<Input iconRight={icon} {...inputProps}>{children}</Input>
)
})
export default withDefaults(InputPassword, passwordDefaultProps)