1
- import { createElement , createRef , Fragment , ReactElement , RefObject , useEffect , useRef } from 'react'
1
+ import { createElement , createRef , Fragment , ReactElement , RefObject , useEffect , useRef , useState } from 'react'
2
2
// eslint-disable-next-line import/no-extraneous-dependencies
3
3
import { followCursor } from 'tippy.js'
4
4
5
- import { ReactComponent as ICCross } from '@Icons/ic-cross .svg'
5
+ import { ReactComponent as ICClose } from '@Icons/ic-close .svg'
6
6
import { Tooltip } from '@Common/Tooltip'
7
7
import { ConditionalWrap } from '@Common/Helper'
8
8
import { ResizableTagTextArea } from '@Common/CustomTagSelector'
9
9
import { ComponentSizeType } from '@Shared/constants'
10
10
11
11
import { Button , ButtonStyleType , ButtonVariantType } from '../Button'
12
- import { SelectTextArea } from '../SelectTextArea'
13
12
import {
14
13
getSelectPickerOptionByValue ,
15
14
SelectPicker ,
15
+ SelectPickerTextArea ,
16
16
SelectPickerOptionType ,
17
17
SelectPickerVariantType ,
18
18
} from '../SelectPicker'
@@ -46,6 +46,7 @@ export const DynamicDataTableRow = <K extends string, CustomStateType = Record<s
46
46
leadingCellIcon,
47
47
trailingCellIcon,
48
48
buttonCellWrapComponent,
49
+ focusableFieldKey,
49
50
} : DynamicDataTableRowProps < K , CustomStateType > ) => {
50
51
// CONSTANTS
51
52
const isFirstRowEmpty = headers . every ( ( { key } ) => ! rows [ 0 ] ?. data [ key ] . value )
@@ -59,6 +60,10 @@ export const DynamicDataTableRow = <K extends string, CustomStateType = Record<s
59
60
isDeletionNotAllowed || readOnly ,
60
61
)
61
62
63
+ // STATES
64
+ const [ isRowAdded , setIsRowAdded ] = useState ( false )
65
+
66
+ // CELL REFS
62
67
const cellRef = useRef < Record < string | number , Record < K , RefObject < HTMLTextAreaElement > > > > ( )
63
68
if ( ! cellRef . current ) {
64
69
cellRef . current = rows . reduce (
@@ -71,6 +76,7 @@ export const DynamicDataTableRow = <K extends string, CustomStateType = Record<s
71
76
}
72
77
73
78
useEffect ( ( ) => {
79
+ setIsRowAdded ( rows . length > 0 && Object . keys ( cellRef . current ) . length < rows . length )
74
80
const rowIds = rows . map ( ( { id } ) => id )
75
81
76
82
const updatedCellRef = rowIds . reduce ( ( acc , curr ) => {
@@ -85,6 +91,15 @@ export const DynamicDataTableRow = <K extends string, CustomStateType = Record<s
85
91
cellRef . current = updatedCellRef
86
92
} , [ rows . length ] )
87
93
94
+ useEffect ( ( ) => {
95
+ // Using the below logic to ensure the cell is focused after row addition.
96
+ const cell = cellRef . current [ rows [ 0 ] . id ] [ focusableFieldKey || headers [ 0 ] . key ] . current
97
+ if ( isRowAdded && cell ) {
98
+ cell . focus ( )
99
+ setIsRowAdded ( false )
100
+ }
101
+ } , [ isRowAdded ] )
102
+
88
103
// METHODS
89
104
const onChange =
90
105
( row : DynamicDataTableRowType < K , CustomStateType > , key : K ) =>
@@ -94,7 +109,7 @@ export const DynamicDataTableRow = <K extends string, CustomStateType = Record<s
94
109
switch ( row . data [ key ] . type ) {
95
110
case DynamicDataTableRowDataType . DROPDOWN :
96
111
case DynamicDataTableRowDataType . SELECT_TEXT :
97
- value = ( e as SelectPickerOptionType < string > ) . value
112
+ value = ( e as SelectPickerOptionType < string > ) ? .value || ''
98
113
extraData . selectedValue = e
99
114
break
100
115
case DynamicDataTableRowDataType . FILE_UPLOAD :
@@ -138,31 +153,32 @@ export const DynamicDataTableRow = <K extends string, CustomStateType = Record<s
138
153
/>
139
154
</ div >
140
155
)
141
- case DynamicDataTableRowDataType . SELECT_TEXT :
156
+ case DynamicDataTableRowDataType . SELECT_TEXT : {
157
+ const { value, props } = row . data [ key ]
158
+ const { isCreatable = true } = props
159
+
142
160
return (
143
- < div className = "dynamic-data-table__select-text-area w-100 h-100 flex top dc__align-self-start" >
144
- < SelectTextArea
145
- { ...row . data [ key ] . props }
146
- value = { row . data [ key ] . value }
147
- onChange = { onChange ( row , key ) }
161
+ < div className = "w-100 h-100 flex top dc__align-self-start" >
162
+ < SelectPickerTextArea
163
+ isCreatable = { isCreatable }
164
+ isClearable
165
+ { ...props }
166
+ variant = { SelectPickerVariantType . BORDER_LESS }
167
+ classNamePrefix = "dynamic-data-table__cell__select-picker"
148
168
inputId = { `data-table-${ row . id } -${ key } -cell` }
149
- disabled = { isDisabled }
150
- refVar = { cellRef ?. current ?. [ row . id ] ?. [ key ] }
151
- dependentRefs = { cellRef ?. current ?. [ row . id ] }
152
- selectPickerProps = { {
153
- ...row . data [ key ] . props ?. selectPickerProps ,
154
- classNamePrefix : 'dynamic-data-table__cell__select-picker' ,
155
- } }
156
- textAreaProps = { {
157
- ...row . data [ key ] . props ?. textAreaProps ,
158
- className : 'dynamic-data-table__cell-input placeholder-cn5 py-8 pr-32 cn-9 fs-13 lh-20' ,
159
- disableOnBlurResizeToMinHeight : true ,
160
- minHeight : 20 ,
161
- maxHeight : 160 ,
162
- } }
169
+ value = { getSelectPickerOptionByValue (
170
+ props ?. options ,
171
+ value ,
172
+ isCreatable && value ? { label : value , value } : null ,
173
+ ) }
174
+ onChange = { onChange ( row , key ) }
175
+ isDisabled = { isDisabled }
176
+ formatCreateLabel = { ( input ) => `Use ${ input } ` }
177
+ fullWidth
163
178
/>
164
179
</ div >
165
180
)
181
+ }
166
182
case DynamicDataTableRowDataType . BUTTON :
167
183
return (
168
184
< div className = "w-100 h-100 flex top" >
@@ -182,7 +198,9 @@ export const DynamicDataTableRow = <K extends string, CustomStateType = Record<s
182
198
)
183
199
case DynamicDataTableRowDataType . FILE_UPLOAD :
184
200
return (
185
- < div className = { `mw-none w-100 h-100 flex top left px-8 ${ row . data [ key ] . value ? 'py-3' : 'py-8' } ` } >
201
+ < div
202
+ className = { `mw-none w-100 h-100 flex top left px-8 ${ row . data [ key ] . props ?. isLoading || row . data [ key ] . value ? 'py-3' : 'py-8' } ` }
203
+ >
186
204
< FileUpload
187
205
{ ...row . data [ key ] . props }
188
206
fileName = { row . data [ key ] . value }
@@ -229,7 +247,7 @@ export const DynamicDataTableRow = <K extends string, CustomStateType = Record<s
229
247
230
248
const renderErrorMessage = ( errorMessage : string ) => (
231
249
< div key = { errorMessage } className = "flexbox align-items-center dc__gap-4" >
232
- < ICCross className = "icon-dim-16 fcr-5 dc__align-self-start dc__no-shrink" />
250
+ < ICClose className = "icon-dim-16 fcr-5 dc__align-self-start dc__no-shrink" />
233
251
< p className = "fs-12 lh-16 cn-7 m-0" > { errorMessage } </ p >
234
252
</ div >
235
253
)
@@ -240,12 +258,17 @@ export const DynamicDataTableRow = <K extends string, CustomStateType = Record<s
240
258
? cellError [ row . id ] [ key ]
241
259
: { isValid : true , errorMessages : [ ] }
242
260
261
+ const isSelectText = row . data [ key ] . type === DynamicDataTableRowDataType . SELECT_TEXT
262
+
243
263
if ( isValid ) {
244
264
return null
245
265
}
246
266
267
+ // Adding 'no-error' class to hide error when SelectPickerTextArea is focused.
247
268
return (
248
- < div className = "dynamic-data-table__error bcn-0 dc__border br-4 py-7 px-8 flexbox-col dc__gap-4" >
269
+ < div
270
+ className = { `dynamic-data-table__error bcn-0 dc__border br-4 py-7 px-8 flexbox-col dc__gap-4 ${ isSelectText ? 'no-error' : '' } ` }
271
+ >
249
272
{ errorMessages . map ( ( error ) => renderErrorMessage ( error ) ) }
250
273
</ div >
251
274
)
@@ -264,7 +287,7 @@ export const DynamicDataTableRow = <K extends string, CustomStateType = Record<s
264
287
plugins = { [ followCursor ] }
265
288
>
266
289
< div
267
- className = { `dynamic-data-table__cell bcn-0 flexbox dc__align-items-center dc__gap-4 dc__position-rel ${ isDisabled ? 'cursor-not-allowed no-hover' : '' } ${ ! isDisabled && hasError ? 'dynamic-data-table__cell--error no-hover' : '' } ${ ! rowTypeHasInputField ( row . data [ key ] . type ) ? 'no-hover no-focus' : '' } ` }
290
+ className = { `dynamic-data-table__cell bcn-0 flexbox dc__align-items-center dc__gap-4 dc__position-rel ${ isDisabled ? 'dc__disabled no-hover' : '' } ${ ! isDisabled && hasError ? 'dynamic-data-table__cell--error no-hover' : '' } ${ ! rowTypeHasInputField ( row . data [ key ] . type ) ? 'no-hover no-focus' : '' } ` }
268
291
>
269
292
{ renderCellIcon ( row , key , true ) }
270
293
{ renderCellContent ( row , key ) }
@@ -321,7 +344,7 @@ export const DynamicDataTableRow = <K extends string, CustomStateType = Record<s
321
344
dataTestId = "dynamic-data-table-row-delete-btn"
322
345
ariaLabel = "Delete Row"
323
346
showAriaLabelInTippy = { false }
324
- icon = { < ICCross /> }
347
+ icon = { < ICClose /> }
325
348
disabled = { disableDeleteRow || row . disableDelete }
326
349
onClick = { onDelete ( row ) }
327
350
variant = { ButtonVariantType . borderLess }
0 commit comments