@engagebay/engagebay-form-module 1.0.6 → 1.0.7-beta.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.6",
3
+ "version": "1.0.7-beta.2",
4
4
  "description": "Provide base form components to reacho",
5
5
  "scripts": {
6
6
  "test": "echo \"Error: no test specified\" && exit 1"
@@ -16,7 +16,6 @@
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",
20
19
  "@types/react-redux": ">=7.1.33",
21
20
  "axios": ">=1.7.2",
22
21
  "clsx": ">=2.1.1",
@@ -32,7 +31,6 @@
32
31
  "@heroicons/react": ">=2.1.5",
33
32
  "@reduxjs/toolkit": ">=2.2.7",
34
33
  "@tippyjs/react": ">=4.2.6",
35
- "@types/lodash": ">=4.17.7",
36
34
  "@types/react-redux": ">=7.1.33",
37
35
  "axios": ">=1.7.2",
38
36
  "clsx": ">=2.1.1",
package/src/api/index.ts CHANGED
@@ -1,10 +1,16 @@
1
1
  import axios, {AxiosInstance, AxiosRequestConfig} from "axios";
2
2
  import {FormFieldSchema} from "../form/schema/FormFieldSchema";
3
3
 
4
+ let baseURL;
5
+ try {
6
+ baseURL = (window as any).DEFAULT_HOST ||
7
+ (window as any).parent.DEFAULT_HOST
8
+ } catch (error) {
9
+
10
+ }
11
+
4
12
  const BASE_API: AxiosRequestConfig = {
5
- baseURL:
6
- (window as any).REACHO_BASE_URL ||
7
- (window as any).parent.REACHO_BASE_URL,
13
+ baseURL: baseURL ?? "",
8
14
  timeout: 30000,
9
15
  headers: {
10
16
  "Content-Type": "application/json",
@@ -28,13 +28,13 @@ import TimeField from "./formfields/TimeField";
28
28
  import Typeahead from "./formfields/Typeahead";
29
29
  import TypeaheadMultiSelect from "./formfields/TypeaheadMultiSelect";
30
30
  import UrlField from "./formfields/UrlField";
31
- import Typeahead2 from "./formfields/Typeahead2";
32
31
  import {
33
32
  FieldOptionsSchema,
34
33
  FormFieldComponentPropSchema,
35
34
  FormFieldType,
36
35
  OptionMappingConfig,
37
36
  } from "./schema/FormFieldSchema";
37
+ import Typeahead2 from "./formfields/Typeahead2";
38
38
 
39
39
  /**
40
40
  * @property {React.FC<FormFieldComponentPropSchema>} component - React component for a form field.
@@ -137,12 +137,12 @@ const formFieldComponents: FormComponentSchema = {
137
137
  [FormFieldType[FormFieldType.TYPEAHEAD]]: {
138
138
  component: Typeahead,
139
139
  },
140
- [FormFieldType[FormFieldType.TYPEAHEAD_2]]: {
141
- component: Typeahead2,
142
- },
143
140
  [FormFieldType[FormFieldType.TYPEAHEAD_MULTI_SELECT]]: {
144
141
  component: TypeaheadMultiSelect,
145
142
  },
143
+ [FormFieldType[FormFieldType.TYPEAHEAD_2]]: {
144
+ component: Typeahead2,
145
+ },
146
146
  [FormFieldType[FormFieldType.COMBO_SELECT]]: {
147
147
  component: ComboSelect,
148
148
  },
@@ -21,7 +21,6 @@ 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";
25
24
 
26
25
  const defaultBusinessHours = {
27
26
  MONDAY: {
@@ -124,9 +123,8 @@ export const BusinessHoursField: React.FC<FormFieldComponentPropSchema> = (
124
123
  <div className="w-full sm:w-full text-end mr-[2.3em]">
125
124
  <button
126
125
  type="button"
127
- className={`text-end text-primary cursor-pointer font-[13px] font-medium ${
128
- getValues(`${mappedName}.sessions`)?.length > 1 ? "mr-9" : ""
129
- }`}
126
+ className={`text-end text-primary cursor-pointer font-[13px] font-medium ${getValues(`${mappedName}.sessions`)?.length > 1 ? "mr-9" : ""
127
+ }`}
130
128
  onClick={() => {
131
129
  const lastEndTime =
132
130
  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,13 +25,13 @@ 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
-
34
+ //registerOptions.valueAsDate = true;
35
35
  let hookProps = formContext.register(props.fieldConfig.name, registerOptions);
36
36
 
37
37
  function getInput() {
@@ -28,7 +28,7 @@ const NumberField: React.FC<FormFieldComponentPropSchema> = (
28
28
  step={props.fieldConfig.decimalAllowed ? 0.01 : 1}
29
29
  defaultValue={props.fieldConfig.defaultValue as string}
30
30
  className={`form-input ${
31
- props.fieldConfig.customClassNames?.fieldClassName || "flex-1 !w-60"
31
+ props.fieldConfig.customClassNames?.fieldClassName || "flex-1"
32
32
  }`}
33
33
  onKeyDown={(e) => {
34
34
  props.fieldConfig.onKeyDown && props.fieldConfig.onKeyDown(e);
@@ -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,199 +12,185 @@ 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(
33
- props.fieldConfig.name,
34
- registerOptions
35
- );
36
- const [listOptions, setListOptions] = useState<FieldOptionsSchema[]>([]);
37
- const [selectedValues, setSelectedValues] = useState<FieldOptionsSchema[]>(
38
- []
39
- );
40
- const [loading, setLoading] = useState<boolean>(true);
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
- fetchData(undefined);
53
- }, []);
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);
54
38
 
55
- const fetchData = useCallback(
56
- async (_query: string | undefined) => {
57
- setLoading(true);
58
- try {
59
- if (!props.fieldConfig.fetchUrl) return;
39
+ useEffect(() => {
40
+ if (
41
+ !formContext.getValues(props.fieldConfig.name) &&
42
+ props.fieldConfig.defaultValue
43
+ ) {
44
+ formContext.setValue(
45
+ props.fieldConfig.name,
46
+ props.fieldConfig.defaultValue,
47
+ );
48
+ }
49
+ fetchData(undefined);
50
+ }, []);
60
51
 
61
- let url = props.fieldConfig.fetchUrl;
62
- if (_query) {
63
- url = url.includes("?")
64
- ? url + "&q=" + _query
65
- : url + "?q=" + _query;
66
- }
52
+ const fetchData = useCallback(
53
+ async (_query: string | undefined) => {
54
+ setLoading(true);
55
+ try {
56
+ if (!props.fieldConfig.fetchUrl) return;
67
57
 
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
- );
58
+ let url = props.fieldConfig.fetchUrl;
59
+ if (_query) {
60
+ url = url.includes("?") ? url + "&q=" + _query : url + "?q=" + _query;
61
+ }
98
62
 
99
- const fetchValue = async (value: string) => {
100
- try {
101
- if (
102
- props.fieldConfig.ignoreFetchValue ||
103
- !props.fieldConfig.fetchUrl
104
- ) {
105
- return;
106
- }
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
+ );
107
90
 
108
- let url = props.fieldConfig.fetchUrl;
91
+ const fetchValue = async (value: string) => {
92
+ try {
93
+ if (props.fieldConfig.ignoreFetchValue || !props.fieldConfig.fetchUrl) {
94
+ return;
95
+ }
109
96
 
110
- if (value)
111
- url = url.includes("?")
112
- ? url + "&values=" + value
113
- : url + "?values=" + value;
97
+ let url = props.fieldConfig.fetchUrl;
114
98
 
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
- };
99
+ if (value)
100
+ url = url.includes("?")
101
+ ? url + "&values=" + value
102
+ : url + "?values=" + value;
129
103
 
130
- const updateListOptions = (data: any) => {
131
- const resData: FieldOptionsSchema = getListOption(
132
- data,
133
- props.fieldConfig.optionsConfig
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,
134
111
  );
135
- setSelectedValues((perv) => [resData]);
136
- formContext.setValue(props.fieldConfig.name, resData.value);
137
- };
112
+ setSelectedValues([...data]);
113
+ }
114
+ } catch (err) {}
115
+ };
138
116
 
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
- );
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
+ };
157
125
 
158
- // If the value matches, set it to null, otherwise set it to val
159
- const newValue = currentValue === val ? null : val;
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);
160
141
 
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
- }
142
+ // If the value matches, set it to null, otherwise set it to val
143
+ const newValue = currentValue === val ? null : val;
205
144
 
206
- return (
207
- <RenderFormField fieldConfig={props.fieldConfig} getInput={getInput} />
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>
208
186
  );
187
+ }
188
+ if (props.fieldConfig.hideWhenNoResults && listOptions.length == 0) {
189
+ return <></>;
190
+ }
191
+
192
+ return (
193
+ <RenderFormField fieldConfig={props.fieldConfig} getInput={getInput} />
194
+ );
209
195
  };
210
196
  export default Typeahead;
@@ -23,9 +23,10 @@ import RenderListOptions, {
23
23
  } from "../util/RenderListOptions";
24
24
  // import _ from "lodash";
25
25
  import axios from "axios";
26
+ import { getAxiosInstance } from "../../api";
26
27
 
27
28
  const TypeaheadMultiSelect: React.FC<FormFieldComponentPropSchema> = (
28
- props: FormFieldComponentPropSchema
29
+ props: FormFieldComponentPropSchema,
29
30
  ) => {
30
31
  const dynamicSelectRef = useRef<HTMLUListElement>(null);
31
32
  const formContext = useContext(FormContext);
@@ -33,7 +34,7 @@ const TypeaheadMultiSelect: React.FC<FormFieldComponentPropSchema> = (
33
34
  let hookProps = formContext.register(props.fieldConfig.name, registerOptions);
34
35
  const [listOptions, setListOptions] = useState<FieldOptionsSchema[]>([]);
35
36
  const [selectedValues, setSelectedValues] = useState<FieldOptionsSchema[]>(
36
- []
37
+ [],
37
38
  );
38
39
  const [loading, setLoading] = useState<boolean>(true);
39
40
 
@@ -44,7 +45,7 @@ const TypeaheadMultiSelect: React.FC<FormFieldComponentPropSchema> = (
44
45
  ) {
45
46
  formContext.setValue(
46
47
  props.fieldConfig.name,
47
- props.fieldConfig.defaultValue
48
+ props.fieldConfig.defaultValue,
48
49
  );
49
50
  }
50
51
  fetchData(undefined);
@@ -60,14 +61,16 @@ const TypeaheadMultiSelect: React.FC<FormFieldComponentPropSchema> = (
60
61
  if (_query) {
61
62
  url = url.includes("?") ? url + "&q=" + _query : url + "?q=" + _query;
62
63
  }
64
+ const axiosInstance = getAxiosInstance(
65
+ formContext.axiosInstance,
66
+ props.fieldConfig,
67
+ );
63
68
 
64
- let response = await (props.fieldConfig.disableHeaderInFetch
65
- ? axios.get(url)
66
- : formContext.axiosInstance?.get(url));
69
+ let response = await axiosInstance.get(url);
67
70
  if (response?.data) {
68
71
  const data: FieldOptionsSchema[] = getListOptions(
69
72
  response?.data,
70
- props.fieldConfig.optionsConfig
73
+ props.fieldConfig.optionsConfig,
71
74
  );
72
75
  setListOptions([...data]);
73
76
  let values = formContext.getValues(props.fieldConfig.name) || [];
@@ -77,7 +80,7 @@ const TypeaheadMultiSelect: React.FC<FormFieldComponentPropSchema> = (
77
80
  (data.length === 0 || // If 'data' is empty
78
81
  (!values.every((v: string) => data.some((i) => i.value === v)) && // Ensure none of 'values' match 'data'
79
82
  !values.every((v: string) =>
80
- selectedValues.some((i) => i.value === v)
83
+ selectedValues.some((i) => i.value === v),
81
84
  ))) // Ensure none of 'values' match 'selectedValues'
82
85
  ) {
83
86
  fetchValue(values); // Call 'fetchValue()' if all conditions are met
@@ -94,7 +97,7 @@ const TypeaheadMultiSelect: React.FC<FormFieldComponentPropSchema> = (
94
97
  setLoading(false);
95
98
  }
96
99
  },
97
- [props.fieldConfig.fetchUrl]
100
+ [props.fieldConfig.fetchUrl],
98
101
  );
99
102
 
100
103
  const fetchValue = async (value: string) => {
@@ -105,7 +108,7 @@ const TypeaheadMultiSelect: React.FC<FormFieldComponentPropSchema> = (
105
108
 
106
109
  let url = props.fieldConfig.fetchUrl;
107
110
 
108
- url = url = url.includes("?")
111
+ url = url.includes("?")
109
112
  ? url + "&values=" + value
110
113
  : url + "?values=" + value;
111
114
 
@@ -115,7 +118,7 @@ const TypeaheadMultiSelect: React.FC<FormFieldComponentPropSchema> = (
115
118
  if (response?.data) {
116
119
  const data: FieldOptionsSchema[] = getListOptions(
117
120
  response?.data,
118
- props.fieldConfig.optionsConfig
121
+ props.fieldConfig.optionsConfig,
119
122
  );
120
123
  let values: any[] = formContext.getValues(props.fieldConfig.name) || [];
121
124
  setSelectedValues(
@@ -123,22 +126,22 @@ const TypeaheadMultiSelect: React.FC<FormFieldComponentPropSchema> = (
123
126
  ...data,
124
127
  props.fieldConfig.dropdownFieldConfig?.isSuggestionBox && values
125
128
  ? values
126
- .filter(
127
- (value) =>
128
- data.some((d) => d.value !== value) || data.length == 0
129
- )
130
- .map((val) => ({ label: val, value: val }))
129
+ .filter(
130
+ (value) =>
131
+ data.some((d) => d.value !== value) || data.length == 0,
132
+ )
133
+ .map((val) => ({ label: val, value: val }))
131
134
  : [],
132
- ].flat()
135
+ ].flat(),
133
136
  );
134
137
  }
135
- } catch (err) {}
138
+ } catch (err) { }
136
139
  };
137
140
 
138
141
  const updateListOptions = (data: any) => {
139
142
  const resData: FieldOptionsSchema = getListOption(
140
143
  data,
141
- props.fieldConfig.optionsConfig
144
+ props.fieldConfig.optionsConfig,
142
145
  );
143
146
  setSelectedValues((prev) => [...prev, resData]);
144
147
  let result = formContext.getValues(props.fieldConfig.name) || [];
@@ -160,14 +163,14 @@ const TypeaheadMultiSelect: React.FC<FormFieldComponentPropSchema> = (
160
163
  className={"relative form-listbox flex-1 overflow-hidden"}
161
164
  onChange={(selectedOptions) => {
162
165
  const chossenOptions = listOptions.filter((op) =>
163
- selectedOptions.includes(op.value)
166
+ selectedOptions.includes(op.value),
164
167
  );
165
168
  setSelectedValues((prev) => [...prev, ...chossenOptions]);
166
169
  handleChange(
167
170
  selectedOptions,
168
171
  formContext,
169
172
  props.fieldConfig,
170
- props.onChange
173
+ props.onChange,
171
174
  );
172
175
  }}
173
176
  multiple
@@ -176,7 +179,7 @@ const TypeaheadMultiSelect: React.FC<FormFieldComponentPropSchema> = (
176
179
  className={
177
180
  props.fieldConfig.customClassNames?.fieldClassName
178
181
  ? "form-listbox-select " +
179
- props.fieldConfig.customClassNames?.fieldClassName
182
+ props.fieldConfig.customClassNames?.fieldClassName
180
183
  : "form-listbox-select"
181
184
  }
182
185
  >
@@ -184,7 +187,7 @@ const TypeaheadMultiSelect: React.FC<FormFieldComponentPropSchema> = (
184
187
  formContext,
185
188
  props.fieldConfig,
186
189
  [...selectedValues, ...listOptions],
187
- props.onChange
190
+ props.onChange,
188
191
  )}
189
192
  </ListboxButton>
190
193
  <RenderListOptions
@@ -1,7 +1,7 @@
1
1
  import React, { useContext } from "react";
2
2
  import { RegisterOptions } from "react-hook-form";
3
3
  import { FormContext } from "../context/FormContext";
4
- import { FormFieldComponentPropSchema } from "../schema/FormFieldSchema";
4
+ import { FormFieldComponentPropSchema, FormFieldPatternsImpl } from "../schema/FormFieldSchema";
5
5
  import { Input } from "@headlessui/react";
6
6
  import RenderFormField from "../util/RenderFormField";
7
7
  import { handleChange, registerFormField } from "../util";
@@ -11,7 +11,12 @@ const UrlField: React.FC<FormFieldComponentPropSchema> = (
11
11
  ) => {
12
12
  const formContext = useContext(FormContext);
13
13
 
14
- let registerOptions: RegisterOptions = registerFormField(props.fieldConfig);
14
+ // Apply URL pattern by default unless the consumer has already set a formFieldPattern
15
+ const fieldConfigWithUrlPattern = props.fieldConfig.formFieldPattern
16
+ ? props.fieldConfig
17
+ : { ...props.fieldConfig, formFieldPattern: [FormFieldPatternsImpl.URL] };
18
+
19
+ let registerOptions: RegisterOptions = registerFormField(fieldConfigWithUrlPattern);
15
20
 
16
21
  let hookProps = formContext.register(props.fieldConfig.name, registerOptions);
17
22
 
@@ -47,7 +52,7 @@ const UrlField: React.FC<FormFieldComponentPropSchema> = (
47
52
  };
48
53
 
49
54
  return (
50
- <RenderFormField fieldConfig={props.fieldConfig} getInput={getInput} />
55
+ <RenderFormField fieldConfig={fieldConfigWithUrlPattern} getInput={getInput} />
51
56
  );
52
57
  };
53
58
  export default UrlField;
@@ -106,7 +106,6 @@ export type FormFieldSchema = {
106
106
  max?: number;
107
107
  min?: number;
108
108
  rows?: number;
109
- allowedMinQueryLength?: number;
110
109
  defaultValue?: string | string[] | {} | boolean;
111
110
  options?: FieldOptionsSchema[];
112
111
  minDate?: Date | null | undefined;
@@ -129,14 +128,15 @@ export type FormFieldSchema = {
129
128
  decimalAllowed?: boolean;
130
129
  errorMessage?: string;
131
130
  submitOnChange?: boolean;
132
- isMultiple?: boolean;
133
131
  formFieldPattern?: FormFieldPatternsImpl[];
134
132
  fetchUrl?: string;
135
- postUrl?: string;
136
133
  fetchSavedDataUrl?: string;
134
+ postUrl?: string;
137
135
  fileAccept?: string;
138
136
  icon?: ReactNode;
139
137
  outputFormat?: OutputFormatType;
138
+ isMultiple?: boolean;
139
+ allowedMinQueryLength?: number;
140
140
  children?: FormFieldSchema[];
141
141
  defaultOptions?: FieldOptionsSchema[];
142
142
  optionsConfig?: OptionMappingConfig;
@@ -205,6 +205,7 @@ export type FieldOptionsSchema = {
205
205
  isDisabled?: boolean;
206
206
  helpText?: string;
207
207
  groupName?: string;
208
+ tooltip?: string;
208
209
  icon?: React.ReactNode;
209
210
  };
210
211
 
@@ -11,13 +11,13 @@ import { handleChange } from ".";
11
11
  import { LoaderWithText } from "../../util/LoaderWithText";
12
12
  import SVGIcon from "../../util/svg/SVGIcon";
13
13
  import { FormContextType } from "../context/FormContext";
14
- import Tippy from "@tippyjs/react";
15
14
  import {
16
15
  FieldOptionsSchema,
17
16
  FormFieldSchema,
18
17
  FormFieldType,
19
18
  OutputFormatType,
20
19
  } from "../schema/FormFieldSchema";
20
+ import Tippy from "@tippyjs/react";
21
21
 
22
22
  type RenderListOptionsProps = {
23
23
  formContext: FormContextType;
@@ -127,7 +127,7 @@ const RenderListOptions = forwardRef<HTMLUListElement, RenderListOptionsProps>(
127
127
  }, {});
128
128
 
129
129
  const handleQueryCallback = useCallback(() => {
130
- if (filteredList.length == 0 && isTypeahead) {
130
+ if (filteredList.length < 5 && isTypeahead) {
131
131
  queryCallback && queryCallback(query);
132
132
  }
133
133
  }, [filteredList]);
@@ -189,7 +189,21 @@ const RenderListOptions = forwardRef<HTMLUListElement, RenderListOptionsProps>(
189
189
  {option.icon && (
190
190
  <span className="listbox-svg">{option.icon}</span>
191
191
  )}
192
- {option.label}
192
+ {option.tooltip ? (
193
+ <Tippy
194
+ content={
195
+ <>
196
+ {option.label}
197
+ <br />
198
+ {option.helpText}
199
+ </>
200
+ }
201
+ >
202
+ <div className="truncate">{option.label}</div>
203
+ </Tippy>
204
+ ) : (
205
+ option.label
206
+ )}
193
207
  </span>
194
208
  {isTypeahead &&
195
209
  !fieldConfig.dropdownFieldConfig?.isSuggestionBox ? (
@@ -208,11 +222,30 @@ const RenderListOptions = forwardRef<HTMLUListElement, RenderListOptionsProps>(
208
222
  )
209
223
  )}
210
224
  </div>
211
- {option.helpText && (
212
- <div className="mt-0 text-xs text-gray-500 font-normal truncate w-full !max-w-[150px]">
213
- {option.helpText}
214
- </div>
215
- )}
225
+ {option.helpText &&
226
+ (option.tooltip ? (
227
+ <Tippy
228
+ content={
229
+ <>
230
+ {option.label}
231
+ <br />
232
+ {option.helpText}
233
+ </>
234
+ }
235
+ >
236
+ <div
237
+ className={`mt-0 text-xs text-gray-500 font-normal truncate w-full ${fieldConfig.customClassNames?.optionClassName}`}
238
+ >
239
+ {option.helpText}
240
+ </div>
241
+ </Tippy>
242
+ ) : (
243
+ <div
244
+ className={`mt-0 text-xs text-gray-500 font-normal truncate w-full ${fieldConfig.customClassNames?.optionClassName}`}
245
+ >
246
+ {option.helpText}
247
+ </div>
248
+ ))}
216
249
  </>
217
250
  )}
218
251
  </ListboxOption>
@@ -291,7 +324,7 @@ const RenderListOptions = forwardRef<HTMLUListElement, RenderListOptionsProps>(
291
324
  fill="currentColor"
292
325
  aria-hidden="true"
293
326
  data-slot="icon"
294
- className="h-5 w-5 text-gray-400"
327
+ className="h-4.5 w-4.5 text-gray-400"
295
328
  >
296
329
  <path
297
330
  fillRule="evenodd"
@@ -425,9 +458,10 @@ export function renderListBoxValue(
425
458
  )
426
459
  );
427
460
  };
428
- let outputFormat = fieldConfig.outputFormat
429
- ? fieldConfig.outputFormat === OutputFormatType.ARRAY
430
- : false;
461
+ let outputFormat =
462
+ fieldConfig.outputFormat != undefined
463
+ ? fieldConfig.outputFormat === OutputFormatType.STRING
464
+ : false;
431
465
  const getPlaceholder = () => (
432
466
  <span className="form-placeholder">
433
467
  {fieldConfig.placeholder || "Select any option"}