{
+ const [value, setValue] = React.useState('');
+
+ return (
+
+
Sender with Length Limit
+
{
+ console.log('Submit:', msg);
+ setValue('');
+ }}
+ />
+ Custom Count Display
+ (
+ maxLength * 0.8 ? 'red' : '#ccc',
+ fontSize: 10,
+ marginBottom: 4,
+ }}
+ >
+ {maxLength
+ ? `Entered ${count} characters, limit ${maxLength} characters`
+ : `Entered ${count} characters`}
+
+ )}
+ placeholder="Custom count display..."
+ onSubmit={(msg) => {
+ console.log('Submit:', msg);
+ setValue('');
+ }}
+ />
+ Count Only, No Length Limit
+ {
+ console.log('Submit:', msg);
+ setValue('');
+ }}
+ />
+
+ );
+};
+
+export default App;
diff --git a/packages/x/components/sender/index.en-US.md b/packages/x/components/sender/index.en-US.md
index 4a47bad68..a4c313e9a 100644
--- a/packages/x/components/sender/index.en-US.md
+++ b/packages/x/components/sender/index.en-US.md
@@ -31,6 +31,7 @@ coverDark: https://mdn.alipayobjects.com/huamei_iwk9zp/afts/img/A*cOfrS4fVkOMAAA
Custom Footer Content
Style Adjustment
Paste Files
+
Max Length
## API
@@ -50,6 +51,8 @@ Common props ref:[Common props](/docs/react/common-props)
| header | Header panel | React.ReactNode \| false \| (oriNode: React.ReactNode, info: { components: ActionsComponents; }) => React.ReactNode \| false | false | - |
| prefix | Prefix content | React.ReactNode \| false \| (oriNode: React.ReactNode, info: { components: ActionsComponents; }) => React.ReactNode \| false | false | - |
| footer | Footer content | React.ReactNode \| false \| (oriNode: React.ReactNode, info: { components: ActionsComponents; }) => React.ReactNode \| false | false | - |
+| maxLength | Maximum length of input content | number | - | - |
+| showCount | Whether to display character count, supports custom rendering | boolean \| ((info: { value: string; count: number; maxLength?: number }) => React.ReactNode) | false | - |
| readOnly | Whether to make the input box read-only | boolean | false | - |
| rootClassName | Root element style class | string | - | - |
| styles | Semantic style definition | [See below](#semantic-dom) | - | - |
diff --git a/packages/x/components/sender/index.tsx b/packages/x/components/sender/index.tsx
index 2e7f71cd1..941b18f5f 100644
--- a/packages/x/components/sender/index.tsx
+++ b/packages/x/components/sender/index.tsx
@@ -79,6 +79,7 @@ const ForwardSender = React.forwardRef
((props, ref) => {
placeholder,
onFocus,
onBlur,
+ showCount,
skill,
...restProps
} = props;
@@ -141,7 +142,7 @@ const ForwardSender = React.forwardRef((props, ref) => {
const [innerValue, setInnerValue] = useMergedState(defaultValue || '', {
value,
});
-
+ const currentCount = innerValue.length;
const triggerValueChange: SenderProps['onChange'] = (nextValue, event, slotConfig) => {
if (slotConfig) {
setInnerValue(nextValue);
@@ -221,6 +222,26 @@ const ForwardSender = React.forwardRef((props, ref) => {
: header || null;
// ============================ Footer ============================
+ const renderCount = () => {
+ if (!showCount) return null;
+
+ const countInfo = {
+ value: innerValue,
+ count: currentCount,
+ maxLength: restProps.maxLength,
+ };
+
+ if (typeof showCount === 'function') {
+ return showCount(countInfo);
+ }
+
+ return (
+
+ {restProps.maxLength ? `${currentCount}/${restProps.maxLength}` : currentCount}
+
+ );
+ };
+
const footerNode =
typeof footer === 'function'
? footer(actionNode, { components: sharedRenderComponents })
@@ -383,6 +404,7 @@ const ForwardSender = React.forwardRef((props, ref) => {
)}
+ {showCount && renderCount()}
);
});
diff --git a/packages/x/components/sender/index.zh-CN.md b/packages/x/components/sender/index.zh-CN.md
index c72dbfd4f..a7fa3e710 100644
--- a/packages/x/components/sender/index.zh-CN.md
+++ b/packages/x/components/sender/index.zh-CN.md
@@ -32,6 +32,7 @@ coverDark: https://mdn.alipayobjects.com/huamei_iwk9zp/afts/img/A*cOfrS4fVkOMAAA