11import { useErrorsLngChange } from '@/hooks/use-errors-lng-change'
22import { TFlowInput , useFlowInputSchema } from '@/lib/schema/flow-input'
3- import { isStringBoolean , isStringNumber , toBoolean } from '@/utils'
3+ import {
4+ isStringArray ,
5+ isStringBoolean ,
6+ isStringNumber ,
7+ isStringObject ,
8+ toArray ,
9+ toBoolean ,
10+ } from '@/utils'
411import { zodResolver } from '@hookform/resolvers/zod'
512import { toNumber } from 'lodash'
613import { X } from 'lucide-react'
@@ -21,20 +28,74 @@ import {
2128 SelectItem ,
2229 SelectTrigger ,
2330 SelectValue ,
31+ Textarea ,
2432} from '../ui'
2533
34+ const closeChars = new Map ( [
35+ [ '{' , '}' ] ,
36+ [ '[' , ']' ] ,
37+ [ '(' , ')' ] ,
38+ ] )
39+
2640type Props = {
2741 id ?: string
2842 onSubmit ?: ( data : TFlowInput ) => void
2943 defaultValues ?: TFlowInput
3044}
3145
32- const parseVariableValue = ( value : string ) => {
33- if ( isStringNumber ( value ) ) return toNumber ( value )
34- if ( isStringBoolean ( value ) ) return toBoolean ( value )
46+ const parseVariableValue = ( value : string , type : string ) => {
47+ if ( isStringNumber ( value ) && type === 'number' ) return toNumber ( value )
48+ if ( isStringBoolean ( value ) && type === 'boolean' ) return toBoolean ( value )
49+
50+ if ( isStringArray ( value ) && type === 'array' ) return toArray ( value )
51+
52+ if ( isStringObject ( value ) && type === 'object' ) return JSON . parse ( value )
53+
3554 return value
3655}
3756
57+ const handleJsonChange = (
58+ e : React . ChangeEvent < HTMLTextAreaElement > ,
59+ onChange : ( value : any ) => void ,
60+ ) => {
61+ const cursorPosition = e . target . selectionStart
62+
63+ const val = [ ...e . target . value ]
64+
65+ const char = val . slice ( cursorPosition - 1 , cursorPosition ) [ 0 ]
66+
67+ const closeChar = closeChars . get ( char )
68+
69+ if ( closeChar ) {
70+ val . splice ( cursorPosition , 0 , closeChar )
71+ e . target . value = val . join ( '' )
72+ e . target . selectionEnd = cursorPosition
73+ }
74+
75+ onChange ( e . target . value )
76+ }
77+
78+ const handleJsonKeyDown = (
79+ e : React . KeyboardEvent < HTMLTextAreaElement > ,
80+ onChange : ( value : any ) => void ,
81+ ) => {
82+ if ( e . key === 'Tab' ) {
83+ e . preventDefault ( )
84+
85+ const cursorPosition = e . currentTarget . selectionStart
86+ const value = e . currentTarget . value
87+ e . currentTarget . value =
88+ value . substring ( 0 , cursorPosition ) +
89+ ' ' +
90+ value . substring ( cursorPosition , value . length )
91+
92+ e . currentTarget . selectionStart = cursorPosition + 2
93+ e . currentTarget . selectionEnd = cursorPosition + 2
94+
95+ onChange ( e . currentTarget . value )
96+ }
97+ }
98+
3899export const VariablesSettingForm = ( {
39100 id = 'variables-setting-form' ,
40101 onSubmit,
@@ -47,19 +108,22 @@ export const VariablesSettingForm = ({
47108 mode : 'onChange' ,
48109 defaultValues : {
49110 ...defaultValues ,
111+ variables : defaultValues ?. variables ?. map ( ( variable ) => ( {
112+ ...variable ,
113+ value : JSON . stringify ( variable . value ) ,
114+ } ) ) ,
50115 } ,
51116 } )
117+
118+ const variablesWatch = form . watch ( 'variables' )
119+
52120 const {
53121 fields : variables ,
54122 append,
55- prepend,
56123 remove,
57- swap,
58- move,
59- insert,
60124 } = useFieldArray ( {
61125 control : form . control ,
62- name : 'variables' , // unique name for your Field Array
126+ name : 'variables' ,
63127 } )
64128
65129 useErrorsLngChange ( form )
@@ -70,7 +134,7 @@ export const VariablesSettingForm = ({
70134 ...data ,
71135 variables : data . variables ?. map ( ( variable ) => ( {
72136 ...variable ,
73- value : parseVariableValue ( variable . value ) ,
137+ value : parseVariableValue ( variable . value , variable . type as string ) ,
74138 } ) ) ,
75139 } )
76140 }
@@ -123,11 +187,27 @@ export const VariablesSettingForm = ({
123187 return (
124188 < FormItem className = 'w-full' >
125189 < FormControl >
126- < Input
127- { ...field }
128- autoComplete = 'off'
129- placeholder = { t ( 'variable_value.placeholder' ) }
130- />
190+ { variablesWatch ?. [ index ] ?. type === 'object' ? (
191+ < Textarea
192+ { ...field }
193+ onChange = { ( e ) => {
194+ handleJsonChange ( e , field . onChange )
195+ } }
196+ onKeyDown = { ( e ) =>
197+ handleJsonKeyDown ( e , field . onChange )
198+ }
199+ autoComplete = 'off'
200+ placeholder = { t ( 'variable_value.placeholder' ) }
201+ className = 'hidden-scroll resize-none'
202+ rows = { 5 }
203+ />
204+ ) : (
205+ < Input
206+ { ...field }
207+ autoComplete = 'off'
208+ placeholder = { t ( 'variable_value.placeholder' ) }
209+ />
210+ ) }
131211 </ FormControl >
132212 < FormMessage />
133213 </ FormItem >
@@ -152,7 +232,13 @@ export const VariablesSettingForm = ({
152232 </ SelectTrigger >
153233 </ FormControl >
154234 < SelectContent >
155- { [ 'string' , 'number' , 'boolean' ] . map ( ( type ) => (
235+ { [
236+ 'string' ,
237+ 'number' ,
238+ 'boolean' ,
239+ 'array' ,
240+ 'object' ,
241+ ] . map ( ( type ) => (
156242 < SelectItem key = { type } value = { type } >
157243 { type }
158244 </ SelectItem >
0 commit comments