@@ -11,6 +11,7 @@ import * as React from 'react';
11
11
import { useState , useRef , useEffect , useMemo } from 'react' ;
12
12
import KeyCode from 'rc-util/lib/KeyCode' ;
13
13
import isMobile from 'rc-util/lib/isMobile' ;
14
+ import { composeRef } from 'rc-util/lib/ref' ;
14
15
import classNames from 'classnames' ;
15
16
import useMergedState from 'rc-util/lib/hooks/useMergedState' ;
16
17
import type { ScrollTo } from 'rc-virtual-list/lib/List' ;
@@ -133,6 +134,8 @@ export interface SelectProps<OptionsType extends object[], ValueType> extends Re
133
134
backfill ?: boolean ;
134
135
/** @private Internal usage. Do not use in your production. */
135
136
getInputElement ?: ( ) => JSX . Element ;
137
+ /** @private Internal usage. Do not use in your production. */
138
+ getRawInputElement ?: ( ) => JSX . Element ;
136
139
optionLabelProp ?: string ;
137
140
maxTagTextLength ?: number ;
138
141
maxTagCount ?: number | 'responsive' ;
@@ -289,6 +292,7 @@ export default function generateSelector<
289
292
backfill,
290
293
tabIndex,
291
294
getInputElement,
295
+ getRawInputElement,
292
296
getPopupContainer,
293
297
294
298
// Dropdown
@@ -635,9 +639,13 @@ export default function generateSelector<
635
639
} ;
636
640
637
641
// ============================= Input ==============================
638
- // Only works in `combobox` or `rc-cascader`
642
+ // Only works in `combobox`
639
643
const customizeInputElement : React . ReactElement =
640
- ( typeof getInputElement === 'function' && getInputElement ( ) ) || null ;
644
+ ( mode === 'combobox' && typeof getInputElement === 'function' && getInputElement ( ) ) || null ;
645
+
646
+ // Used for customize replacement for `rc-cascader`
647
+ const customizeRawInputElement : React . ReactElement =
648
+ typeof getRawInputElement === 'function' && getRawInputElement ( ) ;
641
649
642
650
// ============================== Open ==============================
643
651
const [ innerOpen , setInnerOpen ] = useMergedState < boolean > ( undefined , {
@@ -666,6 +674,14 @@ export default function generateSelector<
666
674
}
667
675
} ;
668
676
677
+ // Used for raw custom input trigger
678
+ let onTriggerVisibleChange : null | ( ( newOpen : boolean ) => void ) ;
679
+ if ( customizeRawInputElement ) {
680
+ onTriggerVisibleChange = ( newOpen : boolean ) => {
681
+ onToggleOpen ( newOpen ) ;
682
+ } ;
683
+ }
684
+
669
685
useSelectTriggerControl (
670
686
[ containerRef . current , triggerRef . current && triggerRef . current . getPopupElement ( ) ] ,
671
687
triggerOpen ,
@@ -931,8 +947,8 @@ export default function generateSelector<
931
947
932
948
useLayoutEffect ( ( ) => {
933
949
if ( triggerOpen ) {
934
- const newWidth = Math . ceil ( containerRef . current . offsetWidth ) ;
935
- if ( containerWidth !== newWidth ) {
950
+ const newWidth = Math . ceil ( containerRef . current ? .offsetWidth ) ;
951
+ if ( containerWidth !== newWidth && ! Number . isNaN ( newWidth ) ) {
936
952
setContainerWidth ( newWidth ) ;
937
953
}
938
954
}
@@ -1034,6 +1050,63 @@ export default function generateSelector<
1034
1050
[ `${ prefixCls } -show-search` ] : mergedShowSearch ,
1035
1051
} ) ;
1036
1052
1053
+ const selectorNode = (
1054
+ < SelectTrigger
1055
+ ref = { triggerRef }
1056
+ disabled = { disabled }
1057
+ prefixCls = { prefixCls }
1058
+ visible = { triggerOpen }
1059
+ popupElement = { popupNode }
1060
+ containerWidth = { containerWidth }
1061
+ animation = { animation }
1062
+ transitionName = { transitionName }
1063
+ dropdownStyle = { dropdownStyle }
1064
+ dropdownClassName = { dropdownClassName }
1065
+ direction = { direction }
1066
+ dropdownMatchSelectWidth = { dropdownMatchSelectWidth }
1067
+ dropdownRender = { dropdownRender }
1068
+ dropdownAlign = { dropdownAlign }
1069
+ getPopupContainer = { getPopupContainer }
1070
+ empty = { ! mergedOptions . length }
1071
+ getTriggerDOMNode = { ( ) => selectorDomRef . current }
1072
+ onPopupVisibleChange = { onTriggerVisibleChange }
1073
+ >
1074
+ { customizeRawInputElement ? (
1075
+ React . cloneElement ( customizeRawInputElement , {
1076
+ ref : composeRef ( selectorDomRef , customizeRawInputElement . props . ref ) ,
1077
+ } )
1078
+ ) : (
1079
+ < Selector
1080
+ { ...props }
1081
+ domRef = { selectorDomRef }
1082
+ prefixCls = { prefixCls }
1083
+ inputElement = { customizeInputElement }
1084
+ ref = { selectorRef }
1085
+ id = { mergedId }
1086
+ showSearch = { mergedShowSearch }
1087
+ mode = { mode }
1088
+ accessibilityIndex = { accessibilityIndex }
1089
+ multiple = { isMultiple }
1090
+ tagRender = { tagRender }
1091
+ values = { displayValues }
1092
+ open = { mergedOpen }
1093
+ onToggleOpen = { onToggleOpen }
1094
+ searchValue = { mergedSearchValue }
1095
+ activeValue = { activeValue }
1096
+ onSearch = { triggerSearch }
1097
+ onSearchSubmit = { onSearchSubmit }
1098
+ onSelect = { onInternalSelectionSelect }
1099
+ tokenWithEnter = { tokenWithEnter }
1100
+ />
1101
+ ) }
1102
+ </ SelectTrigger >
1103
+ ) ;
1104
+
1105
+ // Render raw
1106
+ if ( customizeRawInputElement ) {
1107
+ return selectorNode ;
1108
+ }
1109
+
1037
1110
return (
1038
1111
< div
1039
1112
className = { mergedClassName }
@@ -1060,48 +1133,7 @@ export default function generateSelector<
1060
1133
{ `${ mergedRawValue . join ( ', ' ) } ` }
1061
1134
</ span >
1062
1135
) }
1063
- < SelectTrigger
1064
- ref = { triggerRef }
1065
- disabled = { disabled }
1066
- prefixCls = { prefixCls }
1067
- visible = { triggerOpen }
1068
- popupElement = { popupNode }
1069
- containerWidth = { containerWidth }
1070
- animation = { animation }
1071
- transitionName = { transitionName }
1072
- dropdownStyle = { dropdownStyle }
1073
- dropdownClassName = { dropdownClassName }
1074
- direction = { direction }
1075
- dropdownMatchSelectWidth = { dropdownMatchSelectWidth }
1076
- dropdownRender = { dropdownRender }
1077
- dropdownAlign = { dropdownAlign }
1078
- getPopupContainer = { getPopupContainer }
1079
- empty = { ! mergedOptions . length }
1080
- getTriggerDOMNode = { ( ) => selectorDomRef . current }
1081
- >
1082
- < Selector
1083
- { ...props }
1084
- domRef = { selectorDomRef }
1085
- prefixCls = { prefixCls }
1086
- inputElement = { customizeInputElement }
1087
- ref = { selectorRef }
1088
- id = { mergedId }
1089
- showSearch = { mergedShowSearch }
1090
- mode = { mode }
1091
- accessibilityIndex = { accessibilityIndex }
1092
- multiple = { isMultiple }
1093
- tagRender = { tagRender }
1094
- values = { displayValues }
1095
- open = { mergedOpen }
1096
- onToggleOpen = { onToggleOpen }
1097
- searchValue = { mergedSearchValue }
1098
- activeValue = { activeValue }
1099
- onSearch = { triggerSearch }
1100
- onSearchSubmit = { onSearchSubmit }
1101
- onSelect = { onInternalSelectionSelect }
1102
- tokenWithEnter = { tokenWithEnter }
1103
- />
1104
- </ SelectTrigger >
1136
+ { selectorNode }
1105
1137
1106
1138
{ arrowNode }
1107
1139
{ clearNode }
0 commit comments