@@ -4,7 +4,7 @@ import { DeleteIcon, PlusIcon } from '@ultraviolet/icons'
4
4
import { Button , Row , Stack } from '@ultraviolet/ui'
5
5
import type { ComponentProps } from 'react'
6
6
import type { Control , FieldArrayPath , FieldValues } from 'react-hook-form'
7
- import { useFieldArray } from 'react-hook-form'
7
+ import { useFieldArray , useFormContext } from 'react-hook-form'
8
8
import { TextInputField } from '../TextInputField'
9
9
10
10
type InputKeyProps = {
@@ -25,6 +25,11 @@ type AddButtonProps = {
25
25
maxSizeReachedTooltip ?: string
26
26
}
27
27
28
+ type KeyValuePair = {
29
+ key : string
30
+ value : string
31
+ }
32
+
28
33
type KeyValueFieldProps <
29
34
TFieldValues extends FieldValues ,
30
35
TFieldArrayName extends FieldArrayPath < TFieldValues > ,
@@ -36,6 +41,8 @@ type KeyValueFieldProps<
36
41
maxSize ?: number
37
42
readOnly ?: boolean
38
43
control ?: Control < TFieldValues >
44
+ onChange ?: ( values : KeyValuePair [ ] ) => void
45
+ onBlur ?: ( values : KeyValuePair [ ] ) => void
39
46
}
40
47
41
48
/**
@@ -53,12 +60,24 @@ export const KeyValueField = <
53
60
maxSize = 100 ,
54
61
readOnly = false ,
55
62
control,
63
+ onChange,
64
+ onBlur,
56
65
} : KeyValueFieldProps < TFieldValues , TFieldArrayName > ) => {
57
66
const { fields, append, remove } = useFieldArray ( {
58
67
control,
59
68
name,
60
69
} )
61
70
71
+ const { getValues } = useFormContext ( )
72
+
73
+ const handleFieldChange = ( ) => {
74
+ onChange ?.( getValues ( name ) )
75
+ }
76
+
77
+ const handleFieldBlur = ( ) => {
78
+ onBlur ?.( getValues ( name ) )
79
+ }
80
+
62
81
const canAdd = fields . length !== undefined && fields . length < maxSize
63
82
const maxSizeReachedTooltip =
64
83
addButton . maxSizeReachedTooltip ??
@@ -78,6 +97,8 @@ export const KeyValueField = <
78
97
< TextInputField
79
98
label = { inputKey . label }
80
99
name = { `${ name } .${ index } .key` }
100
+ onBlur = { handleFieldBlur }
101
+ onChange = { handleFieldChange }
81
102
readOnly = { readOnly }
82
103
regex = { inputKey . regex }
83
104
required = { inputKey . required }
@@ -86,6 +107,8 @@ export const KeyValueField = <
86
107
autoComplete = "off"
87
108
label = { inputValue . label }
88
109
name = { `${ name } .${ index } .value` }
110
+ onBlur = { handleFieldBlur }
111
+ onChange = { handleFieldChange }
89
112
placeholder = { inputValue . placeholder }
90
113
readOnly = { readOnly }
91
114
regex = { inputValue . regex }
@@ -96,7 +119,10 @@ export const KeyValueField = <
96
119
< Button
97
120
data-testid = { `remove-button-${ index } ` }
98
121
disabled = { readOnly }
99
- onClick = { ( ) => remove ( index ) }
122
+ onClick = { ( ) => {
123
+ remove ( index )
124
+ handleFieldChange ( )
125
+ } }
100
126
sentiment = "danger"
101
127
size = "large"
102
128
variant = "outlined"
@@ -112,8 +138,11 @@ export const KeyValueField = <
112
138
data-testid = "add-button"
113
139
disabled = { ! canAdd || readOnly }
114
140
fullWidth = { addButton . fullWidth }
115
- // @ts -expect-error can't infer properly
116
- onClick = { ( ) => append ( { key : '' , value : '' } ) }
141
+ onClick = { ( ) => {
142
+ // @ts -expect-error can't infer properly
143
+ append ( { key : '' , value : '' } )
144
+ handleFieldChange ( )
145
+ } }
117
146
sentiment = "primary"
118
147
tooltip = { ! canAdd ? maxSizeReachedTooltip : addButton . tooltip }
119
148
variant = "outlined"
0 commit comments