form-craft-package 1.7.9-dev.2 → 1.7.10-dev.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (50) hide show
  1. package/index.ts +4 -1
  2. package/package.json +4 -4
  3. package/src/api/client.ts +10 -0
  4. package/src/components/common/countdown.tsx +44 -0
  5. package/src/components/common/custom-hooks/index.ts +2 -0
  6. package/src/components/common/custom-hooks/use-breadcrumb.hook.ts +18 -0
  7. package/src/components/common/custom-hooks/use-check-element-conditions.hook.ts +3 -2
  8. package/src/components/common/custom-hooks/use-dayjs-extender.hook.ts +8 -0
  9. package/src/components/common/custom-hooks/use-many-to-many-connector.hook.ts +2 -3
  10. package/src/components/common/custom-hooks/use-notification.hook.tsx +1 -1
  11. package/src/components/common/custom-hooks/use-window-width.hook.ts +6 -4
  12. package/src/components/common/loading-skeletons/details.tsx +61 -6
  13. package/src/components/common/loading-skeletons/index.tsx +10 -2
  14. package/src/components/form/1-list/index.tsx +32 -17
  15. package/src/components/form/1-list/table-header.tsx +29 -55
  16. package/src/components/form/1-list/table.tsx +3 -5
  17. package/src/components/form/2-details/index.tsx +26 -26
  18. package/src/components/form/layout-renderer/1-row/index.tsx +9 -7
  19. package/src/components/form/layout-renderer/3-element/1-dynamic-button/index.tsx +25 -19
  20. package/src/components/form/layout-renderer/3-element/1-dynamic-button/use-button-navigate.hook.tsx +11 -5
  21. package/src/components/form/layout-renderer/3-element/1-dynamic-button/use-custom-function-call.hook.ts +22 -0
  22. package/src/components/form/layout-renderer/3-element/1-dynamic-button/use-generate-report.hook.tsx +2 -2
  23. package/src/components/form/layout-renderer/3-element/2-field-element.tsx +40 -6
  24. package/src/components/form/layout-renderer/3-element/5-re-captcha.tsx +1 -1
  25. package/src/components/form/layout-renderer/3-element/6-signature.tsx +2 -3
  26. package/src/components/form/layout-renderer/3-element/8-fields-with-options.tsx +142 -61
  27. package/src/components/form/layout-renderer/3-element/9-form-data-render.tsx +34 -27
  28. package/src/components/form/layout-renderer/3-element/index.tsx +3 -0
  29. package/src/components/index.tsx +2 -0
  30. package/src/components/modals/pdf-preview.modal.tsx +41 -0
  31. package/src/constants.ts +1 -0
  32. package/src/enums/form.enum.ts +8 -7
  33. package/src/enums/index.ts +1 -0
  34. package/src/functions/forms/conditional-rule-validator.ts +2 -0
  35. package/src/functions/forms/data-render-functions.tsx +21 -6
  36. package/src/functions/forms/get-data-list-option-value.ts +3 -3
  37. package/src/functions/forms/index.ts +33 -4
  38. package/src/functions/forms/linked-form-joins.ts +19 -0
  39. package/src/functions/reports/create-blob-url.ts +16 -0
  40. package/src/functions/reports/index.tsx +1 -0
  41. package/src/types/forms/data-list/filter-config.ts +5 -16
  42. package/src/types/forms/data-list/index.ts +2 -0
  43. package/src/types/forms/index.ts +0 -1
  44. package/src/types/forms/layout-elements/data-render-config.ts +5 -5
  45. package/src/types/forms/layout-elements/field-option-source.ts +25 -10
  46. package/src/types/forms/layout-elements/index.ts +7 -1
  47. package/src/types/forms/layout-elements/style.ts +0 -4
  48. package/src/types/forms/relationship/index.ts +6 -6
  49. package/src/types/index.ts +2 -0
  50. package/src/functions/forms/breadcrumb-handlers.ts +0 -21
@@ -1,18 +1,22 @@
1
1
  import { Form } from 'antd'
2
2
  import { useCallback, useEffect, useMemo, useState } from 'react'
3
3
  import { IDndLayoutStructure_Responsive, IFormSchema } from '../../../types'
4
- import { NEW_FORM_DATA_IDENTIFIER } from '../../../constants'
5
4
  import { LayoutRendererRow } from '../layout-renderer/1-row'
6
5
  import { DynamicFormButtonRender, ICustomFunctionCall } from '../layout-renderer/3-element/1-dynamic-button'
7
6
  import FormDataListSkeleton_Details from '../../common/loading-skeletons/details'
8
7
  import { useLocation } from 'react-router-dom'
9
- import { fromMongoDbExtendedJSON, isValidMongoDbId, queryParamsToObject } from '../../../functions/forms'
10
8
  import { DeviceBreakpointEnum, FormPreservedItemKeys, LOCAL_STORAGE_KEYS_ENUM } from '../../../enums'
11
9
  import useGetCurrentBreakpoint from '../../common/custom-hooks/use-window-width.hook'
12
10
  import client from '../../../api/client'
13
11
  import { useBreadcrumb } from '../../common/custom-hooks/use-breadcrumb.hook'
14
12
  import NotFound from '../../common/not-found'
15
13
  import { useManyToManyConnector } from '../../common/custom-hooks/use-many-to-many-connector.hook'
14
+ import {
15
+ fromMongoDbExtendedJSON,
16
+ isNewFormDataPage,
17
+ isValidMongoDbId,
18
+ queryParamsToObject,
19
+ } from '../../../functions/forms'
16
20
 
17
21
  export default function FormDataDetailsComponent({
18
22
  isPublic,
@@ -46,10 +50,9 @@ export default function FormDataDetailsComponent({
46
50
  }, [formDataId])
47
51
 
48
52
  useEffect(() => {
49
- const isNewDataPage = formDataId === NEW_FORM_DATA_IDENTIFIER
50
53
  const splittedFormName = formName?.split(' ')?.[0] ?? ''
51
54
  push({
52
- label: isNewDataPage ? `New ${splittedFormName.toLowerCase()}` : `${splittedFormName} details`,
55
+ label: isNewFormDataPage(formDataId) ? `New ${splittedFormName.toLowerCase()}` : `${splittedFormName} details`,
53
56
  href: location.pathname,
54
57
  })
55
58
  }, [location.pathname, formName, formDataId])
@@ -61,7 +64,7 @@ export default function FormDataDetailsComponent({
61
64
 
62
65
  // Apply initialValues from parent
63
66
  useEffect(() => {
64
- if (initialValues && formDataId === NEW_FORM_DATA_IDENTIFIER) {
67
+ if (initialValues && isNewFormDataPage(formDataId)) {
65
68
  formDataRef.setFieldsValue(initialValues)
66
69
  }
67
70
  }, [initialValues, formDataId, formDataRef])
@@ -85,8 +88,7 @@ export default function FormDataDetailsComponent({
85
88
 
86
89
  const fetchFormData = useCallback(
87
90
  (dFormId?: number) => {
88
- if (formDataId === NEW_FORM_DATA_IDENTIFIER || !isValidMongoDbId(formDataId))
89
- setLoadings((c) => ({ ...c, data: false }))
91
+ if (isNewFormDataPage(formDataId) || !isValidMongoDbId(formDataId)) setLoadings((c) => ({ ...c, data: false }))
90
92
  else {
91
93
  if (!dFormId) {
92
94
  console.error('Form ID is required to fetch form data')
@@ -151,25 +153,23 @@ export default function FormDataDetailsComponent({
151
153
  if (isNotFound) return <NotFound />
152
154
 
153
155
  return (
154
- <>
155
- <Form layout="vertical" name="dynamic_form_data_form" form={formDataRef}>
156
- {layout.map((row, rowIdx) => (
157
- <LayoutRendererRow
158
- key={rowIdx}
159
- rowData={row}
160
- formContext={formContext}
161
- elements={layoutConfig.elements}
162
- renderButton={(btnProps, conditions) => (
163
- <DynamicFormButtonRender
164
- displayStateProps={{ btnProps, conditions, defaultDisabled: true }}
165
- formContext={formContext}
166
- onCustomFunctionCall={onCustomFunctionCall}
167
- />
168
- )}
169
- />
170
- ))}
171
- </Form>
172
- </>
156
+ <Form layout="vertical" name="dynamic_form_data_form" form={formDataRef}>
157
+ {layout.map((row, rowIdx) => (
158
+ <LayoutRendererRow
159
+ key={rowIdx}
160
+ rowData={row}
161
+ formContext={formContext}
162
+ elements={layoutConfig.elements}
163
+ renderButton={(btnProps, conditions) => (
164
+ <DynamicFormButtonRender
165
+ displayStateProps={{ btnProps, conditions, defaultDisabled: true }}
166
+ formContext={formContext}
167
+ onCustomFunctionCall={onCustomFunctionCall}
168
+ />
169
+ )}
170
+ />
171
+ ))}
172
+ </Form>
173
173
  )
174
174
  }
175
175
 
@@ -1,5 +1,5 @@
1
1
  import { FormInstance } from 'antd'
2
- import { getFlexContainerStyle, getColumnStyle, kebabCaseToCamelCase } from '../../../../functions/forms'
2
+ import { getGridContainerStyle, getColumnStyle, kebabCaseToCamelCase } from '../../../../functions/forms'
3
3
  import LayoutRendererCol from '../2-col'
4
4
  import { memo, ReactElement, ReactNode, useEffect, useMemo, useRef, useState } from 'react'
5
5
  import { LayoutRowConditionalHeaderRenderer } from './header-render'
@@ -26,14 +26,15 @@ export const LayoutRendererRow = memo(
26
26
  if (hideCol) hideCol(hiddenElementCount === rowData.children.length)
27
27
  }, [hiddenElementCount, JSON.stringify(rowData.children)])
28
28
 
29
+ useEffect(() => {
30
+ return () => setHiddenElementCount(0)
31
+ }, [])
32
+
29
33
  return (
30
34
  <LayoutRowConditionalHeaderRenderer header={rowData.props?.header}>
31
35
  <LayoutRowRepeatableRenderer basePath={basePath} repeatingSection={rowData.props?.repeatingSection}>
32
36
  {(formListItemProps) => {
33
- const style: { [key: string]: any } = {
34
- ...styleConfig,
35
- ...getFlexContainerStyle(rowData.display),
36
- }
37
+ const style: { [key: string]: any } = { ...styleConfig, ...getGridContainerStyle(rowData.display) }
37
38
 
38
39
  if (hiddenElementCount === rowData.children.length) return <></>
39
40
 
@@ -62,7 +63,7 @@ export const LayoutRendererRow = memo(
62
63
  formContext={formContext}
63
64
  colStyle={getColumnStyle(colIdx, rowData.display)}
64
65
  renderButton={renderButton}
65
- hideRow={(isHidden) =>
66
+ hideRow={(isHidden) => {
66
67
  setHiddenElementCount((c) => {
67
68
  if (isHidden) {
68
69
  hiddenColIdx.current = [...hiddenColIdx.current, colIdx]
@@ -72,7 +73,7 @@ export const LayoutRendererRow = memo(
72
73
  return c - 1
73
74
  }
74
75
  })
75
- }
76
+ }}
76
77
  />
77
78
  ))}
78
79
  {formListItemProps?.removeButton}
@@ -102,6 +103,7 @@ export interface IFormContext {
102
103
  formName?: string // only passed in DynamicButton component
103
104
  formKey?: string
104
105
  formId?: number
106
+ detailPageFormId?: number
105
107
  parentFormJoins?: IFormJoin[]
106
108
  manyToManyRelInfo?: { middleFormId: number; currentFormId: number; otherFormId: number } | null
107
109
  }
@@ -10,7 +10,6 @@ import { useCreateDataWithPdfActions } from './use-create-data.hook'
10
10
  import { useSaveExistingDataAction } from './use-save-data.hook'
11
11
  import { useGenerateReportAction } from './use-generate-report.hook'
12
12
  import { useSaveSignatureAction } from './use-save-signature.hook'
13
- import { NEW_FORM_DATA_IDENTIFIER } from '../../../../../constants'
14
13
  import { Button_FillerPortal } from '../../../../common/button'
15
14
  import { getButtonRenderProps } from '../../../../../functions/forms/get-element-props'
16
15
  import WarningIcon from '../../../../common/warning-icon'
@@ -18,7 +17,8 @@ import FormDataLoadingIndicatorModal from '../../../../modals/form-data-loading.
18
17
  import { IFormContext } from '../../1-row'
19
18
  import { ButtonActionCategoryEnum, FormLoadingModalTypeEnum } from '../../../../../enums'
20
19
  import { useButtonNavigateAction } from './use-button-navigate.hook'
21
- import { constructDynamicFormHref } from '../../../../../functions'
20
+ import { constructDynamicFormHref, isNewFormDataPage } from '../../../../../functions'
21
+ import { useCustomFunctionCallAction } from './use-custom-function-call.hook'
22
22
  import {
23
23
  IButtonElementProps,
24
24
  IFormLayoutElementConditions,
@@ -60,8 +60,9 @@ export const DynamicFormButtonRender = memo((props: IDynamicButton) => {
60
60
 
61
61
  const handleSecondaryAction = useCallback(
62
62
  (formDataId?: string) => {
63
- if (!btnProps.secondaryAction) {
64
- if (formInfo?.name) navigate(`${constructDynamicFormHref(formInfo.name)}/${formDataId}`, { replace: true })
63
+ if (!btnProps.secondaryAction || Object.values(btnProps.secondaryAction).length === 0) {
64
+ if (formInfo?.name && formDataId)
65
+ navigate(`${constructDynamicFormHref(formInfo.name)}/${formDataId}`, { replace: true })
65
66
  setTimeout(() => {
66
67
  setDataLoadingType(undefined)
67
68
  displayResultMessage()
@@ -72,7 +73,7 @@ export const DynamicFormButtonRender = memo((props: IDynamicButton) => {
72
73
  const { category } = btnProps.secondaryAction
73
74
  if (category === ButtonActionCategoryEnum.Navigate) onButtonNavigate(btnProps.secondaryAction)
74
75
  else if (category === ButtonActionCategoryEnum.CustomFunction) {
75
- onCustomFunctionCall(btnProps.secondaryAction.functionName, btnProps.messages ?? defaultMessage)
76
+ onFunctionCall(btnProps.secondaryAction.functionName, btnProps.messages ?? defaultMessage)
76
77
  setTimeout(() => setLoading(false), 500)
77
78
  }
78
79
  },
@@ -105,16 +106,23 @@ export const DynamicFormButtonRender = memo((props: IDynamicButton) => {
105
106
  setLoading(false)
106
107
  },
107
108
  onSuccess: (formDataId?: string) => handleSecondaryAction(formDataId),
108
- onError: () => displayResultMessage(false),
109
+ onError: () => {
110
+ setDataLoadingType(undefined)
111
+ displayResultMessage(false)
112
+ },
109
113
  onFinal: () => setLoading(false),
110
114
  })
111
115
  const onSaveExistingData = useSaveExistingDataAction({
112
116
  ...formContext,
113
117
  setDataLoadingType,
114
118
  onSuccess: () => handleSecondaryAction(),
115
- onError: () => displayResultMessage(false),
119
+ onError: () => {
120
+ setDataLoadingType(undefined)
121
+ displayResultMessage(false)
122
+ },
116
123
  onFinal: () => setLoading(false),
117
124
  })
125
+ const onFunctionCall = useCustomFunctionCallAction({ ...formContext, onCustomFunctionCall })
118
126
  const { onGenerateReport, ChooseTemplateReportModal } = useGenerateReportAction({
119
127
  ...formContext,
120
128
  onSuccess: () => {},
@@ -157,7 +165,7 @@ export const DynamicFormButtonRender = memo((props: IDynamicButton) => {
157
165
  case ButtonActionCategoryEnum.SaveDataChanges:
158
166
  await onSaveSignature()
159
167
 
160
- if (formDataId === NEW_FORM_DATA_IDENTIFIER) {
168
+ if (isNewFormDataPage(formDataId)) {
161
169
  if (isPublic && submissionPdfConfig) onGeneratePdfProof()
162
170
  else onCreateNewData()
163
171
  } else onSaveExistingData()
@@ -179,7 +187,7 @@ export const DynamicFormButtonRender = memo((props: IDynamicButton) => {
179
187
  break
180
188
 
181
189
  case ButtonActionCategoryEnum.CustomFunction:
182
- onCustomFunctionCall(btnProps.functionName, btnProps.messages ?? defaultMessage)
190
+ onFunctionCall(btnProps.functionName, btnProps.messages)
183
191
  setTimeout(() => setLoading(false), 500)
184
192
  break
185
193
 
@@ -197,7 +205,7 @@ export const DynamicFormButtonRender = memo((props: IDynamicButton) => {
197
205
  formDataId,
198
206
  isPublic,
199
207
  submissionPdfConfig,
200
- onCustomFunctionCall,
208
+ onFunctionCall,
201
209
  onDuplicateData,
202
210
  onDeleteData,
203
211
  onPublishData,
@@ -222,7 +230,7 @@ export const DynamicFormButtonRender = memo((props: IDynamicButton) => {
222
230
  if (inPreviewMode) return
223
231
  if (
224
232
  isPublic &&
225
- formDataId === NEW_FORM_DATA_IDENTIFIER &&
233
+ isNewFormDataPage(formDataId) &&
226
234
  [ButtonActionCategoryEnum.SaveDataChanges, ButtonActionCategoryEnum.Navigate].includes(btnProps.category)
227
235
  )
228
236
  return
@@ -240,7 +248,7 @@ export const DynamicFormButtonRender = memo((props: IDynamicButton) => {
240
248
  }}
241
249
  >
242
250
  {isPublic &&
243
- formDataId === NEW_FORM_DATA_IDENTIFIER &&
251
+ isNewFormDataPage(formDataId) &&
244
252
  btnProps.category !== ButtonActionCategoryEnum.SaveDataChanges && (
245
253
  <WarningIcon tooltip={BUTTON_CUSTOM_ERROR_MESSAGES.UnavailableForPublic} />
246
254
  )}
@@ -270,13 +278,11 @@ interface IDynamicButton_DisplayStateProps {
270
278
  }
271
279
 
272
280
  export interface ICustomFunctionCall {
273
- onCustomFunctionCall?: (
274
- fnName?: string,
275
- messages?: {
276
- success?: string
277
- error?: string
278
- },
279
- ) => void
281
+ onCustomFunctionCall?: (params: {
282
+ fnName: string
283
+ messages?: { success?: string; error?: string }
284
+ formData?: { [key: string]: any }
285
+ }) => void
280
286
  }
281
287
  export interface IOnSuccessFunctions {
282
288
  onSuccess: (formDataId?: string) => void
@@ -1,7 +1,7 @@
1
1
  import { useCallback } from 'react'
2
2
  import { IButtonProps_Navigate } from '../../../../../types'
3
3
  import { useFindDynamiForm, useNotification } from '../../../../common/custom-hooks'
4
- import { constructDynamicFormHref } from '../../../../../functions/forms'
4
+ import { constructDynamicFormHref, isNewFormDataPage } from '../../../../../functions/forms'
5
5
  import { NavigateButtonCustomComponentType, NavigateButtonTypesEnum } from '../../../../../enums'
6
6
  import { IFormContext } from '../../1-row'
7
7
  import { BUTTON_CUSTOM_ERROR_MESSAGES, IOnSuccessFunctions } from '.'
@@ -18,7 +18,7 @@ export const useButtonNavigateAction = ({
18
18
  onFinal,
19
19
  ...formContext
20
20
  }: IOnSuccessFunctions & IFormContext) => {
21
- const { formRef, formDataId, parentFormJoins, manyToManyRelInfo } = formContext
21
+ const { formRef, formDataId, detailPageFormId, parentFormJoins, manyToManyRelInfo } = formContext
22
22
  const { getFormById } = useFindDynamiForm()
23
23
  const { error } = useNotification()
24
24
  const { updateCrumb } = useBreadcrumb()
@@ -32,14 +32,20 @@ export const useButtonNavigateAction = ({
32
32
  switch (btnProps.navigateType) {
33
33
  case NavigateButtonTypesEnum.NewDataPage:
34
34
  let newDatapageNavigateUrl = `${baseDynamicUrl}/${NEW_FORM_DATA_IDENTIFIER}`
35
+
35
36
  if (manyToManyRelInfo && parentFormJoins && formDataId) {
36
37
  const middleFormInfo = getFormById(manyToManyRelInfo.middleFormId)
37
38
 
38
39
  if (middleFormInfo)
39
40
  newDatapageNavigateUrl = `${constructDynamicFormHref(middleFormInfo.name)}/${NEW_FORM_DATA_IDENTIFIER}`
40
41
  }
41
- if (formDataId !== NEW_FORM_DATA_IDENTIFIER)
42
- updateCrumb(location.pathname, { formJoins: parentFormJoins, formDataId, manyToManyRelInfo })
42
+ if (!isNewFormDataPage(formDataId))
43
+ updateCrumb(location.pathname, {
44
+ formJoins: parentFormJoins,
45
+ detailPageFormId,
46
+ formDataId,
47
+ manyToManyRelInfo,
48
+ })
43
49
 
44
50
  navigate(newDatapageNavigateUrl)
45
51
  break
@@ -81,7 +87,7 @@ export const useButtonNavigateAction = ({
81
87
  break
82
88
  }
83
89
  },
84
- [parentFormJoins, manyToManyRelInfo, formRef],
90
+ [parentFormJoins, detailPageFormId, manyToManyRelInfo, formRef],
85
91
  )
86
92
 
87
93
  return onButtonNavigate
@@ -0,0 +1,22 @@
1
+ import { useCallback } from 'react'
2
+ import { IFormContext } from '../../1-row'
3
+ import { ICustomFunctionCall } from '.'
4
+
5
+ export const useCustomFunctionCallAction = ({
6
+ formRef,
7
+ formDataId,
8
+ formId,
9
+ onCustomFunctionCall,
10
+ }: IFormContext & ICustomFunctionCall) => {
11
+ const onFunctionCall = useCallback(
12
+ async (functionName: string, messages?: { success?: string; error?: string }) => {
13
+ let formData: { [key: string]: any } | undefined = undefined
14
+ if (formRef) formData = await formRef.validateFields()
15
+
16
+ onCustomFunctionCall?.({ fnName: functionName, messages, formData: { ...formData, formId, formDataId } })
17
+ },
18
+ [formRef, formId, formDataId],
19
+ )
20
+
21
+ return onFunctionCall
22
+ }
@@ -112,13 +112,13 @@ export const useGenerateReportAction = ({
112
112
  ),
113
113
  }
114
114
  } else if (rep.optionSource.type === FieldElementOptionSourceEnum.DynamicForm) {
115
- const formDataResData = await fetchFormDataAsLookup(rep.optionSource.form.id)
115
+ const formDataResData = await fetchFormDataAsLookup(rep.optionSource.formId)
116
116
 
117
117
  return {
118
118
  placeholder: rep.placeholder,
119
119
  value: renderData(
120
120
  formDataResData.find((data) => data.id === (value as unknown as string))?.[
121
- rep.optionSource.form.field
121
+ rep.optionSource.field
122
122
  ],
123
123
  rep.renderConfig,
124
124
  ),
@@ -3,7 +3,7 @@ import { FaCaretDown } from 'react-icons/fa'
3
3
  import dayjs, { Dayjs } from 'dayjs'
4
4
  import { FaUpload } from 'react-icons/fa6'
5
5
  import { CountryEnum, DataSanitizationTypeEnum, ElementTypeEnum } from '../../../../enums'
6
- import { formatByPattern, mapToFormItemRules } from '../../../../functions/forms'
6
+ import { formatByPattern, mapToFormItemRules, renderData } from '../../../../functions/forms'
7
7
  import { DisabledFieldIndicator } from '../../../common/disabled-field-indicator'
8
8
  import CustomColorField from '../../../common/color-field'
9
9
  import { IDataSanitization, IValidationRule } from '../../../../types'
@@ -83,6 +83,7 @@ const getField = ({
83
83
  isCustom,
84
84
  country = CountryEnum.US,
85
85
  decimalPoint = 0,
86
+ mode,
86
87
  disabledDate,
87
88
  }: Partial<IMapperFieldObj>): JSX.Element => {
88
89
  placeholder = placeholder && placeholder.length > 0 ? placeholder : typeof label === 'string' ? label : ''
@@ -99,13 +100,44 @@ const getField = ({
99
100
  disabled={disabled}
100
101
  showSearch
101
102
  optionFilterProp="label"
102
- filterOption={(input, option) =>
103
- option && typeof option.label === 'string'
104
- ? option.label.toLowerCase().indexOf(input.toLowerCase()) >= 0
105
- : false
106
- }
103
+ filterOption={(input, option) => {
104
+ const noOtherField = !option?.field2 && !option?.field3 && !option?.field4
105
+ const text = option
106
+ ? typeof option.label === 'string' && noOtherField
107
+ ? option.label
108
+ : [option.label, option.field2 ?? '', option.field3 ?? '', option.field4 ?? ''].join(' ')
109
+ : ''
110
+
111
+ return text.toLowerCase().indexOf(input.toLowerCase()) >= 0
112
+ }}
113
+ optionRender={(option: any) => {
114
+ const opData = option.data || {}
115
+ const noOtherField = !opData.field2 && !opData.field3 && !opData.field4
116
+
117
+ if (noOtherField) return option.label
118
+
119
+ return (
120
+ <div key={opData.value} className="flex flex-col gap-0.5">
121
+ <div className="space-x-2">
122
+ <span className="text-primary font-bold">{opData.label}</span>
123
+ {opData.field2 && (
124
+ <span className="text-12 italic font-normal">
125
+ ({opData.field2_RC ? renderData(opData.field2, opData.field2_RC) : opData.field2})
126
+ </span>
127
+ )}
128
+ </div>
129
+ {opData.field3 && (
130
+ <div className="text-12">
131
+ {opData.field3_RC ? renderData(opData.field3, opData.field3_RC) : opData.field3}
132
+ </div>
133
+ )}
134
+ {opData.field4 && opData.field4_RC ? renderData(opData.field4, opData.field4_RC) : opData.field4}
135
+ </div>
136
+ )
137
+ }}
107
138
  allowClear={allowClear}
108
139
  className="w-full"
140
+ mode={mode}
109
141
  />
110
142
  )
111
143
  case ElementTypeEnum.Checkbox:
@@ -220,11 +252,13 @@ interface IMapperFieldObj {
220
252
  sanitization?: IDataSanitization
221
253
  country?: CountryEnum
222
254
  decimalPoint?: number
255
+ mode?: 'multiple' | 'tags'
223
256
  disabledDate?: (date: Dayjs) => boolean
224
257
  }
225
258
  interface ISelectOption {
226
259
  value: number | boolean | string
227
260
  label: string | ReactNode
261
+ [key: string]: any
228
262
  }
229
263
  const datepickerFormats = [
230
264
  'MM/DD/YYYY',
@@ -13,7 +13,7 @@ export default function LayoutRenderer_ReCaptcha({
13
13
  }: ILayoutRenderer_RichEditor) {
14
14
  const { formRef, formKey } = formContext
15
15
  const [tokenVerificationFailed, setTokenVerificationFailed] = useState(false)
16
- const verifyApiCancelFuncRef = useRef<() => void | undefined>(undefined)
16
+ const verifyApiCancelFuncRef = useRef<() => void | undefined>()
17
17
 
18
18
  const verifyReCaptcha = useCallback(
19
19
  (token: string | null) => {
@@ -1,14 +1,13 @@
1
1
  import { Form } from 'antd'
2
2
  import { useEffect, useMemo, useRef } from 'react'
3
3
  import SignatureCanvas from 'react-signature-canvas'
4
- import { NEW_FORM_DATA_IDENTIFIER } from '../../../../constants'
5
4
  import { FormPreservedItemKeys } from '../../../../enums'
6
5
  import { Button_FillerPortal } from '../../../common/button'
7
6
  import { useFormPreservedItemValues } from '../../../common/custom-hooks/use-preserved-form-items.hook'
8
7
  import { IElementBaseProps } from '.'
9
8
  import { ISignatureElementProps, IValidationRule } from '../../../../types'
10
9
  import { IFormContext } from '../1-row'
11
- import { mapToFormItemRules } from '../../../../functions'
10
+ import { isNewFormDataPage, mapToFormItemRules } from '../../../../functions'
12
11
 
13
12
  export default function LayoutRenderer_Signature({
14
13
  formItem,
@@ -55,7 +54,7 @@ export default function LayoutRenderer_Signature({
55
54
  }
56
55
  labelAlign="left"
57
56
  >
58
- {(inPreviewMode || formDataId === NEW_FORM_DATA_IDENTIFIER) && !isGeneratingPdf ? (
57
+ {(inPreviewMode || isNewFormDataPage(formDataId)) && !isGeneratingPdf ? (
59
58
  <SignatureCanvas
60
59
  ref={sigCanvasRef}
61
60
  canvasProps={{