gbs-add-block 0.0.27 → 0.0.29
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 +1 -1
- package/source/components/button/index.tsx +2 -2
- package/source/components/checkbox/index.tsx +7 -0
- package/source/components/darkmode/index.tsx +8 -1
- package/source/components/formrenderer/InputHandles.tsx +54 -18
- package/source/components/formrenderer/SelectHandles.tsx +19 -10
- package/source/components/formrenderer/helperFunctions.ts +9 -0
- package/source/components/formrenderer/index.tsx +18 -11
- package/source/components/formrenderer/types.ts +17 -0
- package/source/components/input/index.tsx +18 -9
- package/source/components/select/index.tsx +4 -2
- package/source/components/select/types.ts +11 -2
- package/source/fallback/index.tsx +1 -1
- /package/source/components/uploader/{Uploader.tsx → index.tsx} +0 -0
package/package.json
CHANGED
|
@@ -5,10 +5,10 @@
|
|
|
5
5
|
* LICENSE file in the root directory of this source tree.
|
|
6
6
|
*/
|
|
7
7
|
|
|
8
|
-
import React, { ButtonHTMLAttributes } from "react";
|
|
8
|
+
import React, { ButtonHTMLAttributes, ReactNode } from "react";
|
|
9
9
|
|
|
10
10
|
interface ButtonProps extends ButtonHTMLAttributes<HTMLButtonElement> {
|
|
11
|
-
children?:
|
|
11
|
+
children?: ReactNode;
|
|
12
12
|
buttonClass?: string;
|
|
13
13
|
}
|
|
14
14
|
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Grampro Business Services and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
1
8
|
import React, { InputHTMLAttributes } from "react";
|
|
2
9
|
|
|
3
10
|
export const Checkbox = ({
|
|
@@ -1,3 +1,10 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Grampro Business Services and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
1
8
|
import React, { useEffect } from "react";
|
|
2
9
|
import Icon from "../icon/Icon";
|
|
3
10
|
import { moon, sun } from "../icon/iconPaths";
|
|
@@ -45,4 +52,4 @@ export const DarkMode = () => {
|
|
|
45
52
|
)}
|
|
46
53
|
</button>
|
|
47
54
|
);
|
|
48
|
-
}
|
|
55
|
+
};
|
|
@@ -1,33 +1,69 @@
|
|
|
1
|
-
import React from "react";
|
|
1
|
+
import React, { useState } from "react";
|
|
2
|
+
import { validateEmail, validatePhoneNumber } from "./helperFunctions";
|
|
2
3
|
import { Input } from "../input";
|
|
4
|
+
import { FormItem } from "./types";
|
|
3
5
|
|
|
4
|
-
|
|
6
|
+
interface InputHandlesProps {
|
|
7
|
+
item?: FormItem;
|
|
8
|
+
requirementError: string[];
|
|
9
|
+
setRequirementError?: React.Dispatch<React.SetStateAction<string[]>>;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
const InputHandles = ({
|
|
5
13
|
item,
|
|
6
14
|
requirementError,
|
|
7
15
|
setRequirementError,
|
|
8
|
-
}:
|
|
16
|
+
}: InputHandlesProps) => {
|
|
17
|
+
const [inputError, setInputError] = useState<string | null>(null);
|
|
18
|
+
|
|
19
|
+
const handleChange = (event: React.ChangeEvent<HTMLInputElement>) => {
|
|
20
|
+
const { value } = event.target;
|
|
21
|
+
|
|
22
|
+
setRequirementError &&
|
|
23
|
+
setRequirementError((prevErrors: string[]) =>
|
|
24
|
+
prevErrors.filter((error) => error !== item?.name)
|
|
25
|
+
);
|
|
26
|
+
|
|
27
|
+
// Validation based on input type
|
|
28
|
+
if (item?.type === "email") {
|
|
29
|
+
if (!validateEmail(value)) {
|
|
30
|
+
setInputError("Invalid email format");
|
|
31
|
+
} else {
|
|
32
|
+
setInputError(null);
|
|
33
|
+
}
|
|
34
|
+
} else if (item?.type === "tel") {
|
|
35
|
+
if (!validatePhoneNumber(value)) {
|
|
36
|
+
setInputError("Invalid phone number. Must be 10 digits.");
|
|
37
|
+
} else {
|
|
38
|
+
setInputError(null);
|
|
39
|
+
}
|
|
40
|
+
}
|
|
41
|
+
};
|
|
42
|
+
|
|
9
43
|
return (
|
|
10
44
|
<div className="w-full">
|
|
11
|
-
{item
|
|
45
|
+
{item?.label && (
|
|
12
46
|
<label htmlFor={item.name} className="font-medium text-sm">
|
|
13
47
|
{item.label}
|
|
14
48
|
</label>
|
|
15
49
|
)}
|
|
16
50
|
<Input
|
|
17
|
-
type={item
|
|
18
|
-
name={item
|
|
19
|
-
placeholder={item
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
setRequirementError((prevErrors: any) =>
|
|
27
|
-
prevErrors.filter((errorName: any) => errorName !== item.name)
|
|
28
|
-
)
|
|
29
|
-
}
|
|
51
|
+
type={item?.type}
|
|
52
|
+
name={item?.name}
|
|
53
|
+
placeholder={item?.placeholder || ""}
|
|
54
|
+
onChange={handleChange}
|
|
55
|
+
className={`border rounded p-2 w-full text-black ${
|
|
56
|
+
inputError || (item?.name && requirementError.includes(item?.name))
|
|
57
|
+
? "border-red-500"
|
|
58
|
+
: "border-gray-300"
|
|
59
|
+
}`}
|
|
30
60
|
/>
|
|
61
|
+
{item?.name && requirementError.includes(item.name) && (
|
|
62
|
+
<p className="text-red-500 text-xs">{`${item?.name} is required`}</p>
|
|
63
|
+
)}
|
|
64
|
+
{inputError && <p className="text-red-500 text-xs">{inputError}</p>}
|
|
31
65
|
</div>
|
|
32
66
|
);
|
|
33
|
-
}
|
|
67
|
+
};
|
|
68
|
+
|
|
69
|
+
export default InputHandles;
|
|
@@ -1,14 +1,22 @@
|
|
|
1
1
|
import React from "react";
|
|
2
2
|
import { Select } from "../select";
|
|
3
|
+
import { FormItem } from "./types";
|
|
4
|
+
|
|
5
|
+
interface SelectHandlesProps {
|
|
6
|
+
item?: FormItem;
|
|
7
|
+
requirementError: string[];
|
|
8
|
+
setRequirementError?: React.Dispatch<React.SetStateAction<string[]>>;
|
|
9
|
+
formRef?: React.RefObject<HTMLFormElement>;
|
|
10
|
+
}
|
|
3
11
|
|
|
4
12
|
export default function SelectHandles({
|
|
5
13
|
item,
|
|
6
14
|
requirementError,
|
|
7
15
|
setRequirementError,
|
|
8
16
|
formRef,
|
|
9
|
-
}:
|
|
17
|
+
}: SelectHandlesProps) {
|
|
10
18
|
const handleSelect = (value: string, key: string) => {
|
|
11
|
-
if (formRef.current) {
|
|
19
|
+
if (formRef && formRef.current) {
|
|
12
20
|
const hiddenInput = formRef.current.querySelector(
|
|
13
21
|
`input[name="${key}"]`
|
|
14
22
|
) as HTMLInputElement;
|
|
@@ -27,22 +35,23 @@ export default function SelectHandles({
|
|
|
27
35
|
|
|
28
36
|
return (
|
|
29
37
|
<div className="w-full">
|
|
30
|
-
{item
|
|
38
|
+
{item?.label && (
|
|
31
39
|
<label htmlFor={item.name} className="font-medium text-sm">
|
|
32
40
|
{item.label}
|
|
33
41
|
</label>
|
|
34
42
|
)}
|
|
35
43
|
<Select
|
|
36
|
-
name={item
|
|
37
|
-
items={item
|
|
44
|
+
name={item?.name}
|
|
45
|
+
items={item?.options}
|
|
38
46
|
onSelect={(value: string) => {
|
|
39
|
-
handleSelect(value, item.key);
|
|
40
|
-
setRequirementError
|
|
41
|
-
|
|
42
|
-
|
|
47
|
+
item?.key && handleSelect(value, item.key);
|
|
48
|
+
setRequirementError &&
|
|
49
|
+
setRequirementError((prevErrors: any) =>
|
|
50
|
+
prevErrors.filter((errorName: any) => errorName !== item?.name)
|
|
51
|
+
);
|
|
43
52
|
}}
|
|
44
53
|
error={
|
|
45
|
-
requirementError.includes(item.name)
|
|
54
|
+
item?.name && requirementError.includes(item.name)
|
|
46
55
|
? `${item.name} is required`
|
|
47
56
|
: undefined
|
|
48
57
|
}
|
|
@@ -0,0 +1,9 @@
|
|
|
1
|
+
export const validateEmail = (email: string) => {
|
|
2
|
+
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
3
|
+
return emailRegex.test(email);
|
|
4
|
+
};
|
|
5
|
+
|
|
6
|
+
export const validatePhoneNumber = (phone: string) => {
|
|
7
|
+
const phoneRegex = /^[0-9]{10}$/;
|
|
8
|
+
return phoneRegex.test(phone);
|
|
9
|
+
};
|
|
@@ -1,9 +1,16 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright (c) Grampro Business Services and affiliates.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
|
|
1
8
|
import React, { useRef, useState } from "react";
|
|
2
|
-
import { Button } from "../button";
|
|
3
9
|
import InputHandles from "./InputHandles";
|
|
4
10
|
import SelectHandles from "./SelectHandles";
|
|
11
|
+
import { FormItem, FormRendererProps } from "./types";
|
|
5
12
|
|
|
6
|
-
const FormRenderer = ({ onSubmit, sourceData }:
|
|
13
|
+
const FormRenderer = ({ onSubmit, sourceData }: FormRendererProps) => {
|
|
7
14
|
const formRef = useRef<HTMLFormElement>(null);
|
|
8
15
|
const [requirementError, setRequirementError] = useState<string[]>([]);
|
|
9
16
|
|
|
@@ -12,8 +19,8 @@ const FormRenderer = ({ onSubmit, sourceData }: any) => {
|
|
|
12
19
|
|
|
13
20
|
const requirementErrorItems: string[] = [];
|
|
14
21
|
|
|
15
|
-
sourceData
|
|
16
|
-
if (item.required) {
|
|
22
|
+
sourceData?.forEach((item: FormItem) => {
|
|
23
|
+
if (item.required && item.name) {
|
|
17
24
|
const field = formRef.current?.querySelector(
|
|
18
25
|
`[name="${item.name}"]`
|
|
19
26
|
) as HTMLInputElement | null;
|
|
@@ -29,14 +36,14 @@ const FormRenderer = ({ onSubmit, sourceData }: any) => {
|
|
|
29
36
|
if (requirementErrorItems.length > 0) return;
|
|
30
37
|
|
|
31
38
|
const formData = new FormData(formRef.current as HTMLFormElement);
|
|
32
|
-
onSubmit(formData);
|
|
39
|
+
if (onSubmit) onSubmit(formData);
|
|
33
40
|
};
|
|
34
41
|
|
|
35
42
|
return (
|
|
36
43
|
<form ref={formRef} onSubmit={handleSubmit} className="w-96">
|
|
37
|
-
{sourceData?.length > 0 ? (
|
|
44
|
+
{sourceData && sourceData?.length > 0 ? (
|
|
38
45
|
<div className="flex flex-col items-start text-left gap-4">
|
|
39
|
-
{sourceData.map((item:
|
|
46
|
+
{sourceData.map((item: FormItem, index: number) => {
|
|
40
47
|
switch (item.component) {
|
|
41
48
|
case "input":
|
|
42
49
|
return (
|
|
@@ -62,12 +69,12 @@ const FormRenderer = ({ onSubmit, sourceData }: any) => {
|
|
|
62
69
|
case "button":
|
|
63
70
|
return (
|
|
64
71
|
<div key={index} className="w-full mt-2">
|
|
65
|
-
<
|
|
66
|
-
type={item.
|
|
67
|
-
className="w-full bg-black text-white py-2 rounded-xl hover:bg-gray-800"
|
|
72
|
+
<button
|
|
73
|
+
type={item.button_type}
|
|
74
|
+
className="w-full bg-black text-white py-2 rounded-xl hover:bg-gray-800 dark:hover:bg-gray-300 dark:bg-white dark:text-black"
|
|
68
75
|
>
|
|
69
76
|
{item.value}
|
|
70
|
-
</
|
|
77
|
+
</button>
|
|
71
78
|
</div>
|
|
72
79
|
);
|
|
73
80
|
|
|
@@ -0,0 +1,17 @@
|
|
|
1
|
+
export type FormItem = {
|
|
2
|
+
name?: string;
|
|
3
|
+
component?: string;
|
|
4
|
+
type?: string;
|
|
5
|
+
required?: boolean;
|
|
6
|
+
placeholder?: string;
|
|
7
|
+
options?: { value: string; label: string }[];
|
|
8
|
+
value?: string;
|
|
9
|
+
label?: string;
|
|
10
|
+
button_type?: "button" | "submit" | "reset";
|
|
11
|
+
key?: string;
|
|
12
|
+
};
|
|
13
|
+
|
|
14
|
+
export type FormRendererProps = {
|
|
15
|
+
onSubmit?: (formData: FormData) => void;
|
|
16
|
+
sourceData?: FormItem[] | undefined;
|
|
17
|
+
};
|
|
@@ -15,21 +15,24 @@ export const Input = ({
|
|
|
15
15
|
OTPField = false,
|
|
16
16
|
OTPValue = "",
|
|
17
17
|
OTPLength = 4,
|
|
18
|
-
OTPClass = "w-8 h-10 m-1 border border-gray-600 rounded-lg text-center",
|
|
18
|
+
OTPClass = "w-8 h-10 m-1 border border-gray-600 rounded-lg text-center text-black",
|
|
19
19
|
onOTPValueChange,
|
|
20
20
|
error = undefined,
|
|
21
21
|
...props
|
|
22
22
|
}: InputProps) => {
|
|
23
23
|
const [otpValues, setOtpValues] = useState(new Array(OTPLength).fill(""));
|
|
24
24
|
const [showPassword, setShowPassword] = useState(false);
|
|
25
|
-
const inputRefs = useRef<
|
|
25
|
+
const inputRefs = useRef<(HTMLInputElement | null)[]>([]);
|
|
26
26
|
|
|
27
27
|
const defaultClass = `bg-gray-100 p-2 rounded-lg ${
|
|
28
28
|
error ? "border border-red-600" : ""
|
|
29
29
|
}`;
|
|
30
30
|
|
|
31
31
|
// This will update the OTP Field Value
|
|
32
|
-
const updateOtpValue = (
|
|
32
|
+
const updateOtpValue = (
|
|
33
|
+
index: number,
|
|
34
|
+
e: React.ChangeEvent<HTMLInputElement>
|
|
35
|
+
) => {
|
|
33
36
|
e.preventDefault();
|
|
34
37
|
const input = e.target;
|
|
35
38
|
if (input) {
|
|
@@ -37,7 +40,7 @@ export const Input = ({
|
|
|
37
40
|
newOtpValues[index] = input.value;
|
|
38
41
|
setOtpValues(newOtpValues);
|
|
39
42
|
if (index < OTPLength - 1 && input.value) {
|
|
40
|
-
inputRefs.current[index + 1]
|
|
43
|
+
inputRefs.current[index + 1]?.focus();
|
|
41
44
|
}
|
|
42
45
|
OTPValue = newOtpValues.join("");
|
|
43
46
|
if (onOTPValueChange) onOTPValueChange(OTPValue);
|
|
@@ -45,13 +48,16 @@ export const Input = ({
|
|
|
45
48
|
};
|
|
46
49
|
|
|
47
50
|
// Function for handling keyboard navigation in OTP Field
|
|
48
|
-
const handleKeydown = (
|
|
51
|
+
const handleKeydown = (
|
|
52
|
+
index: number,
|
|
53
|
+
e: React.KeyboardEvent<HTMLInputElement>
|
|
54
|
+
) => {
|
|
49
55
|
if (e.key === "Backspace" && otpValues[index] === "" && index > 0) {
|
|
50
|
-
inputRefs.current[index - 1]
|
|
56
|
+
inputRefs.current[index - 1]?.focus();
|
|
51
57
|
} else if (e.key === "ArrowLeft" && index > 0) {
|
|
52
|
-
inputRefs.current[index - 1]
|
|
58
|
+
inputRefs.current[index - 1]?.focus();
|
|
53
59
|
} else if (e.key === "ArrowRight" && index < OTPLength - 1) {
|
|
54
|
-
inputRefs.current[index + 1]
|
|
60
|
+
inputRefs.current[index + 1]?.focus();
|
|
55
61
|
}
|
|
56
62
|
};
|
|
57
63
|
|
|
@@ -65,7 +71,10 @@ export const Input = ({
|
|
|
65
71
|
{!OTPField ? (
|
|
66
72
|
<div className="text-input-container w-full relative">
|
|
67
73
|
<input
|
|
68
|
-
className={twMerge(
|
|
74
|
+
className={twMerge(
|
|
75
|
+
defaultClass,
|
|
76
|
+
"w-full text-black focus:outline-blue-400"
|
|
77
|
+
)}
|
|
69
78
|
{...props}
|
|
70
79
|
type={
|
|
71
80
|
props.type === "password" && showPassword ? "text" : props.type
|
|
@@ -18,11 +18,11 @@ import React, {
|
|
|
18
18
|
import Icon from "../icon/Icon";
|
|
19
19
|
import { check, search, upDown, x } from "../icon/iconPaths";
|
|
20
20
|
import { getSourceData } from "../utils";
|
|
21
|
-
import type { ItemsProps, SelectProps } from "./types";
|
|
21
|
+
import type { ItemsProps, SelectHandle, SelectProps } from "./types";
|
|
22
22
|
import { selectStyle } from "./style";
|
|
23
23
|
import { popUp, primary } from "../globalStyle";
|
|
24
24
|
|
|
25
|
-
const Select = forwardRef<
|
|
25
|
+
const Select = forwardRef<SelectHandle, SelectProps>((props, ref) => {
|
|
26
26
|
const {
|
|
27
27
|
id = "",
|
|
28
28
|
name = "",
|
|
@@ -227,5 +227,7 @@ const Select = forwardRef<any, SelectProps>((props, ref) => {
|
|
|
227
227
|
);
|
|
228
228
|
});
|
|
229
229
|
|
|
230
|
+
Select.displayName = "Select";
|
|
231
|
+
|
|
230
232
|
const MemoizedSelect = memo(Select);
|
|
231
233
|
export { MemoizedSelect as Select };
|
|
@@ -11,7 +11,16 @@ export type SelectProps = {
|
|
|
11
11
|
items?: ItemsProps[] | string;
|
|
12
12
|
lazy?: boolean;
|
|
13
13
|
showSearch?: boolean;
|
|
14
|
-
onSelect?:
|
|
14
|
+
onSelect?: (selectedItem: string) => void;
|
|
15
15
|
selectedItem?: string;
|
|
16
|
-
onFiltering?:
|
|
16
|
+
onFiltering?: (searchTerm: string) => void;
|
|
17
|
+
};
|
|
18
|
+
|
|
19
|
+
export type SelectHandle = {
|
|
20
|
+
workingDataSource: ItemsProps[];
|
|
21
|
+
clearSelected: () => void;
|
|
22
|
+
togglePopover: (e: React.MouseEvent) => void;
|
|
23
|
+
getSelectItems: (itemsApi: string) => Promise<void>;
|
|
24
|
+
selectedDisplay: string;
|
|
25
|
+
selected: string | undefined;
|
|
17
26
|
};
|
|
File without changes
|