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 (
-
- {prefixNode}
- {cloneElement(element, {
- style: null,
- value,
- className: getInputClassName(prefixCls, bordered, size, disabled),
- })}
- {suffixNode}
-
- );
- }
-
- 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 (
-
-
- {addonBeforeNode}
- {cloneElement(labeledElement, { style: null })}
- {addonAfterNode}
-
-
- );
- }
-
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();
ref.current!.focus({ cursor: 'start' });
expect(focus).toHaveBeenCalled();
@@ -39,8 +40,8 @@ describe('Input.Focus', () => {
});
it('end', () => {
- const ref = React.createRef();
- mount();
+ const ref = React.createRef();
+ mount();
ref.current!.focus({ cursor: 'end' });
expect(focus).toHaveBeenCalled();
@@ -62,6 +63,7 @@ describe('Input.Focus', () => {
expect(wrapper.exists('.ant-input-affix-wrapper-focused')).toBeTruthy();
wrapper.setProps({ disabled: true });
+ wrapper.update();
expect(wrapper.exists('.ant-input-affix-wrapper-focused')).toBeFalsy();
});
});
diff --git a/components/input/__tests__/index.test.js b/components/input/__tests__/index.test.js
index e6e3539070..42f33c240d 100644
--- a/components/input/__tests__/index.test.js
+++ b/components/input/__tests__/index.test.js
@@ -3,7 +3,6 @@ import { mount } from 'enzyme';
// eslint-disable-next-line import/no-unresolved
import Form from '../../form';
import Input from '..';
-import focusTest from '../../../tests/shared/focusTest';
import mountTest from '../../../tests/shared/mountTest';
import rtlTest from '../../../tests/shared/rtlTest';
@@ -18,7 +17,6 @@ describe('Input', () => {
errorSpy.mockRestore();
});
- focusTest(Input);
mountTest(Input);
mountTest(Input.Group);
@@ -31,8 +29,9 @@ describe('Input', () => {
});
it('select()', () => {
- const wrapper = mount();
- wrapper.instance().select();
+ const ref = React.createRef();
+ mount();
+ ref.current?.select();
});
it('should support size', () => {
@@ -63,8 +62,8 @@ describe('Input', () => {
expect(errorSpy).not.toHaveBeenCalled();
});
it('trigger warning', () => {
- const wrapper = mount(, { attachTo: document.body });
- wrapper.find('input').instance().focus();
+ const wrapper = mount();
+ wrapper.find('input').first().getDOMNode().focus();
wrapper.setProps({
suffix: 'light',
});
@@ -78,10 +77,11 @@ describe('Input', () => {
it('set mouse cursor position', () => {
const defaultValue = '11111';
const valLength = defaultValue.length;
- const wrapper = mount();
- wrapper.instance().setSelectionRange(valLength, valLength);
- expect(wrapper.instance().input.selectionStart).toEqual(5);
- expect(wrapper.instance().input.selectionEnd).toEqual(5);
+ const ref = React.createRef();
+ const wrapper = mount();
+ ref.current?.setSelectionRange(valLength, valLength);
+ expect(wrapper.find('input').first().getDOMNode().selectionStart).toEqual(5);
+ expect(wrapper.find('input').first().getDOMNode().selectionEnd).toEqual(5);
});
});
diff --git a/components/input/__tests__/textarea.test.js b/components/input/__tests__/textarea.test.js
index 0bc447b3c7..320d29f872 100644
--- a/components/input/__tests__/textarea.test.js
+++ b/components/input/__tests__/textarea.test.js
@@ -486,4 +486,27 @@ describe('TextArea allowClear', () => {
wrapper.unmount();
});
+
+ // https://github.com/ant-design/ant-design/issues/31200
+ it('should not lost focus when clear input', () => {
+ const onBlur = jest.fn();
+ const wrapper = mount(, {
+ attachTo: document.body,
+ });
+ wrapper.find('textarea').getDOMNode().focus();
+ wrapper.find('.ant-input-clear-icon').at(0).simulate('mouseDown');
+ wrapper.find('.ant-input-clear-icon').at(0).simulate('click');
+ wrapper.find('.ant-input-clear-icon').at(0).simulate('mouseUp');
+ wrapper.find('.ant-input-clear-icon').at(0).simulate('focus');
+ wrapper.find('.ant-input-clear-icon').at(0).getDOMNode().click();
+ expect(onBlur).not.toBeCalled();
+ wrapper.unmount();
+ });
+
+ it('should focus text area after clear', () => {
+ const wrapper = mount(, { attachTo: document.body });
+ wrapper.find('.ant-input-clear-icon').at(0).simulate('click');
+ expect(document.activeElement).toBe(wrapper.find('textarea').at(0).getDOMNode());
+ wrapper.unmount();
+ });
});
diff --git a/components/input/index.tsx b/components/input/index.tsx
index e7421576b1..dade50b667 100644
--- a/components/input/index.tsx
+++ b/components/input/index.tsx
@@ -1,15 +1,26 @@
-import Input from './Input';
+import * as React from 'react';
+import InternalInput, { InputProps, InputRef } from './Input';
import Group from './Group';
import Search from './Search';
import TextArea from './TextArea';
import Password from './Password';
-export { InputProps } from './Input';
+export { InputProps, InputRef } from './Input';
export { GroupProps } from './Group';
export { SearchProps } from './Search';
export { TextAreaProps } from './TextArea';
export { PasswordProps } from './Password';
+interface CompoundedComponent
+ extends React.ForwardRefExoticComponent> {
+ Group: typeof Group;
+ Search: typeof Search;
+ TextArea: typeof TextArea;
+ Password: typeof Password;
+}
+
+const Input = InternalInput as CompoundedComponent;
+
Input.Group = Group;
Input.Search = Search;
Input.TextArea = TextArea;
diff --git a/components/input/style/allow-clear.less b/components/input/style/allow-clear.less
index 8f548c8a80..be370d87e5 100644
--- a/components/input/style/allow-clear.less
+++ b/components/input/style/allow-clear.less
@@ -2,7 +2,7 @@
@input-prefix-cls: ~'@{ant-prefix}-input';
// ========================= Input =========================
-.@{iconfont-css-prefix}.@{ant-prefix}-input-clear-icon {
+.@{ant-prefix}-input-clear-icon {
margin: 0;
color: @disabled-color;
font-size: @font-size-sm;
diff --git a/components/input/utils.ts b/components/input/utils.ts
index 39eb862fda..8963d8fb35 100644
--- a/components/input/utils.ts
+++ b/components/input/utils.ts
@@ -1,33 +1,7 @@
-import classNames from 'classnames';
-import { ValidateStatus } from '../form/FormItem';
-import type { DirectionType } from '../config-provider';
-import type { SizeType } from '../config-provider/SizeContext';
import type { ClearableInputProps } from './ClearableLabeledInput';
import type { InputProps } from './Input';
-import { getStatusClassNames } from '../_util/statusUtils';
-
-export function getInputClassName(
- prefixCls: string,
- bordered: boolean,
- size?: SizeType,
- disabled?: boolean,
- direction?: DirectionType,
- status?: ValidateStatus,
- hasFeedback?: boolean,
-) {
- return classNames(
- prefixCls,
- {
- [`${prefixCls}-sm`]: size === 'small',
- [`${prefixCls}-lg`]: size === 'large',
- [`${prefixCls}-disabled`]: disabled,
- [`${prefixCls}-rtl`]: direction === 'rtl',
- [`${prefixCls}-borderless`]: !bordered,
- },
- getStatusClassNames(prefixCls, status, hasFeedback),
- );
-}
+// eslint-disable-next-line import/prefer-default-export
export function hasPrefixSuffix(props: InputProps | ClearableInputProps) {
return !!(props.prefix || props.suffix || props.allowClear);
}
diff --git a/components/locale-provider/__tests__/__snapshots__/index.test.js.snap b/components/locale-provider/__tests__/__snapshots__/index.test.js.snap
index 8de740a492..48765d3dbe 100644
--- a/components/locale-provider/__tests__/__snapshots__/index.test.js.snap
+++ b/components/locale-provider/__tests__/__snapshots__/index.test.js.snap
@@ -5467,24 +5467,29 @@ exports[`Locale Provider should display the text as ar 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -5687,24 +5692,29 @@ exports[`Locale Provider should display the text as ar 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -10544,24 +10554,29 @@ exports[`Locale Provider should display the text as az 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -10764,24 +10779,29 @@ exports[`Locale Provider should display the text as az 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -15621,24 +15641,29 @@ exports[`Locale Provider should display the text as bg 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -15841,24 +15866,29 @@ exports[`Locale Provider should display the text as bg 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -20698,24 +20728,29 @@ exports[`Locale Provider should display the text as bn-bd 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -20918,24 +20953,29 @@ exports[`Locale Provider should display the text as bn-bd 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -25775,24 +25815,29 @@ exports[`Locale Provider should display the text as by 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -25995,24 +26040,29 @@ exports[`Locale Provider should display the text as by 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -30852,24 +30902,29 @@ exports[`Locale Provider should display the text as ca 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -31072,24 +31127,29 @@ exports[`Locale Provider should display the text as ca 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -35929,24 +35989,29 @@ exports[`Locale Provider should display the text as cs 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -36149,24 +36214,29 @@ exports[`Locale Provider should display the text as cs 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -41006,24 +41076,29 @@ exports[`Locale Provider should display the text as da 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -41226,24 +41301,29 @@ exports[`Locale Provider should display the text as da 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -46083,24 +46163,29 @@ exports[`Locale Provider should display the text as de 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -46303,24 +46388,29 @@ exports[`Locale Provider should display the text as de 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -51160,24 +51250,29 @@ exports[`Locale Provider should display the text as el 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -51380,24 +51475,29 @@ exports[`Locale Provider should display the text as el 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -56237,24 +56337,29 @@ exports[`Locale Provider should display the text as en 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -56457,24 +56562,29 @@ exports[`Locale Provider should display the text as en 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -61314,24 +61424,29 @@ exports[`Locale Provider should display the text as en-gb 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -61534,24 +61649,29 @@ exports[`Locale Provider should display the text as en-gb 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -66391,24 +66511,29 @@ exports[`Locale Provider should display the text as es 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -66611,24 +66736,29 @@ exports[`Locale Provider should display the text as es 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -71468,24 +71598,29 @@ exports[`Locale Provider should display the text as et 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -71688,24 +71823,29 @@ exports[`Locale Provider should display the text as et 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -76545,24 +76685,29 @@ exports[`Locale Provider should display the text as fa 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -76765,24 +76910,29 @@ exports[`Locale Provider should display the text as fa 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -81622,24 +81772,29 @@ exports[`Locale Provider should display the text as fi 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -81842,24 +81997,29 @@ exports[`Locale Provider should display the text as fi 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -86699,24 +86859,29 @@ exports[`Locale Provider should display the text as fr 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -86919,24 +87084,29 @@ exports[`Locale Provider should display the text as fr 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -91776,24 +91946,29 @@ exports[`Locale Provider should display the text as fr 2`] = `
class="ant-input-suffix"
>
-
+
+
@@ -91996,24 +92171,29 @@ exports[`Locale Provider should display the text as fr 2`] = `
class="ant-input-suffix"
>
-
+
+
@@ -96853,24 +97033,29 @@ exports[`Locale Provider should display the text as fr 3`] = `
class="ant-input-suffix"
>
-
+
+
@@ -97073,24 +97258,29 @@ exports[`Locale Provider should display the text as fr 3`] = `
class="ant-input-suffix"
>
-
+
+
@@ -101930,24 +102120,29 @@ exports[`Locale Provider should display the text as ga 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -102150,24 +102345,29 @@ exports[`Locale Provider should display the text as ga 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -107007,24 +107207,29 @@ exports[`Locale Provider should display the text as gl 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -107227,24 +107432,29 @@ exports[`Locale Provider should display the text as gl 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -112084,24 +112294,29 @@ exports[`Locale Provider should display the text as he 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -112304,24 +112519,29 @@ exports[`Locale Provider should display the text as he 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -117161,24 +117381,29 @@ exports[`Locale Provider should display the text as hi 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -117381,24 +117606,29 @@ exports[`Locale Provider should display the text as hi 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -122238,24 +122468,29 @@ exports[`Locale Provider should display the text as hr 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -122458,24 +122693,29 @@ exports[`Locale Provider should display the text as hr 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -127315,24 +127555,29 @@ exports[`Locale Provider should display the text as hu 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -127535,24 +127780,29 @@ exports[`Locale Provider should display the text as hu 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -132392,24 +132642,29 @@ exports[`Locale Provider should display the text as hy-am 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -132612,24 +132867,29 @@ exports[`Locale Provider should display the text as hy-am 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -137469,24 +137729,29 @@ exports[`Locale Provider should display the text as id 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -137689,24 +137954,29 @@ exports[`Locale Provider should display the text as id 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -142546,24 +142816,29 @@ exports[`Locale Provider should display the text as is 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -142766,24 +143041,29 @@ exports[`Locale Provider should display the text as is 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -147623,24 +147903,29 @@ exports[`Locale Provider should display the text as it 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -147843,24 +148128,29 @@ exports[`Locale Provider should display the text as it 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -152700,24 +152990,29 @@ exports[`Locale Provider should display the text as ja 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -152920,24 +153215,29 @@ exports[`Locale Provider should display the text as ja 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -157777,24 +158077,29 @@ exports[`Locale Provider should display the text as ka 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -157997,24 +158302,29 @@ exports[`Locale Provider should display the text as ka 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -162854,24 +163164,29 @@ exports[`Locale Provider should display the text as kk 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -163074,24 +163389,29 @@ exports[`Locale Provider should display the text as kk 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -167931,24 +168251,29 @@ exports[`Locale Provider should display the text as km 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -168151,24 +168476,29 @@ exports[`Locale Provider should display the text as km 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -173008,24 +173338,29 @@ exports[`Locale Provider should display the text as kn 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -173228,24 +173563,29 @@ exports[`Locale Provider should display the text as kn 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -178085,24 +178425,29 @@ exports[`Locale Provider should display the text as ko 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -178305,24 +178650,29 @@ exports[`Locale Provider should display the text as ko 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -183162,24 +183512,29 @@ exports[`Locale Provider should display the text as ku 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -183382,24 +183737,29 @@ exports[`Locale Provider should display the text as ku 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -188239,24 +188599,29 @@ exports[`Locale Provider should display the text as ku-iq 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -188459,24 +188824,29 @@ exports[`Locale Provider should display the text as ku-iq 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -193316,24 +193686,29 @@ exports[`Locale Provider should display the text as lt 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -193536,24 +193911,29 @@ exports[`Locale Provider should display the text as lt 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -198393,24 +198773,29 @@ exports[`Locale Provider should display the text as lv 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -198613,24 +198998,29 @@ exports[`Locale Provider should display the text as lv 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -203470,24 +203860,29 @@ exports[`Locale Provider should display the text as mk 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -203690,24 +204085,29 @@ exports[`Locale Provider should display the text as mk 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -208547,24 +208947,29 @@ exports[`Locale Provider should display the text as ml 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -208767,24 +209172,29 @@ exports[`Locale Provider should display the text as ml 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -213624,24 +214034,29 @@ exports[`Locale Provider should display the text as mn-mn 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -213844,24 +214259,29 @@ exports[`Locale Provider should display the text as mn-mn 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -218701,24 +219121,29 @@ exports[`Locale Provider should display the text as ms-my 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -218921,24 +219346,29 @@ exports[`Locale Provider should display the text as ms-my 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -223778,24 +224208,29 @@ exports[`Locale Provider should display the text as nb 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -223998,24 +224433,29 @@ exports[`Locale Provider should display the text as nb 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -228855,24 +229295,29 @@ exports[`Locale Provider should display the text as ne-np 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -229075,24 +229520,29 @@ exports[`Locale Provider should display the text as ne-np 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -233932,24 +234382,29 @@ exports[`Locale Provider should display the text as nl 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -234152,24 +234607,29 @@ exports[`Locale Provider should display the text as nl 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -239009,24 +239469,29 @@ exports[`Locale Provider should display the text as nl-be 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -239229,24 +239694,29 @@ exports[`Locale Provider should display the text as nl-be 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -244086,24 +244556,29 @@ exports[`Locale Provider should display the text as pl 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -244306,24 +244781,29 @@ exports[`Locale Provider should display the text as pl 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -249163,24 +249643,29 @@ exports[`Locale Provider should display the text as pt 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -249383,24 +249868,29 @@ exports[`Locale Provider should display the text as pt 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -254240,24 +254730,29 @@ exports[`Locale Provider should display the text as pt-br 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -254460,24 +254955,29 @@ exports[`Locale Provider should display the text as pt-br 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -259317,24 +259817,29 @@ exports[`Locale Provider should display the text as ro 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -259537,24 +260042,29 @@ exports[`Locale Provider should display the text as ro 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -264394,24 +264904,29 @@ exports[`Locale Provider should display the text as ru 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -264614,24 +265129,29 @@ exports[`Locale Provider should display the text as ru 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -269471,24 +269991,29 @@ exports[`Locale Provider should display the text as sk 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -269691,24 +270216,29 @@ exports[`Locale Provider should display the text as sk 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -274548,24 +275078,29 @@ exports[`Locale Provider should display the text as sl 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -274768,24 +275303,29 @@ exports[`Locale Provider should display the text as sl 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -279625,24 +280165,29 @@ exports[`Locale Provider should display the text as sr 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -279845,24 +280390,29 @@ exports[`Locale Provider should display the text as sr 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -284702,24 +285252,29 @@ exports[`Locale Provider should display the text as sv 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -284922,24 +285477,29 @@ exports[`Locale Provider should display the text as sv 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -289779,24 +290339,29 @@ exports[`Locale Provider should display the text as ta 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -289999,24 +290564,29 @@ exports[`Locale Provider should display the text as ta 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -294856,24 +295426,29 @@ exports[`Locale Provider should display the text as th 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -295076,24 +295651,29 @@ exports[`Locale Provider should display the text as th 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -299933,24 +300513,29 @@ exports[`Locale Provider should display the text as tr 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -300153,24 +300738,29 @@ exports[`Locale Provider should display the text as tr 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -305010,24 +305600,29 @@ exports[`Locale Provider should display the text as uk 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -305230,24 +305825,29 @@ exports[`Locale Provider should display the text as uk 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -310087,24 +310687,29 @@ exports[`Locale Provider should display the text as ur 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -310307,24 +310912,29 @@ exports[`Locale Provider should display the text as ur 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -315164,24 +315774,29 @@ exports[`Locale Provider should display the text as vi 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -315384,24 +315999,29 @@ exports[`Locale Provider should display the text as vi 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -320241,24 +320861,29 @@ exports[`Locale Provider should display the text as zh-cn 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -320461,24 +321086,29 @@ exports[`Locale Provider should display the text as zh-cn 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -325318,24 +325948,29 @@ exports[`Locale Provider should display the text as zh-hk 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -325538,24 +326173,29 @@ exports[`Locale Provider should display the text as zh-hk 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -330395,24 +331035,29 @@ exports[`Locale Provider should display the text as zh-tw 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -330615,24 +331260,29 @@ exports[`Locale Provider should display the text as zh-tw 1`] = `
class="ant-input-suffix"
>
-
+
+
diff --git a/components/table/demo/edit-cell.md b/components/table/demo/edit-cell.md
index 9575c85b28..dac0a7ee8a 100644
--- a/components/table/demo/edit-cell.md
+++ b/components/table/demo/edit-cell.md
@@ -15,7 +15,7 @@ Table with editable cells. When work with `shouldCellUpdate`, please take care o
```tsx
import React, { useContext, useState, useEffect, useRef } from 'react';
-import { Table, Input, Button, Popconfirm, Form } from 'antd';
+import { Table, Input, Button, Popconfirm, Form, InputRef } from 'antd';
import { FormInstance } from 'antd/lib/form';
const EditableContext = React.createContext | null>(null);
@@ -61,7 +61,7 @@ const EditableCell: React.FC = ({
...restProps
}) => {
const [editing, setEditing] = useState(false);
- const inputRef = useRef(null);
+ const inputRef = useRef(null);
const form = useContext(EditableContext)!;
useEffect(() => {
diff --git a/components/transfer/__tests__/__snapshots__/demo-extend.test.ts.snap b/components/transfer/__tests__/__snapshots__/demo-extend.test.ts.snap
index cfbc9947ba..b075e8d243 100644
--- a/components/transfer/__tests__/__snapshots__/demo-extend.test.ts.snap
+++ b/components/transfer/__tests__/__snapshots__/demo-extend.test.ts.snap
@@ -225,24 +225,29 @@ exports[`renders ./components/transfer/demo/advanced.md extend context correctly
class="ant-input-suffix"
>
-
+
+
@@ -593,24 +598,29 @@ exports[`renders ./components/transfer/demo/advanced.md extend context correctly
class="ant-input-suffix"
>
-
+
+
@@ -4626,24 +4636,29 @@ exports[`renders ./components/transfer/demo/search.md extend context correctly 1
class="ant-input-suffix"
>
-
+
+
@@ -4974,24 +4989,29 @@ exports[`renders ./components/transfer/demo/search.md extend context correctly 1
class="ant-input-suffix"
>
-
+
+
@@ -5810,24 +5830,29 @@ exports[`renders ./components/transfer/demo/status.md extend context correctly 1
class="ant-input-suffix"
>
-
+
+
@@ -6158,24 +6183,29 @@ exports[`renders ./components/transfer/demo/status.md extend context correctly 1
class="ant-input-suffix"
>
-
+
+
diff --git a/components/transfer/__tests__/__snapshots__/demo.test.js.snap b/components/transfer/__tests__/__snapshots__/demo.test.js.snap
index 6097eddcc5..ce091217ca 100644
--- a/components/transfer/__tests__/__snapshots__/demo.test.js.snap
+++ b/components/transfer/__tests__/__snapshots__/demo.test.js.snap
@@ -96,24 +96,29 @@ exports[`renders ./components/transfer/demo/advanced.md correctly 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -335,24 +340,29 @@ exports[`renders ./components/transfer/demo/advanced.md correctly 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -2894,24 +2904,29 @@ exports[`renders ./components/transfer/demo/search.md correctly 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -3113,24 +3128,29 @@ exports[`renders ./components/transfer/demo/search.md correctly 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -3562,24 +3582,29 @@ exports[`renders ./components/transfer/demo/status.md correctly 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -3781,24 +3806,29 @@ exports[`renders ./components/transfer/demo/status.md correctly 1`] = `
class="ant-input-suffix"
>
-
+
+
diff --git a/components/transfer/__tests__/__snapshots__/search.test.js.snap b/components/transfer/__tests__/__snapshots__/search.test.js.snap
index 6e56448cdc..11444bd6e1 100644
--- a/components/transfer/__tests__/__snapshots__/search.test.js.snap
+++ b/components/transfer/__tests__/__snapshots__/search.test.js.snap
@@ -37,24 +37,29 @@ exports[`Transfer.Search should show cross icon when input value exists 1`] = `
class="ant-input-suffix"
>
-
+
+
@@ -97,24 +102,29 @@ exports[`Transfer.Search should show cross icon when input value exists 2`] = `
class="ant-input-suffix"
>
-
+
+
diff --git a/package.json b/package.json
index 9c9c39329e..b52de2a9c3 100644
--- a/package.json
+++ b/package.json
@@ -129,6 +129,7 @@
"rc-dropdown": "~3.3.2",
"rc-field-form": "~1.23.0",
"rc-image": "~5.2.5",
+ "rc-input": "^0.0.1-alpha.3",
"rc-input-number": "~7.3.0",
"rc-mentions": "~1.6.1",
"rc-menu": "~9.2.1",