gbs-add-block 0.0.25 → 0.0.27
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/index.js +2 -1
- package/package.json +1 -1
- package/source/components/formrenderer/InputHandles.tsx +33 -0
- package/source/components/formrenderer/SelectHandles.tsx +52 -0
- package/source/components/formrenderer/index.tsx +86 -0
- package/source/components/input/types.ts +1 -0
- package/source/components/select/index.tsx +4 -1
package/index.js
CHANGED
|
@@ -18,6 +18,7 @@ const COMPONENTS = [
|
|
|
18
18
|
"Spinner",
|
|
19
19
|
"Toast",
|
|
20
20
|
"Uploader",
|
|
21
|
+
"FormRenderer",
|
|
21
22
|
];
|
|
22
23
|
|
|
23
24
|
const FRAMEWORKS = {
|
|
@@ -63,7 +64,7 @@ function copyCommonFiles() {
|
|
|
63
64
|
const globalStyleSrc = path.join(SOURCE_PATH, "..", "globalStyle.ts");
|
|
64
65
|
const globalStyleDest = path.join(DEST_PATH, "globalStyle.ts");
|
|
65
66
|
fs.copySync(globalStyleSrc, globalStyleDest, { overwrite: true });
|
|
66
|
-
console.log(`
|
|
67
|
+
console.log(`globalStyle.ts copied successfully to ${globalStyleDest}`);
|
|
67
68
|
|
|
68
69
|
// Copy icon folder
|
|
69
70
|
const iconSrc = path.join(SOURCE_PATH, "..", "icon");
|
package/package.json
CHANGED
|
@@ -0,0 +1,33 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Input } from "../input";
|
|
3
|
+
|
|
4
|
+
export default function InputHandles({
|
|
5
|
+
item,
|
|
6
|
+
requirementError,
|
|
7
|
+
setRequirementError,
|
|
8
|
+
}: any) {
|
|
9
|
+
return (
|
|
10
|
+
<div className="w-full">
|
|
11
|
+
{item.label && (
|
|
12
|
+
<label htmlFor={item.name} className="font-medium text-sm">
|
|
13
|
+
{item.label}
|
|
14
|
+
</label>
|
|
15
|
+
)}
|
|
16
|
+
<Input
|
|
17
|
+
type={item.type}
|
|
18
|
+
name={item.name}
|
|
19
|
+
placeholder={item.placeholder || ""}
|
|
20
|
+
error={
|
|
21
|
+
requirementError.includes(item.name)
|
|
22
|
+
? `${item.name} is required`
|
|
23
|
+
: undefined
|
|
24
|
+
}
|
|
25
|
+
onChange={() =>
|
|
26
|
+
setRequirementError((prevErrors: any) =>
|
|
27
|
+
prevErrors.filter((errorName: any) => errorName !== item.name)
|
|
28
|
+
)
|
|
29
|
+
}
|
|
30
|
+
/>
|
|
31
|
+
</div>
|
|
32
|
+
);
|
|
33
|
+
}
|
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
import React from "react";
|
|
2
|
+
import { Select } from "../select";
|
|
3
|
+
|
|
4
|
+
export default function SelectHandles({
|
|
5
|
+
item,
|
|
6
|
+
requirementError,
|
|
7
|
+
setRequirementError,
|
|
8
|
+
formRef,
|
|
9
|
+
}: any) {
|
|
10
|
+
const handleSelect = (value: string, key: string) => {
|
|
11
|
+
if (formRef.current) {
|
|
12
|
+
const hiddenInput = formRef.current.querySelector(
|
|
13
|
+
`input[name="${key}"]`
|
|
14
|
+
) as HTMLInputElement;
|
|
15
|
+
|
|
16
|
+
if (hiddenInput) {
|
|
17
|
+
hiddenInput.value = value;
|
|
18
|
+
} else {
|
|
19
|
+
const input = document.createElement("input");
|
|
20
|
+
input.type = "hidden";
|
|
21
|
+
input.name = key;
|
|
22
|
+
input.value = value;
|
|
23
|
+
formRef.current.appendChild(input);
|
|
24
|
+
}
|
|
25
|
+
}
|
|
26
|
+
};
|
|
27
|
+
|
|
28
|
+
return (
|
|
29
|
+
<div className="w-full">
|
|
30
|
+
{item.label && (
|
|
31
|
+
<label htmlFor={item.name} className="font-medium text-sm">
|
|
32
|
+
{item.label}
|
|
33
|
+
</label>
|
|
34
|
+
)}
|
|
35
|
+
<Select
|
|
36
|
+
name={item.name}
|
|
37
|
+
items={item.options}
|
|
38
|
+
onSelect={(value: string) => {
|
|
39
|
+
handleSelect(value, item.key);
|
|
40
|
+
setRequirementError((prevErrors: any) =>
|
|
41
|
+
prevErrors.filter((errorName: any) => errorName !== item.name)
|
|
42
|
+
);
|
|
43
|
+
}}
|
|
44
|
+
error={
|
|
45
|
+
requirementError.includes(item.name)
|
|
46
|
+
? `${item.name} is required`
|
|
47
|
+
: undefined
|
|
48
|
+
}
|
|
49
|
+
></Select>
|
|
50
|
+
</div>
|
|
51
|
+
);
|
|
52
|
+
}
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
import React, { useRef, useState } from "react";
|
|
2
|
+
import { Button } from "../button";
|
|
3
|
+
import InputHandles from "./InputHandles";
|
|
4
|
+
import SelectHandles from "./SelectHandles";
|
|
5
|
+
|
|
6
|
+
const FormRenderer = ({ onSubmit, sourceData }: any) => {
|
|
7
|
+
const formRef = useRef<HTMLFormElement>(null);
|
|
8
|
+
const [requirementError, setRequirementError] = useState<string[]>([]);
|
|
9
|
+
|
|
10
|
+
const handleSubmit = (event: React.FormEvent<HTMLFormElement>) => {
|
|
11
|
+
event.preventDefault();
|
|
12
|
+
|
|
13
|
+
const requirementErrorItems: string[] = [];
|
|
14
|
+
|
|
15
|
+
sourceData.forEach((item: any) => {
|
|
16
|
+
if (item.required) {
|
|
17
|
+
const field = formRef.current?.querySelector(
|
|
18
|
+
`[name="${item.name}"]`
|
|
19
|
+
) as HTMLInputElement | null;
|
|
20
|
+
|
|
21
|
+
if (!field || !field.value.trim()) {
|
|
22
|
+
requirementErrorItems.push(item.name);
|
|
23
|
+
}
|
|
24
|
+
}
|
|
25
|
+
});
|
|
26
|
+
|
|
27
|
+
setRequirementError(requirementErrorItems);
|
|
28
|
+
|
|
29
|
+
if (requirementErrorItems.length > 0) return;
|
|
30
|
+
|
|
31
|
+
const formData = new FormData(formRef.current as HTMLFormElement);
|
|
32
|
+
onSubmit(formData);
|
|
33
|
+
};
|
|
34
|
+
|
|
35
|
+
return (
|
|
36
|
+
<form ref={formRef} onSubmit={handleSubmit} className="w-96">
|
|
37
|
+
{sourceData?.length > 0 ? (
|
|
38
|
+
<div className="flex flex-col items-start text-left gap-4">
|
|
39
|
+
{sourceData.map((item: any, index: number) => {
|
|
40
|
+
switch (item.component) {
|
|
41
|
+
case "input":
|
|
42
|
+
return (
|
|
43
|
+
<InputHandles
|
|
44
|
+
key={index}
|
|
45
|
+
item={item}
|
|
46
|
+
requirementError={requirementError}
|
|
47
|
+
setRequirementError={setRequirementError}
|
|
48
|
+
/>
|
|
49
|
+
);
|
|
50
|
+
|
|
51
|
+
case "select":
|
|
52
|
+
return (
|
|
53
|
+
<SelectHandles
|
|
54
|
+
key={index}
|
|
55
|
+
item={item}
|
|
56
|
+
requirementError={requirementError}
|
|
57
|
+
setRequirementError={setRequirementError}
|
|
58
|
+
formRef={formRef}
|
|
59
|
+
/>
|
|
60
|
+
);
|
|
61
|
+
|
|
62
|
+
case "button":
|
|
63
|
+
return (
|
|
64
|
+
<div key={index} className="w-full mt-2">
|
|
65
|
+
<Button
|
|
66
|
+
type={item.type}
|
|
67
|
+
className="w-full bg-black text-white py-2 rounded-xl hover:bg-gray-800"
|
|
68
|
+
>
|
|
69
|
+
{item.value}
|
|
70
|
+
</Button>
|
|
71
|
+
</div>
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
default:
|
|
75
|
+
return null;
|
|
76
|
+
}
|
|
77
|
+
})}
|
|
78
|
+
</div>
|
|
79
|
+
) : (
|
|
80
|
+
<div>No Source Data Found</div>
|
|
81
|
+
)}
|
|
82
|
+
</form>
|
|
83
|
+
);
|
|
84
|
+
};
|
|
85
|
+
|
|
86
|
+
export default FormRenderer;
|
|
@@ -175,6 +175,9 @@ const Select = forwardRef<any, SelectProps>((props, ref) => {
|
|
|
175
175
|
<p className={primary["error-primary"]}>{error && error}</p>
|
|
176
176
|
</div>
|
|
177
177
|
|
|
178
|
+
{/* Hidden input to integrate with the form */}
|
|
179
|
+
<input type="hidden" name={name} value={selectedItem || ""} readOnly />
|
|
180
|
+
|
|
178
181
|
{showPopover && (
|
|
179
182
|
<div className={popUp["pop-up-style"]}>
|
|
180
183
|
{showSearch && (
|
|
@@ -225,4 +228,4 @@ const Select = forwardRef<any, SelectProps>((props, ref) => {
|
|
|
225
228
|
});
|
|
226
229
|
|
|
227
230
|
const MemoizedSelect = memo(Select);
|
|
228
|
-
export { MemoizedSelect as Select };
|
|
231
|
+
export { MemoizedSelect as Select };
|