@@ -160,184 +160,214 @@ const ToolsTab = ({
160160 const required = isPropertyRequired ( key , inputSchema ) ;
161161 return (
162162 < div key = { key } >
163- < Label
164- htmlFor = { key }
165- className = "block text-sm font-medium text-gray-700 dark:text-gray-300"
166- >
167- { key }
168- { required && (
169- < span className = "text-red-500 ml-1" > *</ span >
170- ) }
171- </ Label >
172- { prop . type === "boolean" ? (
173- < div className = "flex items-center space-x-2 mt-2" >
174- < Checkbox
175- id = { key }
176- name = { key }
177- checked = { ! ! params [ key ] }
178- onCheckedChange = { ( checked : boolean ) =>
179- setParams ( {
180- ...params ,
181- [ key ] : checked ,
182- } )
183- }
184- />
185- < label
186- htmlFor = { key }
187- className = "text-sm font-medium text-gray-700 dark:text-gray-300"
188- >
189- { prop . description || "Toggle this option" }
190- </ label >
191- </ div >
192- ) : prop . type === "string" && prop . enum ? (
193- < Select
194- value = {
195- params [ key ] === undefined
196- ? ""
197- : String ( params [ key ] )
198- }
199- onValueChange = { ( value ) => {
200- if ( value === "" ) {
201- setParams ( {
202- ...params ,
203- [ key ] : undefined ,
204- } ) ;
205- } else {
206- setParams ( {
207- ...params ,
208- [ key ] : value ,
209- } ) ;
210- }
211- } }
163+ < div className = "flex justify-between" >
164+ < Label
165+ htmlFor = { key }
166+ className = "block text-sm font-medium text-gray-700 dark:text-gray-300"
212167 >
213- < SelectTrigger id = { key } className = "mt-1" >
214- < SelectValue
215- placeholder = {
216- prop . description || "Select an option"
168+ { key }
169+ { required && (
170+ < span className = "text-red-500 ml-1" > *</ span >
171+ ) }
172+ </ Label >
173+ { prop . nullable ? (
174+ < div className = "flex items-center space-x-2" >
175+ < Checkbox
176+ id = { key }
177+ name = { key }
178+ checked = { params [ key ] === null }
179+ onCheckedChange = { ( checked : boolean ) =>
180+ setParams ( {
181+ ...params ,
182+ [ key ] : checked ? null : prop . default ,
183+ } )
184+ }
185+ />
186+ < label
187+ htmlFor = { key }
188+ className = "text-sm font-medium text-gray-700 dark:text-gray-300"
189+ >
190+ null
191+ </ label >
192+ </ div >
193+ ) : null }
194+ </ div >
195+
196+ < div
197+ role = "toolinputwrapper"
198+ className = { `${ prop . nullable && params [ key ] === null ? "pointer-events-none opacity-50" : "" } ` }
199+ >
200+ { prop . type === "boolean" ? (
201+ < div className = "flex items-center space-x-2 mt-2" >
202+ < Checkbox
203+ id = { key }
204+ name = { key }
205+ checked = { ! ! params [ key ] }
206+ onCheckedChange = { ( checked : boolean ) =>
207+ setParams ( {
208+ ...params ,
209+ [ key ] : checked ,
210+ } )
217211 }
218212 />
219- </ SelectTrigger >
220- < SelectContent >
221- { prop . enum . map ( ( option ) => (
222- < SelectItem key = { option } value = { option } >
223- { option }
224- </ SelectItem >
225- ) ) }
226- </ SelectContent >
227- </ Select >
228- ) : prop . type === "string" ? (
229- < Textarea
230- id = { key }
231- name = { key }
232- placeholder = { prop . description }
233- value = {
234- params [ key ] === undefined
235- ? ""
236- : String ( params [ key ] )
237- }
238- onChange = { ( e ) => {
239- const value = e . target . value ;
240- if ( value === "" ) {
241- // Field cleared - set to undefined
242- setParams ( {
243- ...params ,
244- [ key ] : undefined ,
245- } ) ;
246- } else {
247- // Field has value - keep as string
248- setParams ( {
249- ...params ,
250- [ key ] : value ,
251- } ) ;
213+ < label
214+ htmlFor = { key }
215+ className = "text-sm font-medium text-gray-700 dark:text-gray-300"
216+ >
217+ { prop . description || "Toggle this option" }
218+ </ label >
219+ </ div >
220+ ) : prop . type === "string" && prop . enum ? (
221+ < Select
222+ value = {
223+ params [ key ] === undefined
224+ ? ""
225+ : String ( params [ key ] )
252226 }
253- } }
254- className = "mt-1"
255- />
256- ) : prop . type === "object" || prop . type === "array" ? (
257- < div className = "mt-1" >
258- < DynamicJsonForm
259- ref = { ( ref ) => ( formRefs . current [ key ] = ref ) }
260- schema = { {
261- type : prop . type ,
262- properties : prop . properties ,
263- description : prop . description ,
264- items : prop . items ,
227+ onValueChange = { ( value ) => {
228+ if ( value === "" ) {
229+ setParams ( {
230+ ... params ,
231+ [ key ] : undefined ,
232+ } ) ;
233+ } else {
234+ setParams ( {
235+ ... params ,
236+ [ key ] : value ,
237+ } ) ;
238+ }
265239 } }
240+ >
241+ < SelectTrigger id = { key } className = "mt-1" >
242+ < SelectValue
243+ placeholder = {
244+ prop . description || "Select an option"
245+ }
246+ />
247+ </ SelectTrigger >
248+ < SelectContent >
249+ { prop . enum . map ( ( option ) => (
250+ < SelectItem key = { option } value = { option } >
251+ { option }
252+ </ SelectItem >
253+ ) ) }
254+ </ SelectContent >
255+ </ Select >
256+ ) : prop . type === "string" ? (
257+ < Textarea
258+ id = { key }
259+ name = { key }
260+ placeholder = { prop . description }
266261 value = {
267- ( params [ key ] as JsonValue ) ??
268- generateDefaultValue ( prop )
262+ params [ key ] === undefined
263+ ? ""
264+ : String ( params [ key ] )
269265 }
270- onChange = { ( newValue : JsonValue ) => {
271- setParams ( {
272- ...params ,
273- [ key ] : newValue ,
274- } ) ;
275- // Check validation after a short delay to allow form to update
276- setTimeout ( checkValidationErrors , 100 ) ;
277- } }
278- />
279- </ div >
280- ) : prop . type === "number" ||
281- prop . type === "integer" ? (
282- < Input
283- type = "number"
284- id = { key }
285- name = { key }
286- placeholder = { prop . description }
287- value = {
288- params [ key ] === undefined
289- ? ""
290- : String ( params [ key ] )
291- }
292- onChange = { ( e ) => {
293- const value = e . target . value ;
294- if ( value === "" ) {
295- // Field cleared - set to undefined
296- setParams ( {
297- ...params ,
298- [ key ] : undefined ,
299- } ) ;
300- } else {
301- // Field has value - try to convert to number, but store input either way
302- const num = Number ( value ) ;
303- if ( ! isNaN ( num ) ) {
266+ onChange = { ( e ) => {
267+ const value = e . target . value ;
268+ if ( value === "" ) {
269+ // Field cleared - set to undefined
304270 setParams ( {
305271 ...params ,
306- [ key ] : num ,
272+ [ key ] : undefined ,
307273 } ) ;
308274 } else {
309- // Store invalid input as string - let server validate
275+ // Field has value - keep as string
310276 setParams ( {
311277 ...params ,
312278 [ key ] : value ,
313279 } ) ;
314280 }
315- }
316- } }
317- className = "mt-1"
318- />
319- ) : (
320- < div className = "mt-1" >
321- < DynamicJsonForm
322- ref = { ( ref ) => ( formRefs . current [ key ] = ref ) }
323- schema = { {
324- type : prop . type ,
325- properties : prop . properties ,
326- description : prop . description ,
327- items : prop . items ,
328281 } }
329- value = { params [ key ] as JsonValue }
330- onChange = { ( newValue : JsonValue ) => {
331- setParams ( {
332- ...params ,
333- [ key ] : newValue ,
334- } ) ;
335- // Check validation after a short delay to allow form to update
336- setTimeout ( checkValidationErrors , 100 ) ;
282+ className = "mt-1"
283+ />
284+ ) : prop . type === "object" ||
285+ prop . type === "array" ? (
286+ < div className = "mt-1" >
287+ < DynamicJsonForm
288+ ref = { ( ref ) => ( formRefs . current [ key ] = ref ) }
289+ schema = { {
290+ type : prop . type ,
291+ properties : prop . properties ,
292+ description : prop . description ,
293+ items : prop . items ,
294+ } }
295+ value = {
296+ ( params [ key ] as JsonValue ) ??
297+ generateDefaultValue ( prop )
298+ }
299+ onChange = { ( newValue : JsonValue ) => {
300+ setParams ( {
301+ ...params ,
302+ [ key ] : newValue ,
303+ } ) ;
304+ // Check validation after a short delay to allow form to update
305+ setTimeout ( checkValidationErrors , 100 ) ;
306+ } }
307+ />
308+ </ div >
309+ ) : prop . type === "number" ||
310+ prop . type === "integer" ? (
311+ < Input
312+ type = "number"
313+ id = { key }
314+ name = { key }
315+ placeholder = { prop . description }
316+ value = {
317+ params [ key ] === undefined
318+ ? ""
319+ : String ( params [ key ] )
320+ }
321+ onChange = { ( e ) => {
322+ const value = e . target . value ;
323+ if ( value === "" ) {
324+ // Field cleared - set to undefined
325+ setParams ( {
326+ ...params ,
327+ [ key ] : undefined ,
328+ } ) ;
329+ } else {
330+ // Field has value - try to convert to number, but store input either way
331+ const num = Number ( value ) ;
332+ if ( ! isNaN ( num ) ) {
333+ setParams ( {
334+ ...params ,
335+ [ key ] : num ,
336+ } ) ;
337+ } else {
338+ // Store invalid input as string - let server validate
339+ setParams ( {
340+ ...params ,
341+ [ key ] : value ,
342+ } ) ;
343+ }
344+ }
337345 } }
346+ className = "mt-1"
338347 />
339- </ div >
340- ) }
348+ ) : (
349+ < div className = "mt-1" >
350+ < DynamicJsonForm
351+ ref = { ( ref ) => ( formRefs . current [ key ] = ref ) }
352+ schema = { {
353+ type : prop . type ,
354+ properties : prop . properties ,
355+ description : prop . description ,
356+ items : prop . items ,
357+ } }
358+ value = { params [ key ] as JsonValue }
359+ onChange = { ( newValue : JsonValue ) => {
360+ setParams ( {
361+ ...params ,
362+ [ key ] : newValue ,
363+ } ) ;
364+ // Check validation after a short delay to allow form to update
365+ setTimeout ( checkValidationErrors , 100 ) ;
366+ } }
367+ />
368+ </ div >
369+ ) }
370+ </ div >
341371 </ div >
342372 ) ;
343373 } ,
0 commit comments