import React, { useRef, useEffect, useState, ReactNode, MouseEvent, FormEvent, KeyboardEvent, } from 'react'; import classNames from 'classnames'; import Icon from '../icon'; import { BaseProps } from '../_utils/props'; export type InputSizes = 'sm' | 'md' | 'lg'; export interface InputProps extends BaseProps { clearable?: boolean; prefix?: ReactNode; suffix?: ReactNode; value?: string; defaultValue?: string; onChange?: (value: any, event: FormEvent | MouseEvent) => void; onEnterPress?: (event: KeyboardEvent) => void; onKeyDown?: React.KeyboardEventHandler; // prevent covering keydown event by enter press size?: InputSizes; disabled?: boolean; [prop: string]: any; } const DEFAULT_MARGIN = 16; // 8px * 2 const Input: React.FC & { Group?: any; Addon?: any } = (props: InputProps) => { const { prefixCls = 'ty-input', size = 'md', disabled = false, clearable = false, defaultValue = '', prefix, suffix, onChange, onEnterPress, onKeyDown, className, style, ...otherProps } = props; const cls = classNames(prefixCls, className, `${prefixCls}_${size}`, { [`${prefixCls}_disabled`]: disabled, }); const prefixRef = useRef(null); const suffixRef = useRef(null); const [value, setValue] = useState('value' in props ? props.value : defaultValue); const [inputPadding, setInputPadding] = useState({ paddingLeft: '7px', paddingRight: '7px' }); const inputOnChange = (e: FormEvent) => { const val = e.currentTarget.value; !('value' in props) && setValue(val); onChange && onChange(e.currentTarget.value, e); }; const inputOnKeydown = (e: KeyboardEvent) => { if (e.keyCode === 13) { onEnterPress && onEnterPress(e); } onKeyDown && onKeyDown(e); }; const clearBtnOnClick = (e: MouseEvent) => { setValue(''); onChange && onChange('', e); }; const renderClearButton = (): React.ReactNode => { if (clearable && value && value.length > 0) { return ( ); } return null; }; useEffect(() => { const prefixWidth = prefixRef.current && prefixRef.current!.offsetWidth; const suffixWidth = suffixRef.current && suffixRef.current!.offsetWidth; const padding = { ...inputPadding }; if (prefixWidth) { padding.paddingLeft = prefixWidth + DEFAULT_MARGIN + 'px'; } if (suffixWidth) { padding.paddingRight = suffixWidth + DEFAULT_MARGIN + 'px'; } setInputPadding(padding); 'value' in props && setValue(props.value); }, [props.value]); return (
{prefix && (
{prefix}
)} {(suffix || clearable) && (
{renderClearButton()} {suffix}
)}
); }; export default Input;