import { ConfigProvider, Input as OldInput, InputProps } from 'antd'; import React, { ChangeEvent, ReactNode, useContext, useEffect, useMemo, useState, } from 'react'; import './index.less'; import classNames from 'classnames'; import { SearchProps } from 'antd/lib/input/Search'; import { Icon } from '../Icon'; import { PasswordProps } from 'antd/lib/input/Password'; import { AOP } from '../utils/AOP'; import { TextAreaProps } from 'antd/lib/input/TextArea'; import { useTheme } from '@btri-ui/hooks'; interface ExtraProps { vertify?: VertifyProps; textAlign?: 'left' | 'right' | 'center'; } interface VertifyProps { status: 'success' | 'error' | 'warning'; message?: string; } const Input = (props: InputProps & ExtraProps) => { const { addonAfter, addonBefore, prefix, suffix, allowClear, value, showCount, maxLength, vertify, textAlign = 'left', } = props; // 为了与 antd 的生态保持兼容性,我们要求必须要使用 `.@{ant-prefix}` 变量来生成类名 const { getPrefixCls } = useContext(ConfigProvider.ConfigContext); const prefixCls = getPrefixCls('btri-input'); const status = vertify?.status; const message = vertify?.message; const statusClassName = useMemo(() => { let name = `${prefixCls}`; if (props.size === 'large') { name = `${name}-lg`; } else if (props.size === 'small') { name = `${name}-sm`; } return name; }, [props.size]); const inputIconType = useMemo(() => { let type = `${prefixCls}`; if (addonAfter || addonBefore) { type = `${type}-addon`; } if (prefix || suffix || allowClear || showCount || maxLength) { type = `${type}-pureIcon`; } return type; }, [ addonAfter, addonBefore, prefix, suffix, allowClear, showCount, maxLength, ]); const [newVal, setNewVal] = useState(value); useEffect(() => { setNewVal(value); }, [value]); const newChange = new AOP, void>(props.onChange) .after((e) => { setNewVal(e.target.value); }) .getFunction(); const [theme] = useTheme(); const newSuffix = useMemo(() => { const resIcons: ReactNode[] = []; if (allowClear && newVal) { resIcons.push( { setNewVal(''); props.onChange({ target: { value: '', }, } as any); }} >, ); } if (status) { const statusIcons = { success: { name: 'CheckOnCircleOne', color: theme['green-6'], }, error: { name: 'AttentionCircleTwo', color: theme['red-6'], }, warning: { name: 'AttentionCircleTwo', color: theme['orange-6'], }, }; resIcons.push( , ); } return resIcons; }, [allowClear, status, theme, newVal]); return ( <> { newChange(e); }} > {props.children} {message && (
{message}
)} ); }; const Search = (props: SearchProps) => { const { getPrefixCls } = useContext(ConfigProvider.ConfigContext); const prefixCls = getPrefixCls('btri-input'); const [value, setValue] = React.useState(''); // 拦截change const newChange = new AOP, void>( props.onChange, ) .before((e) => { setValue(e.target.value); }) .getFunction(); const searchIcon = props.loading ? ( ) : ( { props.onSearch?.(value, e); }} > ); return ( { props.onSearch?.(value, e); }} suffix={searchIcon} {...props} onChange={newChange} className={classNames(`${prefixCls}-search-box`, props.className)} > {props.children} ); }; Input.Search = Search; const Password = (props: PasswordProps) => { const { getPrefixCls } = useContext(ConfigProvider.ConfigContext); const prefixCls = getPrefixCls('btri-input'); const iconRender = (visible: boolean) => visible ? ( ) : ( ); return ( {props.children} ); }; Input.Password = Password; const TextArea = (props: TextAreaProps) => { const { getPrefixCls } = useContext(ConfigProvider.ConfigContext); const prefixCls = getPrefixCls('btri-input'); return ( {props.children} ); }; Input.TextArea = TextArea; export { Input };