@@ -10,13 +10,14 @@ interface SignatureOption {
1010
1111interface SignatureSelectorProps {
1212 options : SignatureOption [ ] ;
13- value : string ;
14- onChange : ( val : string ) => void ;
13+ value : string | string [ ] ;
14+ onChange : ( val : string | string [ ] ) => void ;
1515 setAbi ?: ( abi : string ) => void ;
1616 placeholder ?: string ;
1717 disabled ?: boolean ;
1818 secondaryTextFormatter ?: ( sig : SignatureOption ) => string ;
1919 className ?: string ;
20+ multiSelect ?: boolean ;
2021}
2122
2223export function SignatureSelector ( {
@@ -28,6 +29,7 @@ export function SignatureSelector({
2829 disabled,
2930 secondaryTextFormatter,
3031 className,
32+ multiSelect = false ,
3133} : SignatureSelectorProps ) {
3234 const [ searchValue , setSearchValue ] = useState ( "" ) ;
3335 const inputRef = useRef < HTMLInputElement > ( null ) ;
@@ -42,38 +44,79 @@ export function SignatureSelector({
4244 } ) ) ;
4345 } , [ options , secondaryTextFormatter ] ) ;
4446
45- // Check if the current value is a custom value (not in options)
46- const isCustomValue = value && ! options . some ( ( opt ) => opt . value === value ) ;
47+ // Handle both single and multi-select values
48+ const currentValues = useMemo ( ( ) : string [ ] => {
49+ if ( multiSelect ) {
50+ if ( Array . isArray ( value ) ) {
51+ return value . filter ( ( val ) : val is string => val !== undefined && val !== null ) ;
52+ } else {
53+ return value ? [ value ] : [ ] ;
54+ }
55+ } else {
56+ if ( Array . isArray ( value ) ) {
57+ return value . length > 0 && value [ 0 ] ? [ value [ 0 ] ] : [ ] ;
58+ } else {
59+ return value ? [ value ] : [ ] ;
60+ }
61+ }
62+ } , [ value , multiSelect ] ) ;
63+
64+ // Check if the current values include custom values (not in options)
65+ const customValues = useMemo ( ( ) => {
66+ return currentValues . filter ( ( val ) : val is string => val !== undefined && val !== null && ! options . some ( ( opt ) => opt . value === val ) ) ;
67+ } , [ currentValues , options ] ) ;
4768
48- // Add the custom value as an option if needed
69+ // Add the custom values as options if needed
4970 const allOptions = useMemo ( ( ) => {
50- if ( isCustomValue && value ) {
51- return [ ... formattedOptions , { label : value , value } ] ;
52- }
53- return formattedOptions ;
54- } , [ formattedOptions , isCustomValue , value ] ) ;
71+ const customOptions = customValues
72+ . filter ( val => val ) // Filter out undefined/null values
73+ . map ( val => ( { label : val ! , value : val ! } ) ) ;
74+ return [ ... formattedOptions , ... customOptions ] ;
75+ } , [ formattedOptions , customValues ] ) ;
5576
56- // Single -select MultiSelect wrapper
77+ // Multi-select or single -select MultiSelect wrapper
5778 const handleSelectedValuesChange = useCallback (
5879 ( selected : string [ ] ) => {
59- // Always use the last selected value for single-select behavior
60- const selectedValue =
61- selected . length > 0 ? ( selected [ selected . length - 1 ] ?? "" ) : "" ;
62- onChange ( selectedValue ) ;
63- const found = options . find ( ( opt ) => opt . value === selectedValue ) ;
64- if ( setAbi ) {
65- setAbi ( found ?. abi || "" ) ;
80+ if ( multiSelect ) {
81+ // Multi-select behavior
82+ onChange ( selected ) ;
83+ // For multi-select, we'll use the ABI from the first selected option that has one
84+ const firstOptionWithAbi = selected . find ( selectedValue => {
85+ const found = options . find ( ( opt ) => opt . value === selectedValue ) ;
86+ return found ?. abi ;
87+ } ) ;
88+ if ( setAbi && firstOptionWithAbi ) {
89+ const found = options . find ( ( opt ) => opt . value === firstOptionWithAbi ) ;
90+ setAbi ( found ?. abi || "" ) ;
91+ }
92+ } else {
93+ // Single-select behavior (maintain backward compatibility)
94+ const selectedValue = selected . length > 0 ? ( selected [ selected . length - 1 ] ?? "" ) : "" ;
95+ onChange ( selectedValue ) ;
96+ const found = options . find ( ( opt ) => opt . value === selectedValue ) ;
97+ if ( setAbi ) {
98+ setAbi ( found ?. abi || "" ) ;
99+ }
66100 }
67101 setSearchValue ( "" ) ;
68102 } ,
69- [ onChange , setAbi , options ] ,
103+ [ onChange , setAbi , options , multiSelect ] ,
70104 ) ;
71105
72106 // Handle custom value entry
73107 const handleInputKeyDown = ( event : React . KeyboardEvent < HTMLInputElement > ) => {
74108 if ( event . key === "Enter" && searchValue . trim ( ) ) {
75109 if ( ! options . some ( ( opt ) => opt . value === searchValue . trim ( ) ) ) {
76- onChange ( searchValue . trim ( ) ) ;
110+ if ( multiSelect ) {
111+ // Add to existing values for multi-select
112+ const currentArray = Array . isArray ( value ) ? value : ( value ? [ value ] : [ ] ) ;
113+ const filteredArray = currentArray . filter ( ( val ) : val is string => val !== undefined && val !== null ) ;
114+ const newValues = [ ...filteredArray , searchValue . trim ( ) ] ;
115+ onChange ( newValues ) ;
116+ } else {
117+ // Replace value for single-select
118+ onChange ( searchValue . trim ( ) ) ;
119+ }
77120 if ( setAbi ) setAbi ( "" ) ;
78121 setSearchValue ( "" ) ;
79122 // Optionally blur input
@@ -106,7 +149,7 @@ export function SignatureSelector({
106149 customSearchInput = { customSearchInput }
107150 customTrigger = { null }
108151 disabled = { disabled }
109- maxCount = { 1 }
152+ maxCount = { multiSelect ? 100 : 1 }
110153 onSelectedValuesChange = { handleSelectedValuesChange }
111154 options = { allOptions }
112155 overrideSearchFn = { ( option , searchTerm ) =>
@@ -116,11 +159,14 @@ export function SignatureSelector({
116159 placeholder = { placeholder }
117160 renderOption = { ( option ) => < span > { option . label } </ span > }
118161 searchPlaceholder = { placeholder }
119- selectedValues = { value ? [ value ] : [ ] }
162+ selectedValues = { currentValues }
120163 />
121- { isCustomValue && (
164+ { customValues . length > 0 && (
122165 < div className = "mt-2 rounded border border-warning-200 bg-warning-50 px-2 py-1 text-warning-700 text-xs" >
123- You entered a custom signature. Please provide the ABI below.
166+ { multiSelect
167+ ? `You entered ${ customValues . length } custom signature${ customValues . length > 1 ? 's' : '' } . Please provide the ABI below.`
168+ : "You entered a custom signature. Please provide the ABI below."
169+ }
124170 </ div >
125171 ) }
126172 </ div >
0 commit comments