@@ -3,6 +3,7 @@ import clsx from 'clsx';
33import { useSelectInputContext } from './context' ;
44import useLayoutEffect from '@rc-component/util/lib/hooks/useLayoutEffect' ;
55import useBaseProps from '../hooks/useBaseProps' ;
6+ import { composeRef } from '@rc-component/util/lib/ref' ;
67
78export interface InputProps {
89 id ?: string ;
@@ -151,41 +152,68 @@ const Input = React.forwardRef<HTMLInputElement, InputProps>((props, ref) => {
151152 } , [ syncWidth , value ] ) ;
152153
153154 // ============================= Render =============================
154- return (
155- < InputComponent
156- id = { id }
157- type = { mode === 'combobox' ? 'text' : 'search' }
158- { ...restProps }
159- ref = { inputRef }
160- style = {
161- {
162- ...styles ?. input ,
163- ...style ,
164- '--select-input-width' : widthCssVar ,
165- } as React . CSSProperties
155+ // Extract shared input props
156+ const sharedInputProps = {
157+ id,
158+ type : mode === 'combobox' ? 'text' : 'search' ,
159+ ...restProps ,
160+ ref : inputRef as React . Ref < HTMLInputElement > ,
161+ style : {
162+ ...styles ?. input ,
163+ ...style ,
164+ '--select-input-width' : widthCssVar ,
165+ } as React . CSSProperties ,
166+ autoFocus,
167+ autoComplete : autoComplete || 'off' ,
168+ className : inputCls ,
169+ disabled,
170+ value : value || '' ,
171+ onChange : handleChange ,
172+ onKeyDown : handleKeyDown ,
173+ onBlur : handleBlur ,
174+ onPaste : handlePaste ,
175+ onCompositionStart : handleCompositionStart ,
176+ onCompositionEnd : handleCompositionEnd ,
177+ // Accessibility attributes
178+ role : role || 'combobox' ,
179+ 'aria-expanded' : open || false ,
180+ 'aria-haspopup' : 'listbox' as const ,
181+ 'aria-owns' : `${ id } _list` ,
182+ 'aria-autocomplete' : 'list' as const ,
183+ 'aria-controls' : `${ id } _list` ,
184+ 'aria-activedescendant' : open ? activeDescendantId : undefined ,
185+ } ;
186+
187+ // Handle different InputComponent types
188+ if ( React . isValidElement ( InputComponent ) ) {
189+ // If InputComponent is a ReactElement, use cloneElement with merged props
190+ const existingProps : any = InputComponent . props || { } ;
191+
192+ // Start with shared props as base
193+ const mergedProps = { ...sharedInputProps , ...existingProps } ;
194+
195+ // Batch update function calls
196+ Object . keys ( existingProps ) . forEach ( ( key ) => {
197+ const existingValue = ( existingProps as any ) [ key ] ;
198+
199+ if ( typeof existingValue === 'function' ) {
200+ // Merge event handlers
201+ ( mergedProps as any ) [ key ] = ( ...args : any [ ] ) => {
202+ existingValue ( ...args ) ;
203+ ( sharedInputProps as any ) [ key ] ?.( ...args ) ;
204+ } ;
166205 }
167- autoFocus = { autoFocus }
168- autoComplete = { autoComplete || 'off' }
169- className = { inputCls }
170- disabled = { disabled }
171- value = { value || '' }
172- onChange = { handleChange }
173- onKeyDown = { handleKeyDown }
174- onBlur = { handleBlur }
175- onPaste = { handlePaste }
176- onCompositionStart = { handleCompositionStart }
177- onCompositionEnd = { handleCompositionEnd }
178- // Accessibility attributes
179- role = { role || 'combobox' }
180- aria-expanded = { open || false }
181- aria-haspopup = "listbox"
182- aria-owns = { `${ id } _list` }
183- aria-autocomplete = "list"
184- aria-controls = { `${ id } _list` }
185- aria-activedescendant = { open ? activeDescendantId : undefined }
186- // onMouseDown={onMouseDown}
187- />
188- ) ;
206+ } ) ;
207+
208+ // Update ref
209+ mergedProps . ref = composeRef ( ( InputComponent as any ) . ref , sharedInputProps . ref ) ;
210+
211+ return React . cloneElement ( InputComponent , mergedProps ) ;
212+ }
213+
214+ // If InputComponent is a component type, render normally
215+ const Component = InputComponent as React . ComponentType < any > ;
216+ return < Component { ...sharedInputProps } /> ;
189217} ) ;
190218
191219export default Input ;
0 commit comments