@engagebay/engagebay-form-module 1.0.0-beta.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/README.md +126 -0
  2. package/link.sh +2 -0
  3. package/package.json +30 -0
  4. package/src/api/index.ts +25 -0
  5. package/src/form/Form.tsx +157 -0
  6. package/src/form/FormField.tsx +80 -0
  7. package/src/form/FormFieldUtils.ts +241 -0
  8. package/src/form/FormFields.tsx +41 -0
  9. package/src/form/context/FormContext.tsx +66 -0
  10. package/src/form/formfields/ArrayField.tsx +169 -0
  11. package/src/form/formfields/BusinessHoursField.tsx +204 -0
  12. package/src/form/formfields/CheckboxButtonsField.tsx +97 -0
  13. package/src/form/formfields/CheckboxField.tsx +118 -0
  14. package/src/form/formfields/ColorPickerField.tsx +59 -0
  15. package/src/form/formfields/ComboMultiSelect.tsx +290 -0
  16. package/src/form/formfields/ComboSelect.tsx +278 -0
  17. package/src/form/formfields/DatePickerField.tsx +89 -0
  18. package/src/form/formfields/DateRangePickerField.tsx +104 -0
  19. package/src/form/formfields/DynamicMultiSelect.tsx +189 -0
  20. package/src/form/formfields/DynamicSelect.tsx +187 -0
  21. package/src/form/formfields/Error.tsx +15 -0
  22. package/src/form/formfields/ErrorContextHandler.tsx +77 -0
  23. package/src/form/formfields/FileUploadField.tsx +196 -0
  24. package/src/form/formfields/IframeField.tsx +65 -0
  25. package/src/form/formfields/InputField.tsx +67 -0
  26. package/src/form/formfields/InputGroupField.tsx +44 -0
  27. package/src/form/formfields/MultipleSelectField.tsx +98 -0
  28. package/src/form/formfields/NumberField.tsx +61 -0
  29. package/src/form/formfields/PasswordField.tsx +93 -0
  30. package/src/form/formfields/PhoneNumberField.tsx +163 -0
  31. package/src/form/formfields/RadioField.tsx +104 -0
  32. package/src/form/formfields/RadioGroupComponent.tsx +94 -0
  33. package/src/form/formfields/RangeField.tsx +53 -0
  34. package/src/form/formfields/SelectField.tsx +82 -0
  35. package/src/form/formfields/SwitchField.tsx +131 -0
  36. package/src/form/formfields/TextAreaField.tsx +48 -0
  37. package/src/form/formfields/TimeField.tsx +53 -0
  38. package/src/form/formfields/Typeahead.tsx +211 -0
  39. package/src/form/formfields/TypeaheadMultiSelect.tsx +203 -0
  40. package/src/form/formfields/UrlField.tsx +53 -0
  41. package/src/form/hooks/useDynamicReducer.tsx +42 -0
  42. package/src/form/schema/CustomValidators.ts +63 -0
  43. package/src/form/schema/FormFieldSchema.ts +342 -0
  44. package/src/form/util/RenderFormField.tsx +149 -0
  45. package/src/form/util/RenderListOptions.tsx +424 -0
  46. package/src/form/util/index.ts +185 -0
  47. package/src/util/LoaderWithText.tsx +28 -0
  48. package/src/util/svg/HELPER_ICONS.ts +16 -0
  49. package/src/util/svg/SVGIcon.tsx +23 -0
  50. package/tsconfig.json +25 -0
@@ -0,0 +1,98 @@
1
+ import React, {
2
+ Fragment,
3
+ useContext,
4
+ useEffect,
5
+ useRef,
6
+ useState,
7
+ } from "react";
8
+
9
+ import { RegisterOptions } from "react-hook-form";
10
+ import { Listbox, ListboxButton, Transition } from "@headlessui/react";
11
+
12
+ import {
13
+ FieldOptionsSchema,
14
+ FormFieldComponentPropSchema,
15
+ FormFieldType,
16
+ } from "../schema/FormFieldSchema";
17
+ import { FormContext } from "../context/FormContext";
18
+ import RenderFormField from "../util/RenderFormField";
19
+ import RenderListOptions, {
20
+ renderListBoxValue,
21
+ } from "../util/RenderListOptions";
22
+ import { handleChange, registerFormField } from "../util";
23
+
24
+ const MultipleSelectField: React.FC<FormFieldComponentPropSchema> = ({
25
+ fieldConfig,
26
+ onChange,
27
+ }: FormFieldComponentPropSchema) => {
28
+ const multiSelectRef = useRef<HTMLUListElement>(null);
29
+ const formContext = useContext(FormContext);
30
+ let registerOptions: RegisterOptions = registerFormField(fieldConfig, true);
31
+ let hookProps = formContext.register(fieldConfig.name, registerOptions);
32
+
33
+ const [listOptions, setListOptions] = useState<FieldOptionsSchema[]>(
34
+ fieldConfig.options ? fieldConfig.options : []
35
+ );
36
+
37
+ const validSelectedValues = (formContext.getValues(fieldConfig.name) ||[])
38
+ .filter((selectedValue:any) =>
39
+ fieldConfig.options && fieldConfig.options.some(option => option.value === selectedValue)
40
+ );
41
+
42
+ useEffect(() => {
43
+ if (
44
+ !formContext.getValues(fieldConfig.name) &&
45
+ fieldConfig.defaultValue
46
+ )
47
+ formContext.setValue(fieldConfig.name, fieldConfig.defaultValue);
48
+
49
+ if (fieldConfig.options && fieldConfig.options.length > 0) {
50
+ setListOptions(fieldConfig.options);
51
+ return;
52
+ }
53
+ }, [fieldConfig.options]);
54
+
55
+ function getInput() {
56
+ return (
57
+ <Listbox
58
+ as={"div"}
59
+ {...hookProps}
60
+ value={validSelectedValues}
61
+ defaultValue={fieldConfig.defaultValue}
62
+ onChange={(val) =>
63
+ handleChange(val, formContext, fieldConfig, onChange)
64
+ }
65
+ disabled={fieldConfig.disabled}
66
+ multiple
67
+ className={"relative form-listbox flex-1"}>
68
+ <ListboxButton
69
+ className={
70
+ fieldConfig.customClassNames?.fieldClassName
71
+ ? "form-listbox-select " +
72
+ fieldConfig.customClassNames?.fieldClassName
73
+ : "form-listbox-select"
74
+ }>
75
+ {renderListBoxValue(
76
+ formContext,
77
+ fieldConfig,
78
+ listOptions,
79
+ onChange
80
+ )
81
+ }
82
+ </ListboxButton>
83
+ <RenderListOptions
84
+ formContext={formContext}
85
+ onChange={onChange}
86
+ formField={FormFieldType.MULTI_SELECT}
87
+ ref={multiSelectRef}
88
+ fieldConfig={fieldConfig}
89
+ listOptions={listOptions}
90
+ setListOptions={setListOptions}
91
+ />
92
+ </Listbox>
93
+ );
94
+ }
95
+
96
+ return <RenderFormField fieldConfig={fieldConfig} getInput={getInput} />;
97
+ };
98
+ export default MultipleSelectField;
@@ -0,0 +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";
6
+ import RenderFormField from "../util/RenderFormField";
7
+
8
+ const NumberField: React.FC<FormFieldComponentPropSchema> = (
9
+ props: FormFieldComponentPropSchema
10
+ ) => {
11
+ const formContext = useContext(FormContext);
12
+
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
+ }
56
+
57
+ return (
58
+ <RenderFormField fieldConfig={props.fieldConfig} getInput={getInput}/>
59
+ );
60
+ };
61
+ export default NumberField;
@@ -0,0 +1,93 @@
1
+ import React, { useContext, useState } from "react";
2
+ import { RegisterOptions } from "react-hook-form";
3
+ import { FormContext } from "../context/FormContext";
4
+ import { FormFieldComponentPropSchema } from "../schema/FormFieldSchema";
5
+ import RenderFormField from "../util/RenderFormField";
6
+ import { handleChange, registerFormField } from "../util";
7
+ import Tippy from '@tippyjs/react';
8
+
9
+ const PasswordField: React.FC<FormFieldComponentPropSchema> = (
10
+ props: FormFieldComponentPropSchema
11
+ ) => {
12
+ const formContext = useContext(FormContext);
13
+
14
+ let registerOptions: RegisterOptions = registerFormField(props.fieldConfig);
15
+
16
+ let hookProps = formContext.register(props.fieldConfig.name, registerOptions);
17
+
18
+ const [isPasswordVisible, setIsPasswordVisible] = useState<boolean>(false);
19
+
20
+ function getInput() {
21
+ return (
22
+ <div className="relative">
23
+ <input
24
+ type={`${isPasswordVisible ? "text" : "password"}`}
25
+ {...hookProps}
26
+ placeholder={props.fieldConfig?.placeholder}
27
+ readOnly={props.fieldConfig?.readOnly}
28
+ disabled={props.fieldConfig?.disabled}
29
+ autoComplete={props.fieldConfig?.autoComplete}
30
+ defaultValue={props.fieldConfig.defaultValue as string}
31
+ className={`form-input ${props.fieldConfig.customClassNames?.fieldClassName || "flex-1"}`}
32
+ onKeyDown={(e) => {
33
+ props.fieldConfig.onKeyDown && props.fieldConfig.onKeyDown(e);
34
+ }}
35
+ onChange={(e) => {
36
+ handleChange(
37
+ e.target.value,
38
+ formContext,
39
+ props.fieldConfig,
40
+ props.onChange
41
+ );
42
+ }}
43
+ />
44
+ <div
45
+ className="absolute inset-y-0 right-0 flex items-center pr-3 cursor-pointer"
46
+ onClick={() => setIsPasswordVisible(!isPasswordVisible)}
47
+ >
48
+ <div
49
+ className="absolute inset-y-0 right-0 flex items-center pr-3 cursor-pointer"
50
+ onClick={() => setIsPasswordVisible(!isPasswordVisible)}
51
+ >
52
+ {isPasswordVisible ? (
53
+ <Tippy
54
+ content={
55
+ <>
56
+ <h4 className="text-sm capitalize text-center truncate">Hide Password</h4>
57
+ </>
58
+ }
59
+ >
60
+ <span className="mark-as-read-btn">
61
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="#121212a1" className="bi bi-eye-slash-fill" viewBox="0 0 16 16">
62
+ <path d="m10.79 12.912-1.614-1.615a3.5 3.5 0 0 1-4.474-4.474l-2.06-2.06C.938 6.278 0 8 0 8s3 5.5 8 5.5a7 7 0 0 0 2.79-.588M5.21 3.088A7 7 0 0 1 8 2.5c5 0 8 5.5 8 5.5s-.939 1.721-2.641 3.238l-2.062-2.062a3.5 3.5 0 0 0-4.474-4.474z" />
63
+ <path d="M5.525 7.646a2.5 2.5 0 0 0 2.829 2.829zm4.95.708-2.829-2.83a2.5 2.5 0 0 1 2.829 2.829zm3.171 6-12-12 .708-.708 12 12z" />
64
+ </svg>
65
+ </span>
66
+ </Tippy>
67
+ ) : (
68
+ <Tippy
69
+ content={
70
+ <>
71
+ <h4 className="text-sm capitalize text-center truncate">Show Password</h4>
72
+ </>
73
+ }
74
+ >
75
+ <span className="mark-as-read-btn">
76
+ <svg xmlns="http://www.w3.org/2000/svg" width="16" height="16" fill="#121212a1" className="bi bi-eye-fill" viewBox="0 0 16 16">
77
+ <path d="M10.5 8a2.5 2.5 0 1 1-5 0 2.5 2.5 0 0 1 5 0" />
78
+ <path d="M0 8s3-5.5 8-5.5S16 8 16 8s-3 5.5-8 5.5S0 8 0 8m8 3.5a3.5 3.5 0 1 0 0-7 3.5 3.5 0 0 0 0 7" />
79
+ </svg>
80
+ </span>
81
+ </Tippy>
82
+ )}
83
+ </div>
84
+ </div>
85
+ </div>
86
+ );
87
+ }
88
+
89
+ return (
90
+ <RenderFormField fieldConfig={props.fieldConfig} getInput={getInput} />
91
+ );
92
+ };
93
+ export default PasswordField;
@@ -0,0 +1,163 @@
1
+ import React, { useContext, useCallback, useState } from "react";
2
+ import { RegisterOptions } from "react-hook-form";
3
+ import 'react-phone-number-input/style.css';
4
+ import PhoneInput, { isValidPhoneNumber, Country } from 'react-phone-number-input';
5
+ import { Input, InputProps, Popover, PopoverButton, PopoverPanel } from "@headlessui/react";
6
+
7
+ import flags from "react-phone-number-input/flags";
8
+ import * as RPNInput from "react-phone-number-input";
9
+ import { FormContext } from "../context/FormContext";
10
+ import { FormFieldComponentPropSchema, FormFieldType } from "../schema/FormFieldSchema";
11
+ import RenderFormField from "../util/RenderFormField";
12
+ import { handleChange, registerFormField } from "../util";
13
+ import { CheckIcon, ChevronUpDownIcon } from "@heroicons/react/24/outline";
14
+ import InputField from "./InputField";
15
+ import clsx from "clsx";
16
+ // Phone Number Field Component
17
+ const PhoneNumberField: React.FC<FormFieldComponentPropSchema> = ({
18
+ fieldConfig,
19
+ onChange
20
+ }: FormFieldComponentPropSchema) => {
21
+ const formContext = useContext(FormContext);
22
+ const registerOptions: RegisterOptions = {
23
+ ...registerFormField(fieldConfig),
24
+ validate: (value) => isValidPhoneNumber(value || '') || "Please enter a valid mobile number."
25
+ };
26
+
27
+ const hookprops = formContext.register(fieldConfig.name, registerOptions);
28
+
29
+ const getInput = () => (
30
+ <>
31
+ {/* Phone Input */}
32
+ <RPNInput.default
33
+ {...hookprops}
34
+ className={clsx("flex")}
35
+ flagComponent={FlagComponent}
36
+ countrySelectComponent={CountrySelect}
37
+ inputComponent={InputComponent}
38
+ onChange={(value: any) => {
39
+ if (!value) return;
40
+
41
+ handleChange(value, formContext, fieldConfig, onChange);
42
+ }}
43
+ defaultCountry={fieldConfig.defaultValue as Country}
44
+ international
45
+ value={formContext.getValues(fieldConfig.name)}
46
+ disabled={fieldConfig.disabled}
47
+ // limitMaxLength={true}
48
+ placeholder={fieldConfig.placeholder}
49
+ withCountryCallingCode
50
+ addInternationalOption={false}
51
+ readOnly={fieldConfig.readOnly}
52
+ />
53
+ </>
54
+ );
55
+
56
+ return <RenderFormField fieldConfig={fieldConfig} getInput={getInput} />;
57
+ };
58
+ export default PhoneNumberField;
59
+
60
+ // Country Select Component
61
+ const CountrySelect: React.FC<{
62
+ disabled: boolean;
63
+ value: Country;
64
+ onChange: (value: Country) => void;
65
+ options: { value: Country; label: string }[];
66
+ }> = ({ disabled, value, onChange, options }) => {
67
+ const [searchTerm, setSearchTerm] = useState<string>("");
68
+
69
+ const handleSelect = useCallback(
70
+ (country: Country) => {
71
+ onChange(country);
72
+ },
73
+ [onChange]
74
+ );
75
+
76
+ // Filter options based on the search term
77
+ const filteredOptions = options.filter((option) =>
78
+ option.label.toLowerCase().includes(searchTerm.toLowerCase())
79
+ );
80
+
81
+ return (
82
+ <Popover className={''}>
83
+ <PopoverButton
84
+ type="button"
85
+ className={`form-listbox-select rounded-e-none flex ${disabled ? 'opacity-50' : ''}`}
86
+ disabled={disabled}
87
+ >
88
+ <FlagComponent
89
+ country={value as Country}
90
+ countryName={value}
91
+ />
92
+ {/* <ChevronUpDownIcon className="h-5 w-5 text-gray-400" /> */}
93
+ </PopoverButton>
94
+ <PopoverPanel className="w-[300px] absolute z-50 p-0 bg-white shadow-lg rounded-md">
95
+ <div className="p-2">
96
+ <input
97
+ className="form-input pr-9"
98
+ placeholder="Search country..."
99
+ value={searchTerm}
100
+ onChange={(e) => setSearchTerm(e.target.value)}
101
+ />
102
+ </div>
103
+ <div className="phone-num-dropdown">
104
+ {filteredOptions.length > 0 ? (
105
+ filteredOptions.map((option) => (
106
+ <div
107
+ key={option.value}
108
+ className="flex items-center justify-between px-3 py-2 hover:bg-gray-100 cursor-pointer"
109
+ onClick={() => handleSelect(option.value)}
110
+ >
111
+ {/* Country flag */}
112
+ <div className="flex items-center">
113
+ <FlagComponent
114
+ country={option.value}
115
+ countryName={option.label}
116
+ />
117
+ <span className="ml-3">{option.label}</span>
118
+ </div>
119
+
120
+ {/* Country code and check icon */}
121
+ <div className="flex items-center space-x-3">
122
+ {option.value && (
123
+ <span className="text-foreground/50 text-sm">
124
+ {`+${RPNInput.getCountryCallingCode(option.value)}`}
125
+ </span>
126
+ )}
127
+ <CheckIcon
128
+ className={`h-4 w-4 ${option.value === value ? 'opacity-100' : 'opacity-0'}`}
129
+ />
130
+ </div>
131
+ </div>
132
+ ))
133
+ ) : (
134
+ <div className="px-3 py-2 text-gray-500 text-center">No country found</div>
135
+ )}
136
+ </div>
137
+ </PopoverPanel>
138
+ </Popover>
139
+ );
140
+ };
141
+
142
+ // Flag Component
143
+ const FlagComponent = ({ country, countryName }: RPNInput.FlagProps) => {
144
+ const Flag = flags[country];
145
+
146
+ return (
147
+ <span className="bg-foreground/20 flex h-5 w-6 overflow-hidden rounded-sm">
148
+ {Flag && <Flag title={countryName} />}
149
+ </span>
150
+ );
151
+ };
152
+
153
+ // Input Component for the phone input
154
+ const InputComponent = React.forwardRef<HTMLInputElement, InputProps>(
155
+ ({ className, ...props }, ref) => (
156
+ <Input
157
+ className={clsx("rounded-s-none form-input", className)}
158
+ {...props}
159
+ ref={ref}
160
+ />
161
+ ),
162
+ );
163
+ InputComponent.displayName = "InputComponent";
@@ -0,0 +1,104 @@
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 RenderFormField from "../util/RenderFormField";
6
+ import { handleChange, registerFormField } from "../util";
7
+ import { Input, Radio, RadioGroup } from "@headlessui/react";
8
+ import clsx from "clsx";
9
+
10
+ const RadioField: React.FC<FormFieldComponentPropSchema> = (
11
+ props: FormFieldComponentPropSchema
12
+ ) => {
13
+ const formContext = useContext(FormContext);
14
+
15
+ let registerOptions: RegisterOptions = registerFormField(props.fieldConfig);
16
+
17
+ let hookProps = formContext.register(
18
+ props.fieldConfig.name,
19
+ registerOptions
20
+ );
21
+
22
+ function getInput() {
23
+ return (
24
+ props.fieldConfig.options && (
25
+ <RadioGroup
26
+ {...hookProps}
27
+ value={formContext.getValues(props.fieldConfig.name) ?? props.fieldConfig.defaultValue}
28
+ className={
29
+ props.fieldConfig.customClassNames
30
+ ?.fieldClassName ||
31
+ "form-check-container"
32
+ }
33
+ onChange={(value) => {
34
+ handleChange(
35
+ value,
36
+ formContext,
37
+ props.fieldConfig,
38
+ props.onChange
39
+ );
40
+ }}>
41
+ {props.fieldConfig.options.map((option) => {
42
+ return (
43
+ <Radio
44
+ value={option.value}
45
+ key={option.value}
46
+ disabled={option.isDisabled}
47
+ className={
48
+ props.fieldConfig.customClassNames
49
+ ?.optionClassName ||
50
+ "form-check-container"
51
+ }
52
+ >
53
+ {({ checked }) => {
54
+ return props.fieldConfig
55
+ .fieldOptionWrapper ? (
56
+ <props.fieldConfig.fieldOptionWrapper
57
+ data={option}
58
+ selected={
59
+ checked
60
+ }></props.fieldConfig.fieldOptionWrapper>
61
+ ) : (
62
+ <>
63
+ <span
64
+ className={"form-check-radio flex items-center"}>
65
+ <span
66
+ className={clsx("form-radio ")}
67
+ >
68
+ {checked &&
69
+ <span className="checked"></span>
70
+ }
71
+ </span>
72
+ <label htmlFor={option.value} className="cursor-pointer">
73
+ {option.label}
74
+ {option.icon && (
75
+ <span
76
+ className={
77
+ "listbox-svg ml-2 cursor-pointer"
78
+ }>
79
+ {option.icon}
80
+ </span>
81
+ )}
82
+ </label>
83
+ </span>
84
+ {option.helpText && (
85
+ <p className="ms-6 text-tiny text-gray-500">
86
+ {option.helpText}
87
+ </p>
88
+ )}
89
+ </>
90
+ );
91
+ }}
92
+ </Radio>
93
+ );
94
+ })}
95
+ </RadioGroup>
96
+ )
97
+ );
98
+ }
99
+
100
+ return (
101
+ <RenderFormField fieldConfig={props.fieldConfig} getInput={getInput} />
102
+ );
103
+ };
104
+ export default RadioField;
@@ -0,0 +1,94 @@
1
+ import React, { useContext } from "react";
2
+ import { RegisterOptions } from "react-hook-form";
3
+ import { FormContext } from "../context/FormContext";
4
+ import { Label, Radio, RadioGroup } from "@headlessui/react";
5
+ import { FormFieldComponentPropSchema } from "../schema/FormFieldSchema";
6
+ import RenderFormField from "../util/RenderFormField";
7
+ import { handleChange, registerFormField } from "../util";
8
+
9
+ const RadioGroupComponent: React.FC<FormFieldComponentPropSchema> = (
10
+ props: FormFieldComponentPropSchema
11
+ ) => {
12
+ const formContext = useContext(FormContext);
13
+
14
+ let registerOptions: RegisterOptions = registerFormField(props.fieldConfig);
15
+
16
+ let hookProps = formContext.register(props.fieldConfig.name, registerOptions);
17
+
18
+ function getInput() {
19
+ return (
20
+ <>
21
+ <div className="w-full">
22
+ {/*<div className="mx-auto w-full max-w-md">*/}
23
+ {props.fieldConfig.options && (
24
+ <RadioGroup
25
+ {...hookProps}
26
+ onChange={(value) => {
27
+ handleChange(
28
+ value,
29
+ formContext,
30
+ props.fieldConfig,
31
+ props.onChange
32
+ );
33
+ }}
34
+ >
35
+ <Label className="sr-only">Server size</Label>
36
+ <div className="space-x-2 flex items-stretch">
37
+ {props.fieldConfig.options.map((option) => (
38
+ <Radio
39
+ key={option.label}
40
+ value={option.value}
41
+ disabled={option.isDisabled}
42
+ className={({ checked }) =>
43
+ `${
44
+ checked ? "bg-blue-50" : "bg-white"
45
+ } flex w-full flex-col gap-2 rounded-lg border border-gray-200 p-4 shadow-sm cursor-pointer`
46
+ }
47
+ >
48
+ {({ checked }) => (
49
+ <>
50
+ <div className="flex w-full items-center justify-between">
51
+ <div className="flex items-center justify-center">
52
+ <span className={"listbox-svg"}>
53
+ {option.icon}
54
+ </span>
55
+ <div className="text-sm ">
56
+ <Label
57
+ as="p"
58
+ className={`font-medium ${
59
+ checked ? "text-gray-900" : "text-gray-900"
60
+ }`}
61
+ >
62
+ {option.label}
63
+ </Label>
64
+ </div>
65
+ </div>
66
+ </div>
67
+ {option.helpText ? (
68
+ <p
69
+ className="mt-2 text-tiny text-gray-500"
70
+ id="email-description"
71
+ >
72
+ {option.helpText}
73
+ </p>
74
+ ) : (
75
+ <></>
76
+ )}
77
+ </>
78
+ )}
79
+ </Radio>
80
+ ))}
81
+ </div>
82
+ </RadioGroup>
83
+ )}
84
+ {/*</div>*/}
85
+ </div>
86
+ </>
87
+ );
88
+ }
89
+
90
+ return (
91
+ <RenderFormField fieldConfig={props.fieldConfig} getInput={getInput} />
92
+ );
93
+ };
94
+ export default RadioGroupComponent;
@@ -0,0 +1,53 @@
1
+ import { useContext } from "react";
2
+ import { RegisterOptions } from "react-hook-form";
3
+ import React from "react";
4
+ import { FormContext } from "../context/FormContext";
5
+ import { FormFieldComponentPropSchema } from "../schema/FormFieldSchema";
6
+ import { Input } from "@headlessui/react";
7
+ import RenderFormField from "../util/RenderFormField";
8
+ import { handleChange, registerFormField } from "../util";
9
+
10
+ export const RangeField: React.FC<FormFieldComponentPropSchema> = (
11
+ props: FormFieldComponentPropSchema
12
+ ) => {
13
+ const formContext = useContext(FormContext);
14
+
15
+ let registerOptions: RegisterOptions = registerFormField(props.fieldConfig);
16
+
17
+ let hookProps = formContext.register(props.fieldConfig.name, registerOptions);
18
+
19
+ /**
20
+ * Raw Form Field
21
+ */
22
+ const getInput = () => {
23
+ return (
24
+ <Input
25
+ type="range"
26
+ {...hookProps}
27
+ placeholder={props.fieldConfig?.placeholder}
28
+ readOnly={props.fieldConfig?.readOnly}
29
+ disabled={props.fieldConfig?.disabled}
30
+ autoComplete={props.fieldConfig?.autoComplete}
31
+ defaultValue={props.fieldConfig.defaultValue as string}
32
+ className={`form-range ${
33
+ props.fieldConfig.customClassNames?.fieldClassName || ""
34
+ }`}
35
+ onChange={(e) => {
36
+ handleChange(
37
+ e.target.value,
38
+ formContext,
39
+ props.fieldConfig,
40
+ props.onChange
41
+ );
42
+ }}
43
+ onClick={(event) => {
44
+ event.currentTarget.showPicker();
45
+ }}
46
+ />
47
+ );
48
+ };
49
+
50
+ return (
51
+ <RenderFormField fieldConfig={props.fieldConfig} getInput={getInput} />
52
+ );
53
+ };