11import clsx from 'classnames' ;
2- import type { FC , ReactElement } from 'react' ;
2+ import type { FC , ReactElement , ReactNode } from 'react' ;
33import React , { cloneElement , useRef } from 'react' ;
44import type { BaseInputProps } from './interface' ;
55import { hasAddon , hasPrefixSuffix } from './utils/commonUtils' ;
66
77const BaseInput : FC < BaseInputProps > = ( props ) => {
88 const {
9- inputElement,
9+ inputElement : inputEl ,
10+ children,
1011 prefixCls,
1112 prefix,
1213 suffix,
@@ -29,6 +30,8 @@ const BaseInput: FC<BaseInputProps> = (props) => {
2930 components,
3031 } = props ;
3132
33+ const inputElement = children ?? inputEl ;
34+
3235 const AffixWrapperComponent = components ?. affixWrapper || 'span' ;
3336 const GroupWrapperComponent = components ?. groupWrapper || 'span' ;
3437 const WrapperComponent = components ?. wrapper || 'span' ;
@@ -42,63 +45,51 @@ const BaseInput: FC<BaseInputProps> = (props) => {
4245 }
4346 } ;
4447
45- // ================== Clear Icon ================== //
46- const getClearIcon = ( ) => {
47- if ( ! allowClear ) {
48- return null ;
49- }
50- const needClear = ! disabled && ! readOnly && value ;
51- const clearIconCls = `${ prefixCls } -clear-icon` ;
52- const iconNode =
53- typeof allowClear === 'object' && allowClear ?. clearIcon
54- ? allowClear . clearIcon
55- : '✖' ;
56-
57- return (
58- < span
59- onClick = { handleReset }
60- // Do not trigger onBlur when clear input
61- // https://github.com/ant-design/ant-design/issues/31200
62- onMouseDown = { ( e ) => e . preventDefault ( ) }
63- className = { clsx ( clearIconCls , {
64- [ `${ clearIconCls } -hidden` ] : ! needClear ,
65- [ `${ clearIconCls } -has-suffix` ] : ! ! suffix ,
66- } ) }
67- role = "button"
68- tabIndex = { - 1 }
69- >
70- { iconNode }
71- </ span >
72- ) ;
73- } ;
74-
7548 let element : ReactElement = cloneElement ( inputElement , {
7649 value,
77- hidden,
78- className :
79- clsx (
80- inputElement . props ?. className ,
81- ! hasPrefixSuffix ( props ) && ! hasAddon ( props ) && className ,
82- ) || null ,
83- style : {
84- ...inputElement . props ?. style ,
85- ...( ! hasPrefixSuffix ( props ) && ! hasAddon ( props ) ? style : { } ) ,
86- } ,
8750 } ) ;
8851
8952 // ================== Prefix & Suffix ================== //
9053 if ( hasPrefixSuffix ( props ) ) {
54+ // ================== Clear Icon ================== //
55+ let clearIcon : ReactNode = null ;
56+ if ( allowClear ) {
57+ const needClear = ! disabled && ! readOnly && value ;
58+ const clearIconCls = `${ prefixCls } -clear-icon` ;
59+ const iconNode =
60+ typeof allowClear === 'object' && allowClear ?. clearIcon
61+ ? allowClear . clearIcon
62+ : '✖' ;
63+
64+ clearIcon = (
65+ < span
66+ onClick = { handleReset }
67+ // Do not trigger onBlur when clear input
68+ // https://github.com/ant-design/ant-design/issues/31200
69+ onMouseDown = { ( e ) => e . preventDefault ( ) }
70+ className = { clsx ( clearIconCls , {
71+ [ `${ clearIconCls } -hidden` ] : ! needClear ,
72+ [ `${ clearIconCls } -has-suffix` ] : ! ! suffix ,
73+ } ) }
74+ role = "button"
75+ tabIndex = { - 1 }
76+ >
77+ { iconNode }
78+ </ span >
79+ ) ;
80+ }
81+
9182 const affixWrapperPrefixCls = `${ prefixCls } -affix-wrapper` ;
9283 const affixWrapperCls = clsx (
9384 affixWrapperPrefixCls ,
9485 {
95- [ `${ affixWrapperPrefixCls } -disabled` ] : disabled ,
96- [ `${ affixWrapperPrefixCls } -focused` ] : focused ,
86+ [ `${ prefixCls } -disabled` ] : disabled ,
87+ [ `${ affixWrapperPrefixCls } -disabled` ] : disabled , // Not used, but keep it
88+ [ `${ affixWrapperPrefixCls } -focused` ] : focused , // Not used, but keep it
9789 [ `${ affixWrapperPrefixCls } -readonly` ] : readOnly ,
9890 [ `${ affixWrapperPrefixCls } -input-with-clear-btn` ] :
9991 suffix && allowClear && value ,
10092 } ,
101- ! hasAddon ( props ) && className ,
10293 classes ?. affixWrapper ,
10394 classNames ?. affixWrapper ,
10495 ) ;
@@ -108,19 +99,15 @@ const BaseInput: FC<BaseInputProps> = (props) => {
10899 className = { clsx ( `${ prefixCls } -suffix` , classNames ?. suffix ) }
109100 style = { styles ?. suffix }
110101 >
111- { getClearIcon ( ) }
102+ { clearIcon }
112103 { suffix }
113104 </ span >
114105 ) ;
115106
116107 element = (
117108 < AffixWrapperComponent
118109 className = { affixWrapperCls }
119- style = { {
120- ...( ! hasAddon ( props ) ? style : undefined ) ,
121- ...styles ?. affixWrapper ,
122- } }
123- hidden = { ! hasAddon ( props ) && hidden }
110+ style = { styles ?. affixWrapper }
124111 onClick = { onInputClick }
125112 { ...dataAttrs ?. affixWrapper }
126113 ref = { containerRef }
@@ -133,10 +120,7 @@ const BaseInput: FC<BaseInputProps> = (props) => {
133120 { prefix }
134121 </ span >
135122 ) }
136- { cloneElement ( inputElement , {
137- value,
138- hidden : null ,
139- } ) }
123+ { element }
140124 { suffixNode }
141125 </ AffixWrapperComponent >
142126 ) ;
@@ -151,31 +135,26 @@ const BaseInput: FC<BaseInputProps> = (props) => {
151135 `${ prefixCls } -wrapper` ,
152136 wrapperCls ,
153137 classes ?. wrapper ,
138+ classNames ?. wrapper ,
154139 ) ;
155140
156141 const mergedGroupClassName = clsx (
157142 `${ prefixCls } -group-wrapper` ,
158- className ,
159143 classes ?. group ,
144+ classNames ?. groupWrapper ,
160145 ) ;
161146
162147 // Need another wrapper for changing display:table to display:inline-block
163148 // and put style prop in wrapper
164- return (
165- < GroupWrapperComponent
166- className = { mergedGroupClassName }
167- style = { style }
168- hidden = { hidden }
169- >
149+ element = (
150+ < GroupWrapperComponent className = { mergedGroupClassName } >
170151 < WrapperComponent className = { mergedWrapperClassName } >
171152 { addonBefore && (
172153 < GroupAddonComponent className = { addonCls } >
173154 { addonBefore }
174155 </ GroupAddonComponent >
175156 ) }
176- { cloneElement ( element , {
177- hidden : null ,
178- } ) }
157+ { element }
179158 { addonAfter && (
180159 < GroupAddonComponent className = { addonCls } >
181160 { addonAfter }
@@ -185,7 +164,16 @@ const BaseInput: FC<BaseInputProps> = (props) => {
185164 </ GroupWrapperComponent >
186165 ) ;
187166 }
188- return element ;
167+
168+ // `className` and `style` are always on the root element
169+ return React . cloneElement ( element , {
170+ className : clsx ( element . props ?. className , className ) || null ,
171+ style : {
172+ ...element . props ?. style ,
173+ ...style ,
174+ } ,
175+ hidden,
176+ } ) ;
189177} ;
190178
191179export default BaseInput ;
0 commit comments