@engagebay/engagebay-form-module 1.0.2-beta.7 → 1.0.2

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@engagebay/engagebay-form-module",
3
- "version": "1.0.2-beta.7",
3
+ "version": "1.0.2",
4
4
  "description": "Provide base form components to reacho",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1"
@@ -16,6 +16,7 @@
16
16
  "@heroicons/react": ">=2.1.5",
17
17
  "@reduxjs/toolkit": ">=2.2.7",
18
18
  "@tippyjs/react": ">=4.2.6",
19
+ "@types/lodash": ">=4.17.7",
19
20
  "@types/react-redux": ">=7.1.33",
20
21
  "axios": ">=1.7.2",
21
22
  "clsx": ">=2.1.1",
@@ -31,6 +32,7 @@
31
32
  "@heroicons/react": ">=2.1.5",
32
33
  "@reduxjs/toolkit": ">=2.2.7",
33
34
  "@tippyjs/react": ">=4.2.6",
35
+ "@types/lodash": ">=4.17.7",
34
36
  "@types/react-redux": ">=7.1.33",
35
37
  "axios": ">=1.7.2",
36
38
  "clsx": ">=2.1.1",
@@ -34,7 +34,6 @@ import {
34
34
  FormFieldType,
35
35
  OptionMappingConfig,
36
36
  } from "./schema/FormFieldSchema";
37
- import Typeahead2 from "./formfields/Typeahead2";
38
37
 
39
38
  /**
40
39
  * @property {React.FC<FormFieldComponentPropSchema>} component - React component for a form field.
@@ -140,9 +139,6 @@ const formFieldComponents: FormComponentSchema = {
140
139
  [FormFieldType[FormFieldType.TYPEAHEAD_MULTI_SELECT]]: {
141
140
  component: TypeaheadMultiSelect,
142
141
  },
143
- [FormFieldType[FormFieldType.TYPEAHEAD_2]]: {
144
- component: Typeahead2,
145
- },
146
142
  [FormFieldType[FormFieldType.COMBO_SELECT]]: {
147
143
  component: ComboSelect,
148
144
  },
@@ -21,6 +21,7 @@ import FormField from "../FormField";
21
21
  import RenderFormField from "../util/RenderFormField";
22
22
  import { TrashIcon, XMarkIcon } from "@heroicons/react/24/outline";
23
23
  import Tippy from "@tippyjs/react";
24
+ import { set } from "lodash";
24
25
 
25
26
  const defaultBusinessHours = {
26
27
  MONDAY: {
@@ -123,8 +124,9 @@ export const BusinessHoursField: React.FC<FormFieldComponentPropSchema> = (
123
124
  <div className="w-full sm:w-full text-end mr-[2.3em]">
124
125
  <button
125
126
  type="button"
126
- className={`text-end text-primary cursor-pointer font-[13px] font-medium ${getValues(`${mappedName}.sessions`)?.length > 1 ? "mr-9" : ""
127
- }`}
127
+ className={`text-end text-primary cursor-pointer font-[13px] font-medium ${
128
+ getValues(`${mappedName}.sessions`)?.length > 1 ? "mr-9" : ""
129
+ }`}
128
130
  onClick={() => {
129
131
  const lastEndTime =
130
132
  getValues(`${mappedName}.sessions`)?.[
@@ -8,7 +8,7 @@ import { handleChange, registerFormField } from "../util";
8
8
  import moment from "moment";
9
9
 
10
10
  const DatePicker: React.FC<FormFieldComponentPropSchema> = (
11
- props: FormFieldComponentPropSchema,
11
+ props: FormFieldComponentPropSchema
12
12
  ) => {
13
13
  const formContext = useContext(FormContext);
14
14
  const initialDate = formContext.getValues(props.fieldConfig.name)
@@ -25,38 +25,24 @@ const DatePicker: React.FC<FormFieldComponentPropSchema> = (
25
25
  ) {
26
26
  formContext.setValue(
27
27
  props.fieldConfig.name,
28
- props.fieldConfig.defaultValue,
28
+ props.fieldConfig.defaultValue
29
29
  );
30
30
  }
31
31
  }, [props.fieldConfig.forceUpdate]);
32
32
 
33
33
  let registerOptions: RegisterOptions = registerFormField(props.fieldConfig);
34
- //registerOptions.valueAsDate = true;
34
+
35
35
  let hookProps = formContext.register(props.fieldConfig.name, registerOptions);
36
36
 
37
37
  function getInput() {
38
- const rawStart =
39
- initialDate?.startDate ||
40
- props.fieldConfig.defaultValue ||
41
- "";
42
- const rawEnd =
43
- initialDate?.endDate ||
44
- props.fieldConfig.defaultValue ||
45
- "";
46
- const toDate = (v: string | Date | null | undefined): Date | null => {
47
- if (v == null || v === "") return null;
48
- return moment(v).isValid() ? moment(v).toDate() : null;
49
- };
50
- const value = {
51
- startDate: toDate(rawStart),
52
- endDate: toDate(rawEnd),
53
- };
54
- // Calendar opens on selected date's month/year (must be a Date instance)
55
- const startFrom = value.startDate instanceof Date ? value.startDate : new Date();
56
38
  return (
57
39
  <Datepicker
58
- value={value}
59
- startFrom={startFrom}
40
+ value={
41
+ initialDate || {
42
+ startDate: props.fieldConfig.defaultValue,
43
+ endDate: props.fieldConfig.defaultValue,
44
+ }
45
+ }
60
46
  {...hookProps}
61
47
  placeholder={
62
48
  props.fieldConfig.placeholder
@@ -67,7 +53,13 @@ const DatePicker: React.FC<FormFieldComponentPropSchema> = (
67
53
  popoverDirection="down"
68
54
  useRange={false}
69
55
  inputName={props.fieldConfig.name}
70
- key={props.fieldConfig.name + "_" + rawStart + "_" + rawEnd}
56
+ key={
57
+ props.fieldConfig.name +
58
+ "_" +
59
+ initialDate.startDate +
60
+ "_" +
61
+ initialDate.endDate
62
+ }
71
63
  containerClassName={"relative"}
72
64
  minDate={props.fieldConfig.minDate}
73
65
  maxDate={props.fieldConfig.maxDate}
@@ -1,62 +1,61 @@
1
- import React, { useContext } from "react";
2
- import { RegisterOptions } from "react-hook-form";
3
- import { FormContext } from "../context/FormContext";
4
- import { FormFieldComponentPropSchema } from "../schema/FormFieldSchema";
5
- import { handleChange, registerFormField } from "../util";
1
+ import React, {useContext} from "react";
2
+ import {RegisterOptions} from "react-hook-form";
3
+ import {FormContext} from "../context/FormContext";
4
+ import {FormFieldComponentPropSchema} from "../schema/FormFieldSchema";
5
+ import {handleChange, registerFormField} from "../util";
6
6
  import RenderFormField from "../util/RenderFormField";
7
7
 
8
8
  const NumberField: React.FC<FormFieldComponentPropSchema> = (
9
- props: FormFieldComponentPropSchema,
9
+ props: FormFieldComponentPropSchema
10
10
  ) => {
11
- const formContext = useContext(FormContext);
11
+ const formContext = useContext(FormContext);
12
12
 
13
- let registerOptions: RegisterOptions = registerFormField(props.fieldConfig);
14
- registerOptions.valueAsNumber = true;
15
- let hookProps = formContext.register(props.fieldConfig.name, registerOptions);
13
+ let registerOptions: RegisterOptions = registerFormField(props.fieldConfig);
14
+
15
+ let hookProps = formContext.register(props.fieldConfig.name, registerOptions);
16
+
17
+ function getInput() {
18
+ return (
19
+ <input
20
+ type="number"
21
+ {...hookProps}
22
+ placeholder={props.fieldConfig?.placeholder}
23
+ readOnly={props.fieldConfig?.readOnly}
24
+ disabled={props.fieldConfig?.disabled}
25
+ autoComplete={props.fieldConfig?.autoComplete}
26
+ min={props.fieldConfig?.min}
27
+ max={props.fieldConfig?.max}
28
+ step={props.fieldConfig.decimalAllowed ? 0.01 : 1}
29
+ defaultValue={props.fieldConfig.defaultValue as string}
30
+ className={`form-input ${
31
+ props.fieldConfig.customClassNames?.fieldClassName || "flex-1 !w-60"
32
+ }`}
33
+ onKeyDown={(e) => {
34
+ props.fieldConfig.onKeyDown && props.fieldConfig.onKeyDown(e);
35
+ }}
36
+ onChange={(e) => {
37
+ let value = e.target.value;
38
+ let numericValue = parseFloat(value);
39
+ if (props.fieldConfig.max !== undefined && numericValue > props.fieldConfig.max) {
40
+ numericValue = props.fieldConfig.max;
41
+ }
42
+ if (props.fieldConfig.min !== undefined && numericValue < props.fieldConfig.min) {
43
+ numericValue = props.fieldConfig.min;
44
+ }
45
+ value = numericValue.toString();
46
+ handleChange(
47
+ value,
48
+ formContext,
49
+ props.fieldConfig,
50
+ props.onChange
51
+ );
52
+ }}
53
+ />
54
+ );
55
+ }
16
56
 
17
- function getInput() {
18
57
  return (
19
- <input
20
- type="number"
21
- {...hookProps}
22
- placeholder={props.fieldConfig?.placeholder}
23
- readOnly={props.fieldConfig?.readOnly}
24
- disabled={props.fieldConfig?.disabled}
25
- autoComplete={props.fieldConfig?.autoComplete}
26
- min={props.fieldConfig?.min}
27
- max={props.fieldConfig?.max}
28
- step={props.fieldConfig.decimalAllowed ? 0.01 : 1}
29
- defaultValue={props.fieldConfig.defaultValue as string}
30
- className={`form-input ${
31
- props.fieldConfig.customClassNames?.fieldClassName || "flex-1"
32
- }`}
33
- onKeyDown={(e) => {
34
- props.fieldConfig.onKeyDown && props.fieldConfig.onKeyDown(e);
35
- }}
36
- onChange={(e) => {
37
- let value = e.target.value;
38
- let numericValue = parseFloat(value);
39
- if (
40
- props.fieldConfig.max !== undefined &&
41
- numericValue > props.fieldConfig.max
42
- ) {
43
- numericValue = props.fieldConfig.max;
44
- }
45
- if (
46
- props.fieldConfig.min !== undefined &&
47
- numericValue < props.fieldConfig.min
48
- ) {
49
- numericValue = props.fieldConfig.min;
50
- }
51
- value = numericValue.toString();
52
- handleChange(value, formContext, props.fieldConfig, props.onChange);
53
- }}
54
- />
58
+ <RenderFormField fieldConfig={props.fieldConfig} getInput={getInput}/>
55
59
  );
56
- }
57
-
58
- return (
59
- <RenderFormField fieldConfig={props.fieldConfig} getInput={getInput} />
60
- );
61
60
  };
62
61
  export default NumberField;
@@ -1,9 +1,9 @@
1
1
  import React, {
2
- useCallback,
3
- useContext,
4
- useEffect,
5
- useRef,
6
- useState,
2
+ useCallback,
3
+ useContext,
4
+ useEffect,
5
+ useRef,
6
+ useState,
7
7
  } from "react";
8
8
 
9
9
  import { Listbox, ListboxButton } from "@headlessui/react";
@@ -12,185 +12,199 @@ import { RegisterOptions } from "react-hook-form";
12
12
  import { FormContext } from "../context/FormContext";
13
13
  import { getListOption, getListOptions } from "../FormFieldUtils";
14
14
  import {
15
- FieldOptionsSchema,
16
- FormFieldComponentPropSchema,
17
- FormFieldType,
18
- OutputFormatType,
15
+ FieldOptionsSchema,
16
+ FormFieldComponentPropSchema,
17
+ FormFieldType,
18
+ OutputFormatType,
19
19
  } from "../schema/FormFieldSchema";
20
20
  import { handleChange, registerFormField } from "../util";
21
21
  import RenderFormField from "../util/RenderFormField";
22
22
  import RenderListOptions, {
23
- renderListBoxValue,
23
+ renderListBoxValue,
24
24
  } from "../util/RenderListOptions";
25
25
 
26
26
  const Typeahead: React.FC<FormFieldComponentPropSchema> = (
27
- props: FormFieldComponentPropSchema,
27
+ props: FormFieldComponentPropSchema
28
28
  ) => {
29
- const dynamicSelectRef = useRef<HTMLUListElement>(null);
30
- const formContext = useContext(FormContext);
31
- let registerOptions: RegisterOptions = registerFormField(props.fieldConfig);
32
- let hookProps = formContext.register(props.fieldConfig.name, registerOptions);
33
- const [listOptions, setListOptions] = useState<FieldOptionsSchema[]>([]);
34
- const [selectedValues, setSelectedValues] = useState<FieldOptionsSchema[]>(
35
- [],
36
- );
37
- const [loading, setLoading] = useState<boolean>(true);
38
-
39
- useEffect(() => {
40
- if (
41
- !formContext.getValues(props.fieldConfig.name) &&
42
- props.fieldConfig.defaultValue
43
- ) {
44
- formContext.setValue(
29
+ const dynamicSelectRef = useRef<HTMLUListElement>(null);
30
+ const formContext = useContext(FormContext);
31
+ let registerOptions: RegisterOptions = registerFormField(props.fieldConfig);
32
+ let hookProps = formContext.register(
45
33
  props.fieldConfig.name,
46
- props.fieldConfig.defaultValue,
47
- );
48
- }
49
- fetchData(undefined);
50
- }, []);
51
-
52
- const fetchData = useCallback(
53
- async (_query: string | undefined) => {
54
- setLoading(true);
55
- try {
56
- if (!props.fieldConfig.fetchUrl) return;
34
+ registerOptions
35
+ );
36
+ const [listOptions, setListOptions] = useState<FieldOptionsSchema[]>([]);
37
+ const [selectedValues, setSelectedValues] = useState<FieldOptionsSchema[]>(
38
+ []
39
+ );
40
+ const [loading, setLoading] = useState<boolean>(true);
57
41
 
58
- let url = props.fieldConfig.fetchUrl;
59
- if (_query) {
60
- url = url.includes("?") ? url + "&q=" + _query : url + "?q=" + _query;
42
+ useEffect(() => {
43
+ if (
44
+ !formContext.getValues(props.fieldConfig.name) &&
45
+ props.fieldConfig.defaultValue
46
+ ) {
47
+ formContext.setValue(
48
+ props.fieldConfig.name,
49
+ props.fieldConfig.defaultValue
50
+ );
61
51
  }
52
+ fetchData(undefined);
53
+ }, []);
62
54
 
63
- let response = await (props.fieldConfig.disableHeaderInFetch
64
- ? axios.get(url)
65
- : formContext.axiosInstance?.get(url));
66
- if (response?.data) {
67
- const data: FieldOptionsSchema[] = getListOptions(
68
- response.data,
69
- props.fieldConfig.optionsConfig,
70
- );
71
- setListOptions([...data]);
72
- let value = formContext.getValues(props.fieldConfig.name);
73
- if (value && data.find((i) => i.value !== value)) {
74
- if (selectedValues.find((i) => i.value !== value))
75
- fetchValue(value);
76
- }
77
- if (props.fieldConfig.fetchCallback) {
78
- props.fieldConfig.fetchCallback(response);
79
- }
80
- } else {
81
- console.error(response?.statusText);
82
- }
83
- } catch (err) {
84
- } finally {
85
- setLoading(false);
86
- }
87
- },
88
- [props.fieldConfig.fetchUrl],
89
- );
55
+ const fetchData = useCallback(
56
+ async (_query: string | undefined) => {
57
+ setLoading(true);
58
+ try {
59
+ if (!props.fieldConfig.fetchUrl) return;
60
+
61
+ let url = props.fieldConfig.fetchUrl;
62
+ if (_query) {
63
+ url = url.includes("?")
64
+ ? url + "&q=" + _query
65
+ : url + "?q=" + _query;
66
+ }
67
+
68
+ let response = await (props.fieldConfig.disableHeaderInFetch
69
+ ? axios.get(url)
70
+ : formContext.axiosInstance?.get(url));
71
+ if (response?.data) {
72
+ const data: FieldOptionsSchema[] = getListOptions(
73
+ response.data,
74
+ props.fieldConfig.optionsConfig
75
+ );
76
+ setListOptions([...data]);
77
+ let value = formContext.getValues(props.fieldConfig.name);
78
+ if (
79
+ value &&
80
+ data.find((i) => i.value !== value)
81
+ ) {
82
+ if (selectedValues.find((i) => i.value !== value))
83
+ fetchValue(value);
84
+ }
85
+ if (props.fieldConfig.fetchCallback) {
86
+ props.fieldConfig.fetchCallback(response);
87
+ }
88
+ } else {
89
+ console.error(response?.statusText);
90
+ }
91
+ } catch (err) {
92
+ } finally {
93
+ setLoading(false);
94
+ }
95
+ },
96
+ [props.fieldConfig.fetchUrl]
97
+ );
90
98
 
91
- const fetchValue = async (value: string) => {
92
- try {
93
- if (props.fieldConfig.ignoreFetchValue || !props.fieldConfig.fetchUrl) {
94
- return;
95
- }
99
+ const fetchValue = async (value: string) => {
100
+ try {
101
+ if (
102
+ props.fieldConfig.ignoreFetchValue ||
103
+ !props.fieldConfig.fetchUrl
104
+ ) {
105
+ return;
106
+ }
96
107
 
97
- let url = props.fieldConfig.fetchUrl;
108
+ let url = props.fieldConfig.fetchUrl;
98
109
 
99
- if (value)
100
- url = url.includes("?")
101
- ? url + "&values=" + value
102
- : url + "?values=" + value;
110
+ if (value)
111
+ url = url.includes("?")
112
+ ? url + "&values=" + value
113
+ : url + "?values=" + value;
103
114
 
104
- let response = await (props.fieldConfig.disableHeaderInFetch
105
- ? axios.get(url)
106
- : formContext.axiosInstance?.get(url));
107
- if (response?.data) {
108
- const data: FieldOptionsSchema[] = getListOptions(
109
- response?.data,
110
- props.fieldConfig.optionsConfig,
115
+ let response = await (
116
+ props.fieldConfig.disableHeaderInFetch
117
+ ? axios.get(url)
118
+ : formContext.axiosInstance?.get(url)
119
+ );
120
+ if (response?.data) {
121
+ const data: FieldOptionsSchema[] = getListOptions(
122
+ response?.data,
123
+ props.fieldConfig.optionsConfig
124
+ );
125
+ setSelectedValues([...data]);
126
+ }
127
+ } catch (err) { }
128
+ };
129
+
130
+ const updateListOptions = (data: any) => {
131
+ const resData: FieldOptionsSchema = getListOption(
132
+ data,
133
+ props.fieldConfig.optionsConfig
111
134
  );
112
- setSelectedValues([...data]);
113
- }
114
- } catch (err) {}
115
- };
135
+ setSelectedValues((perv) => [resData]);
136
+ formContext.setValue(props.fieldConfig.name, resData.value);
137
+ };
116
138
 
117
- const updateListOptions = (data: any) => {
118
- const resData: FieldOptionsSchema = getListOption(
119
- data,
120
- props.fieldConfig.optionsConfig,
121
- );
122
- setSelectedValues((perv) => [resData]);
123
- formContext.setValue(props.fieldConfig.name, resData.value);
124
- };
139
+ function getInput() {
140
+ return (
141
+ <Listbox
142
+ as={"div"}
143
+ {...hookProps}
144
+ className={`relative form-listbox flex-1`}
145
+ value={
146
+ formContext.getValues(props.fieldConfig.name)
147
+ ? props.fieldConfig.outputFormat ===
148
+ OutputFormatType.ARRAY
149
+ ? formContext.getValues(props.fieldConfig.name)[0]
150
+ : formContext.getValues(props.fieldConfig.name)
151
+ : undefined
152
+ }
153
+ onChange={(val) => {
154
+ const currentValue = formContext.getValues(
155
+ props.fieldConfig.name
156
+ );
125
157
 
126
- function getInput() {
127
- return (
128
- <Listbox
129
- as={"div"}
130
- {...hookProps}
131
- className={`relative form-listbox flex-1`}
132
- value={
133
- formContext.getValues(props.fieldConfig.name)
134
- ? props.fieldConfig.outputFormat === OutputFormatType.ARRAY
135
- ? formContext.getValues(props.fieldConfig.name)[0]
136
- : formContext.getValues(props.fieldConfig.name)
137
- : undefined
138
- }
139
- onChange={(val) => {
140
- const currentValue = formContext.getValues(props.fieldConfig.name);
158
+ // If the value matches, set it to null, otherwise set it to val
159
+ const newValue = currentValue === val ? null : val;
141
160
 
142
- // If the value matches, set it to null, otherwise set it to val
143
- const newValue = currentValue === val ? null : val;
161
+ const selected = listOptions.find(o => o.value == newValue);
162
+ selected && setSelectedValues([selected]);
163
+ handleChange(
164
+ newValue,
165
+ formContext,
166
+ props.fieldConfig,
167
+ props.onChange
168
+ );
169
+ }}
170
+ name={props.fieldConfig.name}
171
+ disabled={props.fieldConfig.disabled}>
172
+ <ListboxButton
173
+ className={
174
+ props.fieldConfig.customClassNames?.fieldClassName
175
+ ? "form-listbox-select " +
176
+ props.fieldConfig.customClassNames?.fieldClassName
177
+ : "form-listbox-select"
178
+ }>
179
+ {renderListBoxValue(
180
+ formContext,
181
+ props.fieldConfig,
182
+ [...selectedValues, ...listOptions],
183
+ props.onChange
184
+ )}
185
+ </ListboxButton>
186
+ <RenderListOptions
187
+ formContext={formContext}
188
+ onChange={props.onChange}
189
+ formField={FormFieldType.TYPEAHEAD}
190
+ ref={dynamicSelectRef}
191
+ fieldConfig={props.fieldConfig}
192
+ listOptions={[...selectedValues, ...listOptions]}
193
+ setListOptions={setListOptions}
194
+ loading={loading}
195
+ setLoading={setLoading}
196
+ createCallback={(data) => updateListOptions(data)}
197
+ queryCallback={(query) => fetchData(query)}
198
+ />
199
+ </Listbox>
200
+ );
201
+ }
202
+ if (props.fieldConfig.hideWhenNoResults && listOptions.length == 0) {
203
+ return <></>;
204
+ }
144
205
 
145
- const selected = listOptions.find((o) => o.value == newValue);
146
- selected && setSelectedValues([selected]);
147
- handleChange(
148
- newValue,
149
- formContext,
150
- props.fieldConfig,
151
- props.onChange,
152
- );
153
- }}
154
- name={props.fieldConfig.name}
155
- disabled={props.fieldConfig.disabled}
156
- >
157
- <ListboxButton
158
- className={
159
- props.fieldConfig.customClassNames?.fieldClassName
160
- ? "form-listbox-select " +
161
- props.fieldConfig.customClassNames?.fieldClassName
162
- : "form-listbox-select"
163
- }
164
- >
165
- {renderListBoxValue(
166
- formContext,
167
- props.fieldConfig,
168
- [...selectedValues, ...listOptions],
169
- props.onChange,
170
- )}
171
- </ListboxButton>
172
- <RenderListOptions
173
- formContext={formContext}
174
- onChange={props.onChange}
175
- formField={FormFieldType.TYPEAHEAD}
176
- ref={dynamicSelectRef}
177
- fieldConfig={props.fieldConfig}
178
- listOptions={[...selectedValues, ...listOptions]}
179
- setListOptions={setListOptions}
180
- loading={loading}
181
- setLoading={setLoading}
182
- createCallback={(data) => updateListOptions(data)}
183
- queryCallback={(query) => fetchData(query)}
184
- />
185
- </Listbox>
206
+ return (
207
+ <RenderFormField fieldConfig={props.fieldConfig} getInput={getInput} />
186
208
  );
187
- }
188
- if (props.fieldConfig.hideWhenNoResults && listOptions.length == 0) {
189
- return <></>;
190
- }
191
-
192
- return (
193
- <RenderFormField fieldConfig={props.fieldConfig} getInput={getInput} />
194
- );
195
209
  };
196
210
  export default Typeahead;
@@ -23,10 +23,9 @@ import RenderListOptions, {
23
23
  } from "../util/RenderListOptions";
24
24
  // import _ from "lodash";
25
25
  import axios from "axios";
26
- import { getAxiosInstance } from "../../api";
27
26
 
28
27
  const TypeaheadMultiSelect: React.FC<FormFieldComponentPropSchema> = (
29
- props: FormFieldComponentPropSchema,
28
+ props: FormFieldComponentPropSchema
30
29
  ) => {
31
30
  const dynamicSelectRef = useRef<HTMLUListElement>(null);
32
31
  const formContext = useContext(FormContext);
@@ -34,7 +33,7 @@ const TypeaheadMultiSelect: React.FC<FormFieldComponentPropSchema> = (
34
33
  let hookProps = formContext.register(props.fieldConfig.name, registerOptions);
35
34
  const [listOptions, setListOptions] = useState<FieldOptionsSchema[]>([]);
36
35
  const [selectedValues, setSelectedValues] = useState<FieldOptionsSchema[]>(
37
- [],
36
+ []
38
37
  );
39
38
  const [loading, setLoading] = useState<boolean>(true);
40
39
 
@@ -45,7 +44,7 @@ const TypeaheadMultiSelect: React.FC<FormFieldComponentPropSchema> = (
45
44
  ) {
46
45
  formContext.setValue(
47
46
  props.fieldConfig.name,
48
- props.fieldConfig.defaultValue,
47
+ props.fieldConfig.defaultValue
49
48
  );
50
49
  }
51
50
  fetchData(undefined);
@@ -61,16 +60,14 @@ const TypeaheadMultiSelect: React.FC<FormFieldComponentPropSchema> = (
61
60
  if (_query) {
62
61
  url = url.includes("?") ? url + "&q=" + _query : url + "?q=" + _query;
63
62
  }
64
- const axiosInstance = getAxiosInstance(
65
- formContext.axiosInstance,
66
- props.fieldConfig,
67
- );
68
63
 
69
- let response = await axiosInstance.get(url);
64
+ let response = await (props.fieldConfig.disableHeaderInFetch
65
+ ? axios.get(url)
66
+ : formContext.axiosInstance?.get(url));
70
67
  if (response?.data) {
71
68
  const data: FieldOptionsSchema[] = getListOptions(
72
69
  response?.data,
73
- props.fieldConfig.optionsConfig,
70
+ props.fieldConfig.optionsConfig
74
71
  );
75
72
  setListOptions([...data]);
76
73
  let values = formContext.getValues(props.fieldConfig.name) || [];
@@ -80,7 +77,7 @@ const TypeaheadMultiSelect: React.FC<FormFieldComponentPropSchema> = (
80
77
  (data.length === 0 || // If 'data' is empty
81
78
  (!values.every((v: string) => data.some((i) => i.value === v)) && // Ensure none of 'values' match 'data'
82
79
  !values.every((v: string) =>
83
- selectedValues.some((i) => i.value === v),
80
+ selectedValues.some((i) => i.value === v)
84
81
  ))) // Ensure none of 'values' match 'selectedValues'
85
82
  ) {
86
83
  fetchValue(values); // Call 'fetchValue()' if all conditions are met
@@ -97,7 +94,7 @@ const TypeaheadMultiSelect: React.FC<FormFieldComponentPropSchema> = (
97
94
  setLoading(false);
98
95
  }
99
96
  },
100
- [props.fieldConfig.fetchUrl],
97
+ [props.fieldConfig.fetchUrl]
101
98
  );
102
99
 
103
100
  const fetchValue = async (value: string) => {
@@ -108,7 +105,7 @@ const TypeaheadMultiSelect: React.FC<FormFieldComponentPropSchema> = (
108
105
 
109
106
  let url = props.fieldConfig.fetchUrl;
110
107
 
111
- url = url.includes("?")
108
+ url = url = url.includes("?")
112
109
  ? url + "&values=" + value
113
110
  : url + "?values=" + value;
114
111
 
@@ -118,7 +115,7 @@ const TypeaheadMultiSelect: React.FC<FormFieldComponentPropSchema> = (
118
115
  if (response?.data) {
119
116
  const data: FieldOptionsSchema[] = getListOptions(
120
117
  response?.data,
121
- props.fieldConfig.optionsConfig,
118
+ props.fieldConfig.optionsConfig
122
119
  );
123
120
  let values: any[] = formContext.getValues(props.fieldConfig.name) || [];
124
121
  setSelectedValues(
@@ -126,22 +123,22 @@ const TypeaheadMultiSelect: React.FC<FormFieldComponentPropSchema> = (
126
123
  ...data,
127
124
  props.fieldConfig.dropdownFieldConfig?.isSuggestionBox && values
128
125
  ? values
129
- .filter(
130
- (value) =>
131
- data.some((d) => d.value !== value) || data.length == 0,
132
- )
133
- .map((val) => ({ label: val, value: val }))
126
+ .filter(
127
+ (value) =>
128
+ data.some((d) => d.value !== value) || data.length == 0
129
+ )
130
+ .map((val) => ({ label: val, value: val }))
134
131
  : [],
135
- ].flat(),
132
+ ].flat()
136
133
  );
137
134
  }
138
- } catch (err) { }
135
+ } catch (err) {}
139
136
  };
140
137
 
141
138
  const updateListOptions = (data: any) => {
142
139
  const resData: FieldOptionsSchema = getListOption(
143
140
  data,
144
- props.fieldConfig.optionsConfig,
141
+ props.fieldConfig.optionsConfig
145
142
  );
146
143
  setSelectedValues((prev) => [...prev, resData]);
147
144
  let result = formContext.getValues(props.fieldConfig.name) || [];
@@ -163,14 +160,14 @@ const TypeaheadMultiSelect: React.FC<FormFieldComponentPropSchema> = (
163
160
  className={"relative form-listbox flex-1 overflow-hidden"}
164
161
  onChange={(selectedOptions) => {
165
162
  const chossenOptions = listOptions.filter((op) =>
166
- selectedOptions.includes(op.value),
163
+ selectedOptions.includes(op.value)
167
164
  );
168
165
  setSelectedValues((prev) => [...prev, ...chossenOptions]);
169
166
  handleChange(
170
167
  selectedOptions,
171
168
  formContext,
172
169
  props.fieldConfig,
173
- props.onChange,
170
+ props.onChange
174
171
  );
175
172
  }}
176
173
  multiple
@@ -179,7 +176,7 @@ const TypeaheadMultiSelect: React.FC<FormFieldComponentPropSchema> = (
179
176
  className={
180
177
  props.fieldConfig.customClassNames?.fieldClassName
181
178
  ? "form-listbox-select " +
182
- props.fieldConfig.customClassNames?.fieldClassName
179
+ props.fieldConfig.customClassNames?.fieldClassName
183
180
  : "form-listbox-select"
184
181
  }
185
182
  >
@@ -187,7 +184,7 @@ const TypeaheadMultiSelect: React.FC<FormFieldComponentPropSchema> = (
187
184
  formContext,
188
185
  props.fieldConfig,
189
186
  [...selectedValues, ...listOptions],
190
- props.onChange,
187
+ props.onChange
191
188
  )}
192
189
  </ListboxButton>
193
190
  <RenderListOptions
@@ -37,7 +37,6 @@ export enum FormFieldType {
37
37
  DYNAMIC_MULTI_SELECT = "DYNAMIC_MULTI_SELECT",
38
38
 
39
39
  TYPEAHEAD = "TYPEAHEAD",
40
- TYPEAHEAD_2 = "TYPEAHEAD_2",
41
40
  TYPEAHEAD_MULTI_SELECT = "TYPEAHEAD_MULTI_SELECT",
42
41
  PHONE_NUMBER_INPUT = "PHONE_NUMBER_INPUT",
43
42
  SWITCH = "SWITCH",
@@ -130,12 +129,10 @@ export type FormFieldSchema = {
130
129
  submitOnChange?: boolean;
131
130
  formFieldPattern?: FormFieldPatternsImpl[];
132
131
  fetchUrl?: string;
133
- fetchSavedDataUrl?: string;
134
132
  postUrl?: string;
135
133
  fileAccept?: string;
136
134
  icon?: ReactNode;
137
135
  outputFormat?: OutputFormatType;
138
- isMultiple?: boolean;
139
136
  children?: FormFieldSchema[];
140
137
  defaultOptions?: FieldOptionsSchema[];
141
138
  optionsConfig?: OptionMappingConfig;
@@ -204,7 +201,6 @@ export type FieldOptionsSchema = {
204
201
  isDisabled?: boolean;
205
202
  helpText?: string;
206
203
  groupName?: string;
207
- tooltip?: string;
208
204
  icon?: React.ReactNode;
209
205
  };
210
206
 
@@ -17,7 +17,6 @@ import {
17
17
  FormFieldType,
18
18
  OutputFormatType,
19
19
  } from "../schema/FormFieldSchema";
20
- import Tippy from "@tippyjs/react";
21
20
 
22
21
  type RenderListOptionsProps = {
23
22
  formContext: FormContextType;
@@ -46,7 +45,7 @@ const RenderListOptions = forwardRef<HTMLUListElement, RenderListOptionsProps>(
46
45
  queryCallback,
47
46
  createCallback,
48
47
  },
49
- ref,
48
+ ref
50
49
  ) => {
51
50
  const [query, setQuery] = useState<string>("");
52
51
  const [createdListItems, setCreatedListItems] = useState<
@@ -91,7 +90,7 @@ const RenderListOptions = forwardRef<HTMLUListElement, RenderListOptionsProps>(
91
90
  .filter((result) => result.label)
92
91
  .filter(
93
92
  (option, index, self) =>
94
- index === self.findIndex((obj) => obj.value === option.value),
93
+ index === self.findIndex((obj) => obj.value === option.value)
95
94
  ),
96
95
  ]; // removing duplicate values
97
96
 
@@ -102,15 +101,15 @@ const RenderListOptions = forwardRef<HTMLUListElement, RenderListOptionsProps>(
102
101
 
103
102
  const filteredList = query
104
103
  ? resultList.filter((item) => {
105
- const normalizedLabel = fieldConfig.dropdownFieldConfig
106
- ?.isCaseSensitive
107
- ? item.label
108
- : item.label.toLowerCase();
104
+ const normalizedLabel = fieldConfig.dropdownFieldConfig
105
+ ?.isCaseSensitive
106
+ ? item.label
107
+ : item.label.toLowerCase();
109
108
 
110
- return normalizedLabel
111
- .replace(/\s+/g, "")
112
- .includes(caseSensitive.replace(/\s+/g, ""));
113
- })
109
+ return normalizedLabel
110
+ .replace(/\s+/g, "")
111
+ .includes(caseSensitive.replace(/\s+/g, ""));
112
+ })
114
113
  : resultList;
115
114
 
116
115
  let nullGroupOptions: any[] = [];
@@ -127,15 +126,13 @@ const RenderListOptions = forwardRef<HTMLUListElement, RenderListOptionsProps>(
127
126
  }, {});
128
127
 
129
128
  const handleQueryCallback = useCallback(() => {
130
- if (filteredList.length < 5 && isTypeahead) {
129
+ if (filteredList.length == 0 && isTypeahead) {
131
130
  queryCallback && queryCallback(query);
132
131
  }
133
132
  }, [filteredList]);
134
133
 
135
134
  useEffect(() => {
136
- if (formField == FormFieldType.TYPEAHEAD_2)
137
- queryCallback && queryCallback(query);
138
- else handleQueryCallback();
135
+ handleQueryCallback();
139
136
  }, [query]);
140
137
 
141
138
  let enableCreateFlag =
@@ -145,7 +142,6 @@ const RenderListOptions = forwardRef<HTMLUListElement, RenderListOptionsProps>(
145
142
 
146
143
  let validTypeaheadFields = [
147
144
  FormFieldType.TYPEAHEAD,
148
- FormFieldType.TYPEAHEAD_2,
149
145
  FormFieldType.TYPEAHEAD_MULTI_SELECT,
150
146
  ];
151
147
  let isTypeahead: boolean = validTypeaheadFields.indexOf(formField) > -1;
@@ -169,10 +165,11 @@ const RenderListOptions = forwardRef<HTMLUListElement, RenderListOptionsProps>(
169
165
  key={option.value}
170
166
  disabled={option.isDisabled}
171
167
  onClick={() => setTimeout(resetToDefault, 300)}
172
- className={`form-listbox-option ${selected
173
- ? " bg-gray-100 text-gray-900"
174
- : "hover:bg-gray-100 text-gray-700"
175
- }`}
168
+ className={`form-listbox-option ${
169
+ selected
170
+ ? " bg-gray-100 text-gray-900"
171
+ : "hover:bg-gray-100 text-gray-700"
172
+ }`}
176
173
  value={option.value}
177
174
  >
178
175
  {fieldConfig.fieldOptionWrapper ? (
@@ -181,30 +178,17 @@ const RenderListOptions = forwardRef<HTMLUListElement, RenderListOptionsProps>(
181
178
  <>
182
179
  <div className="flex items-center justify-between gap-x-1.5">
183
180
  <span
184
- className={`block truncate w-full ${fieldConfig.customClassNames?.optionClassName} space-x-2 ${selected ? "font-medium" : "font-normal"
185
- }`}
181
+ className={`block truncate w-full !max-w-[150px] space-x-2 ${
182
+ selected ? "font-medium" : "font-normal"
183
+ }`}
186
184
  >
187
185
  {option.icon && (
188
186
  <span className="listbox-svg">{option.icon}</span>
189
187
  )}
190
- {option.tooltip ? (
191
- <Tippy
192
- content={
193
- <>
194
- {option.label}
195
- <br />
196
- {option.helpText}
197
- </>
198
- }
199
- >
200
- <div className="truncate">{option.label}</div>
201
- </Tippy>
202
- ) : (
203
- option.label
204
- )}
188
+ {option.label}
205
189
  </span>
206
190
  {isTypeahead &&
207
- !fieldConfig.dropdownFieldConfig?.isSuggestionBox ? (
191
+ !fieldConfig.dropdownFieldConfig?.isSuggestionBox ? (
208
192
  <input
209
193
  type="checkbox"
210
194
  className="form-checkbox"
@@ -220,30 +204,11 @@ const RenderListOptions = forwardRef<HTMLUListElement, RenderListOptionsProps>(
220
204
  )
221
205
  )}
222
206
  </div>
223
- {option.helpText &&
224
- (option.tooltip ? (
225
- <Tippy
226
- content={
227
- <>
228
- {option.label}
229
- <br />
230
- {option.helpText}
231
- </>
232
- }
233
- >
234
- <div
235
- className={`mt-0 text-xs text-gray-500 font-normal truncate w-full ${fieldConfig.customClassNames?.optionClassName}`}
236
- >
237
- {option.helpText}
238
- </div>
239
- </Tippy>
240
- ) : (
241
- <div
242
- className={`mt-0 text-xs text-gray-500 font-normal truncate w-full ${fieldConfig.customClassNames?.optionClassName}`}
243
- >
244
- {option.helpText}
245
- </div>
246
- ))}
207
+ {option.helpText && (
208
+ <div className="mt-0 text-xs text-gray-500 font-normal truncate w-full !max-w-[150px]">
209
+ {option.helpText}
210
+ </div>
211
+ )}
247
212
  </>
248
213
  )}
249
214
  </ListboxOption>
@@ -353,7 +318,7 @@ const RenderListOptions = forwardRef<HTMLUListElement, RenderListOptionsProps>(
353
318
  </div>
354
319
  </ListboxOptions>
355
320
  );
356
- },
321
+ }
357
322
  );
358
323
 
359
324
  export default RenderListOptions;
@@ -361,7 +326,7 @@ export function renderListBoxValue(
361
326
  formContext: FormContextType,
362
327
  fieldConfig: FormFieldSchema,
363
328
  listOptions: FieldOptionsSchema[],
364
- onChange?: (value: any) => void,
329
+ onChange?: (value: any) => void
365
330
  ): JSX.Element {
366
331
  let value = formContext.getValues(fieldConfig.name);
367
332
  const renderAsString = () => {
@@ -373,17 +338,10 @@ export function renderListBoxValue(
373
338
  return icon ? (
374
339
  <span className="flex items-center fs-8 whitespace-nowrap text-gray-500">
375
340
  <span>{icon}</span>
376
-
377
- <Tippy content={label} delay={500}>
378
- <span className="block truncate">{label}</span>
379
- </Tippy>
341
+ <span>{label} </span>
380
342
  </span>
381
- ) : label ? (
382
- <Tippy content={<>{label}</>} delay={500}>
383
- <span className="block truncate">{label}</span>
384
- </Tippy>
385
343
  ) : (
386
- getPlaceholder()
344
+ label || getPlaceholder()
387
345
  );
388
346
  };
389
347
  const renderAsArray = () => {
@@ -400,28 +358,23 @@ export function renderListBoxValue(
400
358
  {values.length > 1
401
359
  ? `${values.length} selected`
402
360
  : listOptions.find((option) => option.value == value[0])?.label ||
403
- values[0]}
361
+ values[0]}
404
362
  </span>
405
363
  {getDeleteButton()}
406
364
  </span>
407
365
  ) : (
408
366
  Array.isArray(values) &&
409
- values.map((opt: any) => {
410
- const option = listOptions.find((option) => option.value == opt);
411
- if (!option && values.length == 0) return getPlaceholder();
367
+ values.map((opt: any) => {
368
+ const option = listOptions.find((option) => option.value == opt);
369
+ if (!option && values.length == 0) return getPlaceholder();
412
370
 
413
- return (
414
- <span key={option?.value} className="form-selected-badge">
415
- <Tippy content={option?.label} delay={500}>
416
- <span className="form-selected-badge-name">
417
- {option?.label}
418
- </span>
419
- </Tippy>
420
-
421
- {getDeleteButton(opt)}
422
- </span>
423
- );
424
- })
371
+ return (
372
+ <span key={option?.value} className="form-selected-badge">
373
+ <span className="form-selected-badge-name">{option?.label}</span>
374
+ {getDeleteButton(opt)}
375
+ </span>
376
+ );
377
+ })
425
378
  );
426
379
  };
427
380
  const getDeleteButton = (option?: string) => {
@@ -453,10 +406,9 @@ export function renderListBoxValue(
453
406
  )
454
407
  );
455
408
  };
456
- let outputFormat =
457
- fieldConfig.outputFormat != undefined
458
- ? fieldConfig.outputFormat === OutputFormatType.STRING
459
- : false;
409
+ let outputFormat = fieldConfig.outputFormat
410
+ ? fieldConfig.outputFormat === OutputFormatType.ARRAY
411
+ : false;
460
412
  const getPlaceholder = () => (
461
413
  <span className="form-placeholder">
462
414
  {fieldConfig.placeholder || "Select any option"}
@@ -1,283 +0,0 @@
1
- import React, {
2
- useCallback,
3
- useContext,
4
- useEffect,
5
- useMemo,
6
- useRef,
7
- useState,
8
- } from "react";
9
-
10
- import { Listbox, ListboxButton } from "@headlessui/react";
11
- import { RegisterOptions } from "react-hook-form";
12
-
13
- import { FormContext } from "../context/FormContext";
14
- import { getListOption, getListOptions } from "../FormFieldUtils";
15
- import {
16
- FieldOptionsSchema,
17
- FormFieldComponentPropSchema,
18
- FormFieldType,
19
- } from "../schema/FormFieldSchema";
20
- import { handleChange, registerFormField } from "../util";
21
- import RenderFormField from "../util/RenderFormField";
22
- import RenderListOptions, {
23
- renderListBoxValue,
24
- } from "../util/RenderListOptions";
25
- import axios from "axios";
26
- import { getAxiosInstance } from "../../api";
27
-
28
- const Typeahead2: React.FC<FormFieldComponentPropSchema> = (
29
- props: FormFieldComponentPropSchema,
30
- ) => {
31
- const dynamicSelectRef = useRef<HTMLUListElement>(null);
32
- const abortControllerRef = useRef<AbortController | null>(null);
33
- const formContext = useContext(FormContext);
34
- let registerOptions: RegisterOptions = registerFormField(props.fieldConfig);
35
- let hookProps = formContext.register(props.fieldConfig.name, registerOptions);
36
- const [listOptions, setListOptions] = useState<FieldOptionsSchema[]>([]);
37
- const [selectedValues, setSelectedValues] = useState<FieldOptionsSchema[]>(
38
- [],
39
- );
40
- const [loading, setLoading] = useState<boolean>(false);
41
-
42
- useEffect(() => {
43
- if (
44
- !formContext.getValues(props.fieldConfig.name) &&
45
- props.fieldConfig.defaultValue
46
- ) {
47
- formContext.setValue(
48
- props.fieldConfig.name,
49
- props.fieldConfig.defaultValue,
50
- );
51
- }
52
- let values: any | any[] | undefined =
53
- formContext.getValues(props.fieldConfig.name) ||
54
- props.fieldConfig.defaultValue;
55
-
56
- if (values && selectedValues.length < 1) {
57
- if (props.fieldConfig.fetchSavedDataUrl) {
58
- fetchValue(values);
59
- } else {
60
- setSelectedValues(
61
- Array.isArray(values)
62
- ? values.map((val: any) => ({ label: val, value: val }))
63
- : [values],
64
- );
65
- }
66
- }
67
- }, []);
68
-
69
-
70
-
71
- const fetchData = useMemo(() => {
72
- let timeoutId: ReturnType<typeof setTimeout>;
73
-
74
- return (_query: string | undefined) => {
75
- // Clear the previous timer
76
- if (timeoutId) clearTimeout(timeoutId);
77
-
78
- // Set a new timer
79
- timeoutId = setTimeout(async () => {
80
- // 1. Cancel the previous request if it's still pending
81
- if (abortControllerRef.current) {
82
- abortControllerRef.current.abort();
83
- }
84
-
85
- // 2. Create a new controller for the current request
86
- const controller = new AbortController();
87
- abortControllerRef.current = controller;
88
-
89
- if (!_query || _query.length < 3) {
90
- setListOptions([]);
91
- setLoading(false);
92
- return;
93
- }
94
- setLoading(true);
95
- try {
96
- if (!props.fieldConfig.fetchUrl) return;
97
-
98
- let url = props.fieldConfig.fetchUrl;
99
-
100
- url = url.includes("?") ? url + "&q=" + _query : url + "?q=" + _query;
101
-
102
- const axiosInstance = getAxiosInstance(
103
- formContext.axiosInstance,
104
- props.fieldConfig,
105
- );
106
- const response = await axiosInstance.get(url);
107
-
108
- if (controller === abortControllerRef.current) {
109
- if (response?.data) {
110
- const data: FieldOptionsSchema[] = getListOptions(
111
- response?.data,
112
- props.fieldConfig.optionsConfig,
113
- );
114
- setListOptions([...data]);
115
-
116
- if (props.fieldConfig.fetchCallback) {
117
- props.fieldConfig.fetchCallback(response);
118
- }
119
- }
120
- }
121
- } catch (err) {
122
- console.error("Fetch error:", err);
123
- } finally {
124
- // Only stop loading if this was the "active" request
125
- if (controller === abortControllerRef.current) {
126
- setLoading(false);
127
- }
128
- }
129
- }, 250);
130
- };
131
- }, []);
132
-
133
- // Cleanup on unmount
134
- useEffect(() => {
135
- return () => {
136
- abortControllerRef.current?.abort();
137
- };
138
- }, []);
139
-
140
- const fetchValue = async (value: string | any | any[]) => {
141
- try {
142
- if (
143
- props.fieldConfig.ignoreFetchValue ||
144
- !props.fieldConfig.fetchSavedDataUrl
145
- ) {
146
- return;
147
- }
148
-
149
- let url = props.fieldConfig.fetchSavedDataUrl;
150
-
151
- // url = url.includes("?")
152
- // ? url + "&values=" + value
153
- // : url + "?values=" + value;
154
-
155
- let response = await (props.fieldConfig.disableHeaderInFetch
156
- ? axios.post(url, Array.isArray(value) ? value : [value])
157
- : formContext.axiosInstance?.post(
158
- url,
159
- Array.isArray(value) ? value : [value],
160
- ));
161
- if (response?.data) {
162
- const data: FieldOptionsSchema[] = getListOptions(
163
- response?.data,
164
- props.fieldConfig.optionsConfig,
165
- );
166
- let values: any[] = formContext.getValues(props.fieldConfig.name) || [];
167
- setSelectedValues(
168
- [
169
- ...data,
170
- props.fieldConfig.dropdownFieldConfig?.isSuggestionBox &&
171
- values &&
172
- Array.isArray(values)
173
- ? values
174
- .filter(
175
- (value) =>
176
- data.some((d) => d.value !== value) || data.length == 0,
177
- )
178
- .map((val) => ({ label: val, value: val }))
179
- : [],
180
- ].flat(),
181
- );
182
- }
183
- } catch (err) { }
184
- };
185
-
186
- const updateListOptions = (data: any) => {
187
- const resData: FieldOptionsSchema = getListOption(
188
- data,
189
- props.fieldConfig.optionsConfig,
190
- );
191
- setListOptions([]);
192
- setSelectedValues((prev) =>
193
- props.fieldConfig.isMultiple ? [...prev, resData] : [resData],
194
- );
195
- let result = formContext.getValues(props.fieldConfig.name) || [];
196
- result = !props.fieldConfig.isMultiple
197
- ? resData.value
198
- : result.includes(resData.value)
199
- ? [...result.filter((v: string) => v != resData.value), resData.value]
200
- : [...result, resData.value];
201
- formContext.setValue(props.fieldConfig.name, result);
202
- };
203
-
204
- const getInput = () => {
205
- return (
206
- <Listbox
207
- as={"div"}
208
- {...hookProps}
209
- value={
210
- props.fieldConfig.isMultiple
211
- ? formContext.getValues(props.fieldConfig.name)
212
- ? formContext.getValues(props.fieldConfig.name)
213
- : []
214
- : formContext.getValues(props.fieldConfig.name)
215
- }
216
- name={props.fieldConfig.name}
217
- defaultValue={props.fieldConfig.defaultValue}
218
- key={props.fieldConfig.name}
219
- className={"relative form-listbox flex-1 overflow-hidden"}
220
- onChange={(selectedOptions) => {
221
- let currentValue = formContext.getValues(props.fieldConfig.name);
222
- const newValue =
223
- currentValue === selectedOptions ? null : selectedOptions;
224
-
225
- if (props.fieldConfig.isMultiple) {
226
- currentValue = listOptions.filter((op) =>
227
- selectedOptions.includes(op.value),
228
- );
229
- setSelectedValues((prev) => [...prev, ...currentValue]);
230
- } else {
231
- const selected = listOptions.find((o) => o.value == newValue);
232
- selected && setSelectedValues([selected]);
233
- }
234
- setListOptions([]);
235
- handleChange(
236
- newValue,
237
- formContext,
238
- props.fieldConfig,
239
- props.onChange,
240
- );
241
- }}
242
- multiple={props.fieldConfig.isMultiple}
243
- >
244
- <ListboxButton
245
- className={
246
- props.fieldConfig.customClassNames?.fieldClassName
247
- ? "form-listbox-select " +
248
- props.fieldConfig.customClassNames?.fieldClassName
249
- : "form-listbox-select"
250
- }
251
- >
252
- {renderListBoxValue(
253
- formContext,
254
- props.fieldConfig,
255
- [...selectedValues, ...listOptions],
256
- props.onChange,
257
- )}
258
- </ListboxButton>
259
- <RenderListOptions
260
- formContext={formContext}
261
- onChange={props.onChange}
262
- formField={FormFieldType.TYPEAHEAD_2}
263
- ref={dynamicSelectRef}
264
- fieldConfig={props.fieldConfig}
265
- listOptions={listOptions}
266
- setListOptions={setListOptions}
267
- loading={loading}
268
- setLoading={setLoading}
269
- createCallback={(data) => updateListOptions(data)}
270
- queryCallback={(query) => fetchData(query)}
271
- />
272
- </Listbox>
273
- );
274
- };
275
- if (props.fieldConfig.hideWhenNoResults && listOptions.length == 0) {
276
- return <></>;
277
- }
278
-
279
- return (
280
- <RenderFormField fieldConfig={props.fieldConfig} getInput={getInput} />
281
- );
282
- };
283
- export default Typeahead2;