(
blur: () => innerRef.current?.blur(),
}));
- const textArea = (
-
- );
-
- let val = fixControlledValue(value) as string;
+ const prefixCls = getPrefixCls('input', customizePrefixCls);
- if (!compositing && hasMaxLength && (props.value === null || props.value === undefined)) {
- // fix #27612 将value转为数组进行截取,解决 '😂'.length === 2 等emoji表情导致的截取乱码的问题
- val = fixEmojiLength(val, maxLength!);
+ // Allow clear
+ let mergedAllowClear: BaseInputProps['allowClear'];
+ if (typeof allowClear === 'object' && allowClear?.clearIcon) {
+ mergedAllowClear = allowClear;
+ } else if (allowClear) {
+ mergedAllowClear = { clearIcon: };
}
- // TextArea
- const textareaNode = (
-
- );
-
- // Only show text area wrapper when needed
- if (showCount || hasFeedback) {
- const valueLength = [...val].length;
-
- let dataCount = '';
- if (typeof showCount === 'object') {
- dataCount = showCount.formatter({ value: val, count: valueLength, maxLength });
- } else {
- dataCount = `${valueLength}${hasMaxLength ? ` / ${maxLength}` : ''}`;
- }
+ // ===================== Style =====================
+ const [wrapSSR, hashId] = useStyle(prefixCls);
- return (
-
- {textareaNode}
- {hasFeedback && {feedbackIcon} }
-
- );
- }
-
- return wrapSSR(textareaNode);
+ ),
+ }}
+ prefixCls={prefixCls}
+ suffix={
+ hasFeedback && {feedbackIcon}
+ }
+ ref={innerRef}
+ />,
+ );
},
);
diff --git a/components/input/__tests__/__snapshots__/demo-extend.test.ts.snap b/components/input/__tests__/__snapshots__/demo-extend.test.ts.snap
index 17c4d68b1f..16091c5730 100644
--- a/components/input/__tests__/__snapshots__/demo-extend.test.ts.snap
+++ b/components/input/__tests__/__snapshots__/demo-extend.test.ts.snap
@@ -4902,31 +4902,40 @@ Array [
,
,
-
-
-
+
+
+
+
+
+
,
]
@@ -4994,31 +5003,40 @@ exports[`renders ./components/input/demo/borderless-debug.tsx extend context cor
placeholder="Unbordered"
/>
-
-
-
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
@@ -9707,12 +9734,17 @@ Array [
,
,
+
+ 0 / 100
+
,
]
`;
@@ -9970,31 +10002,40 @@ Array [
The autoSize property applies to textarea nodes, and only the height changes automatically. In addition, autoSize can be set to an object, specifying the minimum number of rows and the maximum number of rows. The autoSize property applies to textarea nodes, and only the height changes automatically. In addition, autoSize can be set to an object, specifying the minimum number of rows and the maximum number of rows.
,
-
-
-
+
+
+
+
+
+
,
]
@@ -10003,7 +10044,7 @@ Array [
exports[`renders ./components/input/demo/textarea-show-count.tsx extend context correctly 1`] = `
Array [
@@ -10011,9 +10052,14 @@ Array [
class="ant-input"
placeholder="can resize"
/>
+
+ 0 / 100
+
,
@@ -10022,6 +10068,11 @@ Array [
placeholder="disable resize"
style="resize:none"
/>
+
+ 0 / 100
+
,
]
`;
diff --git a/components/input/__tests__/__snapshots__/demo.test.ts.snap b/components/input/__tests__/__snapshots__/demo.test.ts.snap
index 41e2eb67b8..71294465c6 100644
--- a/components/input/__tests__/__snapshots__/demo.test.ts.snap
+++ b/components/input/__tests__/__snapshots__/demo.test.ts.snap
@@ -1103,31 +1103,40 @@ Array [
,
,
-
-
-
+
+
+
+
+
+
+
,
]
@@ -1195,31 +1204,40 @@ exports[`renders ./components/input/demo/borderless-debug.tsx correctly 1`] = `
placeholder="Unbordered"
/>
-
-
-
+
+
+
+
+
+
+
-
-
-
+
+
+
+
+
+
+
@@ -3455,12 +3482,17 @@ Array [
,
,
+
+ 0 / 100
+
,
]
`;
@@ -3718,31 +3750,40 @@ Array [
The autoSize property applies to textarea nodes, and only the height changes automatically. In addition, autoSize can be set to an object, specifying the minimum number of rows and the maximum number of rows. The autoSize property applies to textarea nodes, and only the height changes automatically. In addition, autoSize can be set to an object, specifying the minimum number of rows and the maximum number of rows.
,
-
-
-
+
+
+
+
+
+
+
,
]
@@ -3751,7 +3792,7 @@ Array [
exports[`renders ./components/input/demo/textarea-show-count.tsx correctly 1`] = `
Array [
@@ -3759,9 +3800,14 @@ Array [
class="ant-input"
placeholder="can resize"
/>
+
+ 0 / 100
+
,
@@ -3770,6 +3816,11 @@ Array [
placeholder="disable resize"
style="resize:none"
/>
+
+ 0 / 100
+
,
]
`;
diff --git a/components/input/__tests__/__snapshots__/textarea.test.tsx.snap b/components/input/__tests__/__snapshots__/textarea.test.tsx.snap
index cfc3205bc9..08979f8f81 100644
--- a/components/input/__tests__/__snapshots__/textarea.test.tsx.snap
+++ b/components/input/__tests__/__snapshots__/textarea.test.tsx.snap
@@ -2,7 +2,7 @@
exports[`TextArea allowClear should change type when click 1`] = `
`;
exports[`TextArea allowClear should change type when click 2`] = `
-
-
-
+
+
+
+
+
+
`;
exports[`TextArea allowClear should not show icon if defaultValue is undefined, null or empty string 1`] = `
-
-
-
+
+
+
+
+
+
`;
exports[`TextArea allowClear should not show icon if defaultValue is undefined, null or empty string 2`] = `
-
-
-
+
+
+
+
+
+
`;
exports[`TextArea allowClear should not show icon if defaultValue is undefined, null or empty string 3`] = `
-
-
-
+
+
+
+
+
+
`;
exports[`TextArea allowClear should not show icon if value is undefined, null or empty string 1`] = `
-
-
-
+
+
+
+
+
+
`;
exports[`TextArea allowClear should not show icon if value is undefined, null or empty string 2`] = `
-
-
-
+
+
+
+
+
+
`;
exports[`TextArea allowClear should not show icon if value is undefined, null or empty string 3`] = `
-
-
-
+
+
+
+
+
+
`;
diff --git a/components/input/__tests__/textarea.test.tsx b/components/input/__tests__/textarea.test.tsx
index 75971e6733..d300b9cb53 100644
--- a/components/input/__tests__/textarea.test.tsx
+++ b/components/input/__tests__/textarea.test.tsx
@@ -574,4 +574,9 @@ describe('TextArea allowClear', () => {
textareaSpy.mockRestore();
});
+
+ it('should support custom clearIcon', () => {
+ const { container } = render();
+ expect(container.querySelector('.ant-input-clear-icon')?.textContent).toBe('clear');
+ });
});
diff --git a/components/input/style/index.ts b/components/input/style/index.ts
index 03cfd70a86..5bc75214ed 100644
--- a/components/input/style/index.ts
+++ b/components/input/style/index.ts
@@ -562,19 +562,6 @@ const genAllowClearStyle = (token: InputToken): CSSObject => {
margin: `0 ${token.inputAffixPadding}px`,
},
},
-
- // ======================= TextArea ========================
- '&-textarea-with-clear-btn': {
- padding: '0 !important',
- border: '0 !important',
-
- [`${componentCls}-clear-icon`]: {
- position: 'absolute',
- insetBlockStart: token.paddingXS,
- insetInlineEnd: token.paddingXS,
- zIndex: 1,
- },
- },
};
};
@@ -870,53 +857,79 @@ export function initInputToken(token: T): I
}
const genTextAreaStyle: GenerateStyle = (token) => {
- const { componentCls, inputPaddingHorizontal, paddingLG } = token;
+ const { componentCls, paddingLG } = token;
const textareaPrefixCls = `${componentCls}-textarea`;
return {
[textareaPrefixCls]: {
position: 'relative',
- [`${textareaPrefixCls}-suffix`]: {
- position: 'absolute',
- top: 0,
- insetInlineEnd: inputPaddingHorizontal,
- bottom: 0,
- zIndex: 1,
- display: 'inline-flex',
- alignItems: 'center',
- margin: 'auto',
- },
-
- [`&-status-error,
- &-status-warning,
- &-status-success,
- &-status-validating`]: {
- [`&${textareaPrefixCls}-has-feedback`]: {
- [`${componentCls}`]: {
- paddingInlineEnd: paddingLG,
- },
- },
- },
-
'&-show-count': {
// https://github.com/ant-design/ant-design/issues/33049
[`> ${componentCls}`]: {
height: '100%',
},
- '&::after': {
+ [`${componentCls}-data-count`]: {
color: token.colorTextDescription,
whiteSpace: 'nowrap',
- content: 'attr(data-count)',
pointerEvents: 'none',
float: 'right',
+ marginBottom: -token.fontSize * token.lineHeight,
+ },
+
+ '&-rtl': {
+ [`${componentCls}-data-count`]: {
+ float: 'left',
+ },
},
},
- '&-rtl': {
- '&::after': {
- float: 'left',
+ [`&-affix-wrapper${textareaPrefixCls}-has-feedback`]: {
+ [`${componentCls}`]: {
+ paddingInlineEnd: paddingLG,
+ },
+ },
+
+ [`&-affix-wrapper${componentCls}-affix-wrapper`]: {
+ padding: 0,
+
+ [`> textarea${componentCls}`]: {
+ fontSize: 'inherit',
+ border: 'none',
+ outline: 'none',
+
+ '&:focus': {
+ boxShadow: 'none !important',
+ },
+ },
+
+ [`${componentCls}-suffix`]: {
+ margin: 0,
+
+ '> *:not(:last-child)': {
+ marginInline: 0,
+ },
+
+ // Clear Icon
+ [`${componentCls}-clear-icon`]: {
+ position: 'absolute',
+ insetInlineEnd: token.paddingXS,
+ insetBlockStart: token.paddingXS,
+ },
+
+ // Feedback Icon
+ [`${textareaPrefixCls}-suffix`]: {
+ position: 'absolute',
+ top: 0,
+ insetInlineEnd: token.inputPaddingHorizontal,
+ bottom: 0,
+ zIndex: 1,
+ display: 'inline-flex',
+ alignItems: 'center',
+ margin: 'auto',
+ pointerEvents: 'none',
+ },
},
},
},
diff --git a/components/input/utils.ts b/components/input/utils.ts
index 8963d8fb35..802cd23ef5 100644
--- a/components/input/utils.ts
+++ b/components/input/utils.ts
@@ -1,7 +1,6 @@
-import type { ClearableInputProps } from './ClearableLabeledInput';
import type { InputProps } from './Input';
// eslint-disable-next-line import/prefer-default-export
-export function hasPrefixSuffix(props: InputProps | ClearableInputProps) {
+export function hasPrefixSuffix(props: InputProps) {
return !!(props.prefix || props.suffix || props.allowClear);
}
diff --git a/components/mentions/index.tsx b/components/mentions/index.tsx
index 7d263264f6..cd33acc828 100644
--- a/components/mentions/index.tsx
+++ b/components/mentions/index.tsx
@@ -35,7 +35,7 @@ export interface OptionProps {
[key: string]: any;
}
-export interface MentionProps extends RcMentionsProps {
+export interface MentionProps extends Omit {
loading?: boolean;
status?: InputStatus;
options?: MentionsOptionProps[];
@@ -44,10 +44,6 @@ export interface MentionProps extends RcMentionsProps {
export interface MentionsRef extends RcMentionsRef {}
-export interface MentionState {
- focused: boolean;
-}
-
interface MentionsConfig {
prefix?: string | string[];
split?: string;
@@ -179,27 +175,15 @@ const InternalMentions: React.ForwardRefRenderFunction
{getOptions()}
);
- if (hasFeedback) {
- return (
-
- {mentions}
- {feedbackIcon}
-
- );
- }
-
return wrapSSR(mentions);
};
diff --git a/components/typography/Base/index.tsx b/components/typography/Base/index.tsx
index 2652860d80..04dd426d21 100644
--- a/components/typography/Base/index.tsx
+++ b/components/typography/Base/index.tsx
@@ -4,7 +4,7 @@ import EditOutlined from '@ant-design/icons/EditOutlined';
import classNames from 'classnames';
import copy from 'copy-to-clipboard';
import ResizeObserver from 'rc-resize-observer';
-import type { AutoSizeType } from 'rc-textarea/lib/ResizableTextArea';
+import type { AutoSizeType } from 'rc-textarea';
import toArray from 'rc-util/lib/Children/toArray';
import useIsomorphicLayoutEffect from 'rc-util/lib/hooks/useLayoutEffect';
import useMergedState from 'rc-util/lib/hooks/useMergedState';
diff --git a/components/typography/Editable.tsx b/components/typography/Editable.tsx
index b26c4e5bbb..e80dd76d11 100644
--- a/components/typography/Editable.tsx
+++ b/components/typography/Editable.tsx
@@ -1,6 +1,6 @@
import EnterOutlined from '@ant-design/icons/EnterOutlined';
import classNames from 'classnames';
-import type { AutoSizeType } from 'rc-textarea/lib/ResizableTextArea';
+import type { AutoSizeType } from 'rc-textarea';
import KeyCode from 'rc-util/lib/KeyCode';
import * as React from 'react';
import type { DirectionType } from '../config-provider';
diff --git a/package.json b/package.json
index 8de1bdbc52..d33ced88a7 100644
--- a/package.json
+++ b/package.json
@@ -127,9 +127,9 @@
"rc-dropdown": "~4.0.0",
"rc-field-form": "~1.27.0",
"rc-image": "~5.13.0",
- "rc-input": "~0.1.4",
+ "rc-input": "~0.2.1",
"rc-input-number": "~7.4.0",
- "rc-mentions": "~1.13.1",
+ "rc-mentions": "~2.0.0",
"rc-menu": "~9.8.0",
"rc-motion": "^2.6.1",
"rc-notification": "~5.0.0",
@@ -145,7 +145,7 @@
"rc-switch": "~4.0.0",
"rc-table": "~7.30.2",
"rc-tabs": "~12.5.1",
- "rc-textarea": "~0.4.5",
+ "rc-textarea": "~1.0.0",
"rc-tooltip": "~5.2.0",
"rc-tree": "~5.7.0",
"rc-tree-select": "~5.6.0",