@@ -21,68 +21,57 @@ type CreateOptionsCreateableFunction = (
2121 options : CreateOptionsOption [ ] ,
2222) => CreateSelectValue | CreateSelectValue [ ] ;
2323
24- type CreateOptionsFormatFunction = < Type extends "value" | "label" | "text" > (
24+ type CreateOptionsFormatFunction = (
2525 value : CreateSelectValue ,
26- type : Type ,
26+ type : "value" | "label" ,
2727 meta : { highlight ?: JSXElement ; prefix ?: string } ,
28- ) => Type extends "text" ? string : JSXElement ;
29-
30- const hasToString = ( value : any ) : value is { toString : ( ) => string } =>
31- typeof value . toString === "function" ;
32-
33- const defaultFormat : CreateOptionsFormatFunction = ( value , type , meta ) => {
34- switch ( type ) {
35- case "value" :
36- return value ;
37- case "text" :
38- if ( ! hasToString ( value ) ) {
39- throw new Error (
40- "Value must have a 'toString' method for text extraction." ,
41- ) ;
42- }
43- return value . toString ( ) ;
44- case "label" :
45- return (
46- < >
47- { meta ?. prefix }
48- { meta ?. highlight ?? value }
49- </ >
50- ) ;
51- }
52- } ;
53-
54- type CreateOptionsConfig = (
55- | {
56- key ?: string ;
57- format ?: never ;
58- }
59- | {
60- format ?: CreateOptionsFormatFunction ;
61- key ?: never ;
62- }
63- ) & {
28+ ) => JSXElement ;
29+
30+ const defaultFormat : CreateOptionsFormatFunction = ( value , type , meta ) =>
31+ type === "label" ? (
32+ < >
33+ { meta . prefix }
34+ { meta . highlight ?? value }
35+ </ >
36+ ) : (
37+ value
38+ ) ;
39+
40+ interface CreateOptionsConfig {
41+ key ?: string ;
42+ format ?: CreateOptionsFormatFunction ;
6443 filterable ?: boolean | CreateOptionsFilterableFunction ;
6544 createable ?: boolean | CreateOptionsCreateableFunction ;
45+ extractText ?: ( value : CreateSelectValue ) => string ;
6646 disable ?: ( value : CreateSelectValue ) => boolean ;
67- } ;
47+ }
6848
6949const createOptions = (
7050 values : CreateSelectValue [ ] | ( ( inputValue : string ) => CreateSelectValue [ ] ) ,
7151 userConfig ?: CreateOptionsConfig ,
7252) => {
7353 const config : CreateOptionsConfig &
74- Required < Pick < CreateOptionsConfig , "filterable" | "disable" > > =
75- Object . assign (
76- {
77- filterable : true ,
78- disable : ( ) => false ,
79- } ,
80- userConfig || { } ,
81- ) ;
54+ Required <
55+ Pick < CreateOptionsConfig , "extractText" | "filterable" | "disable" >
56+ > = Object . assign (
57+ {
58+ extractText : ( value : CreateSelectValue ) =>
59+ value . toString ? value . toString ( ) : value ,
60+ filterable : true ,
61+ disable : ( ) => false ,
62+ } ,
63+ userConfig || { } ,
64+ ) ;
8265
83- if ( config . key && config . format ) {
66+ if (
67+ config . key &&
68+ userConfig &&
69+ ( userConfig . format || userConfig . disable || userConfig . extractText )
70+ ) {
8471 console . warn (
85- "The 'key' option is ignored when 'format' option is specified." ,
72+ "When 'key' option is specified, custom 'format', 'disable' and" ,
73+ "'extractText' functions will receive the keyed value rather than the" ,
74+ "full object." ,
8675 ) ;
8776 }
8877
@@ -98,26 +87,32 @@ const createOptions = (
9887 ) ;
9988 }
10089
101- const formatter : CreateOptionsFormatFunction = (
102- value ,
103- type ,
104- meta : { highlight ?: JSXElement ; prefix ?: string } ,
105- ) => {
90+ const resolveValue = ( value : CreateSelectValue ) =>
91+ config . key ? value [ config . key ] : value ;
92+
93+ const extractText = ( value : CreateSelectValue ) =>
94+ config . extractText ( resolveValue ( value ) ) ;
95+
96+ const format : CreateOptionsFormatFunction = ( value , type , meta ) => {
97+ const resolvedValue = resolveValue ( value ) ;
10698 return config . format
107- ? config . format ( value , type , meta )
108- : defaultFormat ( config . key ? value [ config . key ] : value , type , meta ) ;
99+ ? config . format ( resolvedValue , type , meta )
100+ : defaultFormat ( resolvedValue , type , meta ) ;
109101 } ;
110102
103+ const disable = ( value : CreateSelectValue ) =>
104+ config . disable ( resolveValue ( value ) ) ;
105+
111106 const options = ( inputValue : string ) => {
112107 const initialValues =
113108 typeof values === "function" ? values ( inputValue ) : values ;
114109
115110 let createdOptions : CreateOptionsOption [ ] = initialValues . map ( ( value ) => {
116111 return {
117- value : value ,
118- label : formatter ( value , "label" , { } ) ,
119- text : formatter ( value , "text" , { } ) ,
120- disabled : config . disable ( value ) ,
112+ value,
113+ label : format ( value , "label" , { } ) ,
114+ text : extractText ( value ) ,
115+ disabled : disable ( value ) ,
121116 } ;
122117 } ) ;
123118
@@ -128,7 +123,7 @@ const createOptions = (
128123 createdOptions = fuzzySort ( inputValue , createdOptions , "text" ) . map (
129124 ( result ) => ( {
130125 ...result . item ,
131- label : formatter ( result . item . value , "label" , {
126+ label : format ( result . item . value , "label" , {
132127 highlight : fuzzyHighlight ( result ) ,
133128 } ) ,
134129 } ) ,
@@ -162,10 +157,9 @@ const createOptions = (
162157 ) ;
163158 }
164159 } else if ( ! exists ) {
165- valueOrValues =
166- config . key && ! config . format
167- ? { [ config . key ] : trimmedValue }
168- : trimmedValue ;
160+ valueOrValues = config . key
161+ ? { [ config . key ] : trimmedValue }
162+ : trimmedValue ;
169163 }
170164
171165 if ( valueOrValues !== undefined ) {
@@ -177,8 +171,8 @@ const createOptions = (
177171 for ( const value of values ) {
178172 optionsToAdd . push ( {
179173 value : value ,
180- label : formatter ( value , "label" , { prefix : "Create " } ) ,
181- text : formatter ( value , "text" , { } ) ,
174+ label : format ( value , "label" , { prefix : "Create " } ) ,
175+ text : extractText ( value ) ,
182176 disabled : false ,
183177 } ) ;
184178 }
@@ -191,23 +185,17 @@ const createOptions = (
191185 return createdOptions ;
192186 } ;
193187
194- const optionToValue = ( option : CreateOptionsOption ) => option . value ;
195-
196- const format = (
197- item : CreateOptionsOption | CreateSelectValue ,
198- type : "option" | "value" ,
199- ) =>
200- type === "option"
201- ? ( item as CreateOptionsOption ) . label
202- : formatter ( item , "value" , { } ) ;
203-
204- const isOptionDisabled = ( option : CreateOptionsOption ) => option . disabled ;
205-
206188 return {
207189 options,
208- optionToValue,
209- isOptionDisabled,
210- format,
190+ optionToValue : ( option : CreateOptionsOption ) => option . value ,
191+ isOptionDisabled : ( option : CreateOptionsOption ) => option . disabled ,
192+ format : (
193+ item : CreateOptionsOption | CreateSelectValue ,
194+ type : "option" | "value" ,
195+ ) =>
196+ type === "option"
197+ ? ( item as CreateOptionsOption ) . label
198+ : format ( item as CreateSelectValue , "value" , { } ) ,
211199 } ;
212200} ;
213201
0 commit comments