From bfebb88bdb6ad204da5a4bc4c030a0abf845e5c2 Mon Sep 17 00:00:00 2001 From: MadCcc <1075746765@qq.com> Date: Tue, 1 Mar 2022 14:17:48 +0800 Subject: [PATCH] feat: introduce rc-input (#34206) * feat: introduce rc-input * fix: export InputRef alias * docs: fix demo * chore: code clean * test: fix lint * test: test coverage * chore: code clean * chore: code clean * test: update snapshot --- .../__snapshots__/demo-extend.test.ts.snap | 4 +- .../__tests__/__snapshots__/demo.test.js.snap | 4 +- .../__snapshots__/components.test.js.snap | 6 +- .../__snapshots__/demo-extend.test.ts.snap | 66 +- .../__tests__/__snapshots__/demo.test.js.snap | 66 +- components/index.tsx | 2 +- components/input/ClearableLabeledInput.tsx | 166 +- components/input/Input.tsx | 456 +- components/input/Password.tsx | 4 +- components/input/Search.tsx | 10 +- components/input/__tests__/Password.test.js | 2 +- .../__snapshots__/Password.test.js.snap | 6 +- .../__snapshots__/Search.test.js.snap | 2 +- .../__snapshots__/demo-extend.test.ts.snap | 251 +- .../__tests__/__snapshots__/demo.test.js.snap | 251 +- .../__snapshots__/index.test.js.snap | 264 +- components/input/__tests__/focus.test.tsx | 10 +- components/input/__tests__/index.test.js | 20 +- components/input/__tests__/textarea.test.js | 23 + components/input/index.tsx | 15 +- components/input/style/allow-clear.less | 2 +- components/input/utils.ts | 28 +- .../__snapshots__/index.test.js.snap | 4290 ++++++++++------- components/table/demo/edit-cell.md | 4 +- .../__snapshots__/demo-extend.test.ts.snap | 198 +- .../__tests__/__snapshots__/demo.test.js.snap | 198 +- .../__snapshots__/search.test.js.snap | 66 +- package.json | 1 + 28 files changed, 3449 insertions(+), 2966 deletions(-) diff --git a/components/auto-complete/__tests__/__snapshots__/demo-extend.test.ts.snap b/components/auto-complete/__tests__/__snapshots__/demo-extend.test.ts.snap index b6b6ca89be..08fcb1420c 100644 --- a/components/auto-complete/__tests__/__snapshots__/demo-extend.test.ts.snap +++ b/components/auto-complete/__tests__/__snapshots__/demo-extend.test.ts.snap @@ -107,7 +107,7 @@ exports[`renders ./components/auto-complete/demo/certain-category.md extend cont class="ant-select-selection-search" > diff --git a/components/form/__tests__/__snapshots__/demo-extend.test.ts.snap b/components/form/__tests__/__snapshots__/demo-extend.test.ts.snap index 5b92f5e0cb..e0b571afa8 100644 --- a/components/form/__tests__/__snapshots__/demo-extend.test.ts.snap +++ b/components/form/__tests__/__snapshots__/demo-extend.test.ts.snap @@ -20704,24 +20704,29 @@ exports[`renders ./components/form/demo/validate-static.md extend context correc class="ant-input-suffix" > - + + - + + - + + - + + { - /** @private Do Not use out of this class. We do not promise this is always keep. */ - private containerRef = React.createRef(); - - onInputMouseUp: React.MouseEventHandler = e => { - if (this.containerRef.current?.contains(e.target as Element)) { - const { triggerFocus } = this.props; - triggerFocus?.(); - } - }; - renderClearIcon(prefixCls: string) { - const { allowClear, value, disabled, readOnly, handleReset, suffix } = this.props; - if (!allowClear) { - return null; - } + const { value, disabled, readOnly, handleReset, suffix } = this.props; const needClear = !disabled && !readOnly && value; const className = `${prefixCls}-clear-icon`; return ( @@ -81,151 +67,6 @@ class ClearableLabeledInput extends React.Component { ); } - renderSuffix(prefixCls: string) { - const { suffix, allowClear } = this.props; - if (suffix || allowClear) { - return ( - - {this.renderClearIcon(prefixCls)} - {suffix} - - ); - } - return null; - } - - renderLabeledIcon( - prefixCls: string, - element: React.ReactElement, - statusContext: FormItemStatusContextProps, - ) { - const { - focused, - value, - prefix, - className, - size, - suffix, - disabled, - allowClear, - direction, - style, - readOnly, - bordered, - hidden, - status: customStatus, - } = this.props; - - const { status: contextStatus, hasFeedback } = statusContext; - - if (!hasPrefixSuffix(this.props)) { - return cloneElement(element, { - value, - }); - } - - const suffixNode = this.renderSuffix(prefixCls); - const prefixNode = prefix ? {prefix} : null; - - const affixWrapperCls = classNames( - `${prefixCls}-affix-wrapper`, - { - [`${prefixCls}-affix-wrapper-focused`]: focused, - [`${prefixCls}-affix-wrapper-disabled`]: disabled, - [`${prefixCls}-affix-wrapper-sm`]: size === 'small', - [`${prefixCls}-affix-wrapper-lg`]: size === 'large', - [`${prefixCls}-affix-wrapper-input-with-clear-btn`]: suffix && allowClear && value, - [`${prefixCls}-affix-wrapper-rtl`]: direction === 'rtl', - [`${prefixCls}-affix-wrapper-readonly`]: readOnly, - [`${prefixCls}-affix-wrapper-borderless`]: !bordered, - // className will go to addon wrapper - [`${className}`]: !hasAddon(this.props) && className, - }, - getStatusClassNames( - `${prefixCls}-affix-wrapper`, - getMergedStatus(contextStatus, customStatus), - hasFeedback, - ), - ); - return ( - - ); - } - - renderInputWithLabel( - prefixCls: string, - labeledElement: React.ReactElement, - statusContext: FormItemStatusContextProps, - ) { - const { - addonBefore, - addonAfter, - style, - size, - className, - direction, - hidden, - status: customStatus, - } = this.props; - const { status: contextStatus, hasFeedback } = statusContext; - // Not wrap when there is not addons - if (!hasAddon(this.props)) { - return labeledElement; - } - - const wrapperClassName = `${prefixCls}-group`; - const addonClassName = `${wrapperClassName}-addon`; - const addonBeforeNode = addonBefore ? ( - {addonBefore} - ) : null; - const addonAfterNode = addonAfter ? {addonAfter} : null; - - const mergedWrapperClassName = classNames(`${prefixCls}-wrapper`, wrapperClassName, { - [`${wrapperClassName}-rtl`]: direction === 'rtl', - }); - - const mergedGroupClassName = classNames( - `${prefixCls}-group-wrapper`, - { - [`${prefixCls}-group-wrapper-sm`]: size === 'small', - [`${prefixCls}-group-wrapper-lg`]: size === 'large', - [`${prefixCls}-group-wrapper-rtl`]: direction === 'rtl', - }, - getStatusClassNames( - `${prefixCls}-group-wrapper`, - getMergedStatus(contextStatus, customStatus), - hasFeedback, - ), - className, - ); - - // Need another wrapper for changing display:table to display:inline-block - // and put style prop in wrapper - return ( - - ); - } - renderTextAreaWithClearIcon( prefixCls: string, element: React.ReactElement, @@ -283,11 +124,6 @@ class ClearableLabeledInput extends React.Component { if (inputType === ClearableInputType[0]) { return this.renderTextAreaWithClearIcon(prefixCls, element, statusContext); } - return this.renderInputWithLabel( - prefixCls, - this.renderLabeledIcon(prefixCls, element, statusContext), - statusContext, - ); }} ); diff --git a/components/input/Input.tsx b/components/input/Input.tsx index 5959c9ff9a..065ce1f593 100644 --- a/components/input/Input.tsx +++ b/components/input/Input.tsx @@ -1,69 +1,25 @@ -import * as React from 'react'; +import React, { forwardRef, useContext, useEffect, useRef } from 'react'; +import RcInput, { InputProps as RcInputProps, InputRef } from 'rc-input'; +import CloseCircleFilled from '@ant-design/icons/CloseCircleFilled'; import classNames from 'classnames'; -import omit from 'rc-util/lib/omit'; -import { ValidateStatus } from '../form/FormItem'; -import type Group from './Group'; -import type Search from './Search'; -import type TextArea from './TextArea'; -import type Password from './Password'; -import { LiteralUnion } from '../_util/type'; -import ClearableLabeledInput from './ClearableLabeledInput'; -import { ConfigConsumer, ConfigConsumerProps, DirectionType } from '../config-provider'; +import { composeRef } from 'rc-util/lib/ref'; import SizeContext, { SizeType } from '../config-provider/SizeContext'; -import devWarning from '../_util/devWarning'; -import { getInputClassName, hasPrefixSuffix } from './utils'; +import { + getFeedbackIcon, + getMergedStatus, + getStatusClassNames, + InputStatus, +} from '../_util/statusUtils'; +import { ConfigContext } from '../config-provider'; import { FormItemStatusContext } from '../form/context'; -import { getFeedbackIcon, InputStatus, getMergedStatus } from '../_util/statusUtils'; +import { hasPrefixSuffix } from './utils'; +import devWarning from '../_util/devWarning'; export interface InputFocusOptions extends FocusOptions { cursor?: 'start' | 'end' | 'all'; } -export interface ShowCountProps { - formatter: (args: { count: number; maxLength?: number }) => React.ReactNode; -} - -export interface InputProps - extends Omit, 'size' | 'prefix' | 'type'> { - prefixCls?: string; - size?: SizeType; - // ref: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input#%3Cinput%3E_types - type?: LiteralUnion< - | 'button' - | 'checkbox' - | 'color' - | 'date' - | 'datetime-local' - | 'email' - | 'file' - | 'hidden' - | 'image' - | 'month' - | 'number' - | 'password' - | 'radio' - | 'range' - | 'reset' - | 'search' - | 'submit' - | 'tel' - | 'text' - | 'time' - | 'url' - | 'week', - string - >; - onPressEnter?: React.KeyboardEventHandler; - addonBefore?: React.ReactNode; - addonAfter?: React.ReactNode; - prefix?: React.ReactNode; - suffix?: React.ReactNode; - allowClear?: boolean; - showCount?: boolean | ShowCountProps; - bordered?: boolean; - htmlSize?: number; - status?: InputStatus; -} +export type { InputRef }; export function fixControlledValue(value: T) { if (typeof value === 'undefined' || value === null) { @@ -154,303 +110,133 @@ export function triggerFocus( } } -export interface InputState { - value: any; - focused: boolean; - /** `value` from prev props */ - prevValue: any; +export interface InputProps + extends Omit< + RcInputProps, + 'wrapperClassName' | 'groupClassName' | 'inputClassName' | 'affixWrapperClassName' | 'clearIcon' + > { + size?: SizeType; + status?: InputStatus; + bordered?: boolean; } -class Input extends React.Component { - static Group: typeof Group; +const Input = forwardRef((props, ref) => { + const { + prefixCls: customizePrefixCls, + bordered = true, + status: customStatus, + size: customSize, + onBlur, + onFocus, + suffix, + ...rest + } = props; + const { getPrefixCls, direction, input } = React.useContext(ConfigContext); - static Search: typeof Search; + const prefixCls = getPrefixCls('input', customizePrefixCls); + const inputRef = useRef(null); - static TextArea: typeof TextArea; + // ===================== Status ===================== + const size = React.useContext(SizeContext); + const mergedSize = customSize || size; - static Password: typeof Password; + // ===================== Status ===================== + const { status: contextStatus, hasFeedback } = useContext(FormItemStatusContext); + const mergedStatus = getMergedStatus(contextStatus, customStatus); - static defaultProps = { - type: 'text', - }; - - input!: HTMLInputElement; - - clearableInput!: ClearableLabeledInput; - - removePasswordTimeout: any; - - direction: DirectionType = 'ltr'; - - constructor(props: InputProps) { - super(props); - const value = typeof props.value === 'undefined' ? props.defaultValue : props.value; - this.state = { - value, - focused: false, - // eslint-disable-next-line react/no-unused-state - prevValue: props.value, - }; - } - - static getDerivedStateFromProps(nextProps: InputProps, { prevValue }: InputState) { - const newState: Partial = { prevValue: nextProps.value }; - if (nextProps.value !== undefined || prevValue !== nextProps.value) { - newState.value = nextProps.value; - } - if (nextProps.disabled) { - newState.focused = false; - } - return newState; - } - - componentDidMount() { - this.clearPasswordValueAttribute(); - } - - // Since polyfill `getSnapshotBeforeUpdate` need work with `componentDidUpdate`. - // We keep an empty function here. - componentDidUpdate() {} - - getSnapshotBeforeUpdate(prevProps: InputProps) { - if (hasPrefixSuffix(prevProps) !== hasPrefixSuffix(this.props)) { + // ===================== Focus warning ===================== + const inputHasPrefixSuffix = hasPrefixSuffix(props); + const prevHasPrefixSuffix = useRef(inputHasPrefixSuffix); + useEffect(() => { + if (inputHasPrefixSuffix && !prevHasPrefixSuffix.current) { devWarning( - this.input !== document.activeElement, + document.activeElement === inputRef.current?.input, 'Input', `When Input is focused, dynamic add or remove prefix / suffix will make it lose focus caused by dom structure change. Read more: https://ant.design/components/input/#FAQ`, ); } - return null; - } + prevHasPrefixSuffix.current = inputHasPrefixSuffix; + }, [inputHasPrefixSuffix]); - componentWillUnmount() { - if (this.removePasswordTimeout) { - clearTimeout(this.removePasswordTimeout); - } - } - - focus = (option?: InputFocusOptions) => { - triggerFocus(this.input, option); + // ===================== Remove Password value ===================== + const removePasswordTimeoutRef = useRef([]); + const removePasswordTimeout = () => { + removePasswordTimeoutRef.current.push( + window.setTimeout(() => { + if ( + inputRef.current?.input && + inputRef.current?.input.getAttribute('type') === 'password' && + inputRef.current?.input.hasAttribute('value') + ) { + inputRef.current?.input.removeAttribute('value'); + } + }), + ); }; - blur() { - this.input.blur(); - } + useEffect(() => { + removePasswordTimeout(); + return () => removePasswordTimeoutRef.current.forEach(item => window.clearTimeout(item)); + }, []); - setSelectionRange(start: number, end: number, direction?: 'forward' | 'backward' | 'none') { - this.input.setSelectionRange(start, end, direction); - } - - select() { - this.input.select(); - } - - saveClearableInput = (input: ClearableLabeledInput) => { - this.clearableInput = input; - }; - - saveInput = (input: HTMLInputElement) => { - this.input = input; - }; - - onFocus: React.FocusEventHandler = e => { - const { onFocus } = this.props; - this.setState({ focused: true }, this.clearPasswordValueAttribute); - onFocus?.(e); - }; - - onBlur: React.FocusEventHandler = e => { - const { onBlur } = this.props; - this.setState({ focused: false }, this.clearPasswordValueAttribute); + const handleBlur = (e: React.FocusEvent) => { + removePasswordTimeout(); onBlur?.(e); }; - setValue(value: string, callback?: () => void) { - if (this.props.value === undefined) { - this.setState({ value }, callback); - } else { - callback?.(); - } - } - - handleReset = (e: React.MouseEvent) => { - this.setValue('', () => { - this.focus(); - }); - resolveOnChange(this.input, e, this.props.onChange); + const handleFocus = (e: React.FocusEvent) => { + removePasswordTimeout(); + onFocus?.(e); }; - renderInput = ( - prefixCls: string, - size: SizeType | undefined, - bordered: boolean, - status?: ValidateStatus, - input: ConfigConsumerProps['input'] = {}, - ) => { - const { - className, - addonBefore, - addonAfter, - size: customizeSize, - disabled, - htmlSize, - } = this.props; - // Fix https://fb.me/react-unknown-prop - const otherProps = omit(this.props as InputProps & { inputType: any }, [ - 'prefixCls', - 'onPressEnter', - 'addonBefore', - 'addonAfter', - 'prefix', - 'suffix', - 'allowClear', - // Input elements must be either controlled or uncontrolled, - // specify either the value prop, or the defaultValue prop, but not both. - 'defaultValue', - 'size', - 'inputType', - 'bordered', - 'htmlSize', - 'showCount', - 'status', - ]); + const suffixNode = (hasFeedback || suffix) && ( + <> + {suffix} + {hasFeedback && getFeedbackIcon(prefixCls, mergedStatus)} + + ); - return ( - - ); - }; - - clearPasswordValueAttribute = () => { - // https://github.com/ant-design/ant-design/issues/20541 - this.removePasswordTimeout = setTimeout(() => { - if ( - this.input && - this.input.getAttribute('type') === 'password' && - this.input.hasAttribute('value') - ) { - this.input.removeAttribute('value'); - } - }); - }; - - handleChange = (e: React.ChangeEvent) => { - this.setValue(e.target.value, this.clearPasswordValueAttribute); - resolveOnChange(this.input, e, this.props.onChange); - }; - - handleKeyDown = (e: React.KeyboardEvent) => { - const { onPressEnter, onKeyDown } = this.props; - if (onPressEnter && e.keyCode === 13) { - onPressEnter(e); - } - onKeyDown?.(e); - }; - - renderShowCountSuffix = (prefixCls: string) => { - const { value } = this.state; - const { maxLength, suffix, showCount } = this.props; - // Max length value - const hasMaxLength = Number(maxLength) > 0; - - if (suffix || showCount) { - const valueLength = [...fixControlledValue(value)].length; - let dataCount = null; - if (typeof showCount === 'object') { - dataCount = showCount.formatter({ count: valueLength, maxLength }); - } else { - dataCount = `${valueLength}${hasMaxLength ? ` / ${maxLength}` : ''}`; - } - return ( - !!showCount && ( - - {dataCount} - - ) - ); - } - return null; - }; - - renderSuffix = (prefixCls: string, hasFeedback?: boolean, status?: ValidateStatus) => { - const { suffix, showCount } = this.props; - - return ( - (showCount || suffix || hasFeedback) && ( - <> - {this.renderShowCountSuffix(prefixCls)} - {suffix} - {hasFeedback && getFeedbackIcon(prefixCls, status)} - - ) - ); - }; - - renderComponent = ({ getPrefixCls, direction, input }: ConfigConsumerProps) => { - const { value, focused } = this.state; - const { prefixCls: customizePrefixCls, bordered = true, status: customStatus } = this.props; - const prefixCls = getPrefixCls('input', customizePrefixCls); - this.direction = direction; - - return ( - - {size => ( - - {({ status: contextStatus, hasFeedback }) => { - const mergedStatus = getMergedStatus(contextStatus, customStatus); - - return ( - - ); - }} - - )} - - ); - }; - - render() { - return {this.renderComponent}; - } -} + return ( + } + inputClassName={classNames( + { + [`${prefixCls}-sm`]: mergedSize === 'small', + [`${prefixCls}-lg`]: mergedSize === 'large', + [`${prefixCls}-rtl`]: direction === 'rtl', + [`${prefixCls}-borderless`]: !bordered, + }, + getStatusClassNames(prefixCls, mergedStatus), + )} + affixWrapperClassName={classNames( + { + [`${prefixCls}-affix-wrapper-sm`]: mergedSize === 'small', + [`${prefixCls}-affix-wrapper-lg`]: mergedSize === 'large', + [`${prefixCls}-affix-wrapper-rtl`]: direction === 'rtl', + [`${prefixCls}-affix-wrapper-borderless`]: !bordered, + }, + getStatusClassNames(`${prefixCls}-affix-wrapper`, mergedStatus, hasFeedback), + )} + wrapperClassName={classNames({ + [`${prefixCls}-group-rtl`]: direction === 'rtl', + })} + groupClassName={classNames( + { + [`${prefixCls}-group-wrapper-sm`]: mergedSize === 'small', + [`${prefixCls}-group-wrapper-lg`]: mergedSize === 'large', + [`${prefixCls}-group-wrapper-rtl`]: direction === 'rtl', + }, + getStatusClassNames(`${prefixCls}-group-wrapper`, mergedStatus, hasFeedback), + )} + /> + ); +}); export default Input; diff --git a/components/input/Password.tsx b/components/input/Password.tsx index efcf854746..1d2155a091 100644 --- a/components/input/Password.tsx +++ b/components/input/Password.tsx @@ -5,8 +5,8 @@ import EyeOutlined from '@ant-design/icons/EyeOutlined'; import EyeInvisibleOutlined from '@ant-design/icons/EyeInvisibleOutlined'; import { useState } from 'react'; +import Input, { InputRef, InputProps } from './Input'; import { ConfigConsumer, ConfigConsumerProps } from '../config-provider'; -import Input, { InputProps } from './Input'; export interface PasswordProps extends InputProps { readonly inputPrefixCls?: string; @@ -20,7 +20,7 @@ const ActionMap: Record = { hover: 'onMouseOver', }; -const Password = React.forwardRef((props, ref) => { +const Password = React.forwardRef((props, ref) => { const [visible, setVisible] = useState(false); const onVisibleChange = () => { diff --git a/components/input/Search.tsx b/components/input/Search.tsx index 5fc2631dc2..2a4ac4cd7e 100644 --- a/components/input/Search.tsx +++ b/components/input/Search.tsx @@ -2,7 +2,7 @@ import * as React from 'react'; import classNames from 'classnames'; import { composeRef } from 'rc-util/lib/ref'; import SearchOutlined from '@ant-design/icons/SearchOutlined'; -import Input, { InputProps } from './Input'; +import Input, { InputProps, InputRef } from './Input'; import Button from '../button'; import SizeContext from '../config-provider/SizeContext'; import { ConfigContext } from '../config-provider'; @@ -21,7 +21,7 @@ export interface SearchProps extends InputProps { loading?: boolean; } -const Search = React.forwardRef((props, ref) => { +const Search = React.forwardRef((props, ref) => { const { prefixCls: customizePrefixCls, inputPrefixCls: customizeInputPrefixCls, @@ -42,7 +42,7 @@ const Search = React.forwardRef((props, ref) => { const size = customizeSize || contextSize; - const inputRef = React.useRef(null); + const inputRef = React.useRef(null); const onChange = (e: React.ChangeEvent) => { if (e && e.target && e.type === 'click' && customOnSearch) { @@ -61,7 +61,7 @@ const Search = React.forwardRef((props, ref) => { const onSearch = (e: React.MouseEvent | React.KeyboardEvent) => { if (customOnSearch) { - customOnSearch(inputRef.current?.input.value!, e); + customOnSearch(inputRef.current?.input?.value!, e); } }; @@ -129,7 +129,7 @@ const Search = React.forwardRef((props, ref) => { return ( (inputRef, ref)} + ref={composeRef(inputRef, ref)} onPressEnter={onSearch} {...restProps} size={size} diff --git a/components/input/__tests__/Password.test.js b/components/input/__tests__/Password.test.js index 734c1a8a20..0eac90ea2f 100644 --- a/components/input/__tests__/Password.test.js +++ b/components/input/__tests__/Password.test.js @@ -25,7 +25,7 @@ describe('Input.Password', () => { it('should support size', () => { const wrapper = mount(); - expect(wrapper.find('input').hasClass('ant-input-lg')).toBe(true); + expect(wrapper.find('.ant-input-affix-wrapper-lg')).toBeTruthy(); expect(wrapper.render()).toMatchSnapshot(); }); diff --git a/components/input/__tests__/__snapshots__/Password.test.js.snap b/components/input/__tests__/__snapshots__/Password.test.js.snap index 2753b0914a..c1774e867a 100644 --- a/components/input/__tests__/__snapshots__/Password.test.js.snap +++ b/components/input/__tests__/__snapshots__/Password.test.js.snap @@ -2,7 +2,7 @@ exports[`Input.Password rtl render component should be rendered correctly in RTL direction 1`] = ` diff --git a/components/input/__tests__/__snapshots__/Search.test.js.snap b/components/input/__tests__/__snapshots__/Search.test.js.snap index 29de245a3a..bebab65545 100644 --- a/components/input/__tests__/__snapshots__/Search.test.js.snap +++ b/components/input/__tests__/__snapshots__/Search.test.js.snap @@ -2,7 +2,7 @@ exports[`Input.Search rtl render component should be rendered correctly in RTL direction 1`] = ` - + + , @@ -5004,7 +5009,7 @@ exports[`renders ./components/input/demo/borderless-debug.md extend context corr class="ant-input-affix-wrapper ant-input-affix-wrapper-borderless" > - + + @@ -5043,7 +5053,7 @@ exports[`renders ./components/input/demo/borderless-debug.md extend context corr ¥ @@ -5062,7 +5072,7 @@ exports[`renders ./components/input/demo/borderless-debug.md extend context corr ¥ - + + @@ -5555,24 +5570,29 @@ exports[`renders ./components/input/demo/group.md extend context correctly 1`] = class="ant-input-suffix" > - + + @@ -8937,24 +8957,29 @@ exports[`renders ./components/input/demo/search-input.md extend context correctl class="ant-input-suffix" > - + + @@ -9018,24 +9043,29 @@ exports[`renders ./components/input/demo/search-input.md extend context correctl class="ant-input-suffix" > - + + @@ -9122,7 +9152,7 @@ exports[`renders ./components/input/demo/search-input.md extend context correctl style="margin-bottom:8px" > - + + @@ -9180,7 +9215,7 @@ exports[`renders ./components/input/demo/search-input.md extend context correctl class="ant-space-item" > ,
, - + +
, @@ -1221,7 +1226,7 @@ exports[`renders ./components/input/demo/borderless-debug.md correctly 1`] = ` class="ant-input-affix-wrapper ant-input-affix-wrapper-borderless" > - + + @@ -1260,7 +1270,7 @@ exports[`renders ./components/input/demo/borderless-debug.md correctly 1`] = ` ¥ @@ -1279,7 +1289,7 @@ exports[`renders ./components/input/demo/borderless-debug.md correctly 1`] = ` ¥ - + + @@ -1666,24 +1681,29 @@ exports[`renders ./components/input/demo/group.md correctly 1`] = ` class="ant-input-suffix" > - + + @@ -2711,24 +2731,29 @@ exports[`renders ./components/input/demo/search-input.md correctly 1`] = ` class="ant-input-suffix" > - + + @@ -2792,24 +2817,29 @@ exports[`renders ./components/input/demo/search-input.md correctly 1`] = ` class="ant-input-suffix" > - + + @@ -2896,7 +2926,7 @@ exports[`renders ./components/input/demo/search-input.md correctly 1`] = ` style="margin-bottom:8px" > - + + @@ -2954,7 +2989,7 @@ exports[`renders ./components/input/demo/search-input.md correctly 1`] = ` class="ant-space-item" > ,
, - + +
@@ -49,24 +54,29 @@ exports[`Input allowClear should change type when click 2`] = ` class="ant-input-suffix" > - + + @@ -85,24 +95,29 @@ exports[`Input allowClear should not show icon if defaultValue is undefined, nul class="ant-input-suffix" > - + + @@ -121,24 +136,29 @@ exports[`Input allowClear should not show icon if defaultValue is undefined, nul class="ant-input-suffix" > - + + @@ -157,24 +177,29 @@ exports[`Input allowClear should not show icon if defaultValue is undefined, nul class="ant-input-suffix" > - + + @@ -193,24 +218,29 @@ exports[`Input allowClear should not show icon if value is undefined, null or em class="ant-input-suffix" > - + + @@ -229,24 +259,29 @@ exports[`Input allowClear should not show icon if value is undefined, null or em class="ant-input-suffix" > - + + @@ -265,24 +300,29 @@ exports[`Input allowClear should not show icon if value is undefined, null or em class="ant-input-suffix" > - + + diff --git a/components/input/__tests__/focus.test.tsx b/components/input/__tests__/focus.test.tsx index 640132c2a3..5637cabe80 100644 --- a/components/input/__tests__/focus.test.tsx +++ b/components/input/__tests__/focus.test.tsx @@ -1,6 +1,7 @@ import React from 'react'; import { mount } from 'enzyme'; import { spyElementPrototypes } from 'rc-util/lib/test/domHook'; +import { InputRef } from '../Input'; import Input from '..'; const { TextArea } = Input; @@ -30,8 +31,8 @@ describe('Input.Focus', () => { }); it('start', () => { - const ref = React.createRef(); - mount(); + const ref = React.createRef(); + mount(