gbs-add-block 0.0.50 → 0.0.51
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/README.md +2 -2
- package/package.json +1 -1
- package/source/components/datepicker/index.tsx +7 -2
- package/source/components/datepicker/types.ts +1 -0
- package/source/components/formrenderer/componentHandles/DatePickerHandles.tsx +34 -2
- package/source/components/formrenderer/componentHandles/MultiHandles.tsx +1 -2
- package/source/components/formrenderer/componentHandles/SelectHandles.tsx +0 -1
- package/source/components/formrenderer/helperFunctions.ts +48 -13
- package/source/components/formrenderer/index.tsx +9 -29
- package/source/components/formrenderer/types.ts +6 -0
- package/source/components/multiselect/index.tsx +1 -0
- package/source/components/select/index.tsx +7 -1
package/README.md
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
# GBS Building Blocks 2.0 (v0.0.
|
|
1
|
+
# GBS Building Blocks 2.0 (v0.0.51)
|
|
2
2
|
|
|
3
3
|
Latest and upgraded version of GBS building blocks with headless UI and removed dependencies.
|
|
4
4
|
|
|
@@ -6,7 +6,7 @@ Latest and upgraded version of GBS building blocks with headless UI and removed
|
|
|
6
6
|
|
|
7
7
|
For detailed documentation on usage and props, Please visit: [Building Block Documentation v2.0](https://blackmax-designs.gitbook.io/building-block-v2.0)
|
|
8
8
|
|
|
9
|
-
## What's New 🎉 (Ver 0.0.
|
|
9
|
+
## What's New 🎉 (Ver 0.0.51)
|
|
10
10
|
|
|
11
11
|
- Update on form renderer
|
|
12
12
|
- Refactored Code for Better Readability
|
package/package.json
CHANGED
|
@@ -29,6 +29,7 @@ export const DatePicker = ({
|
|
|
29
29
|
name,
|
|
30
30
|
error,
|
|
31
31
|
placeholder = "Select a date",
|
|
32
|
+
disabled = false,
|
|
32
33
|
}: DatePickerProps) => {
|
|
33
34
|
applyScrollbarStyles();
|
|
34
35
|
|
|
@@ -61,6 +62,7 @@ export const DatePicker = ({
|
|
|
61
62
|
setCurrentMonth,
|
|
62
63
|
setCurrentYear
|
|
63
64
|
);
|
|
65
|
+
|
|
64
66
|
useClickOutside(
|
|
65
67
|
dateRef as React.RefObject<HTMLElement>,
|
|
66
68
|
() => {
|
|
@@ -124,7 +126,10 @@ export const DatePicker = ({
|
|
|
124
126
|
onClick={toggleDatepicker}
|
|
125
127
|
className={`${
|
|
126
128
|
error ? primary["error-border"] : "border"
|
|
127
|
-
} p-2 rounded-lg w-full flex items-center gap-2 dark:text-white
|
|
129
|
+
} p-2 rounded-lg w-full flex items-center gap-2 dark:text-white ${
|
|
130
|
+
disabled ? "opacity-50 cursor-not-allowed" : ""
|
|
131
|
+
}`}
|
|
132
|
+
disabled={disabled}
|
|
128
133
|
>
|
|
129
134
|
<Icon
|
|
130
135
|
dimensions={{ width: "20", height: "20" }}
|
|
@@ -144,7 +149,7 @@ export const DatePicker = ({
|
|
|
144
149
|
readOnly
|
|
145
150
|
/>
|
|
146
151
|
|
|
147
|
-
{showDatepicker && (
|
|
152
|
+
{showDatepicker && !disabled && (
|
|
148
153
|
<div className="absolute z-10 bg-white border border-gray-300 shadow-lg mt-1 w-full rounded dark:bg-black dark:text-white px-2">
|
|
149
154
|
<div className="flex justify-between items-center p-2">
|
|
150
155
|
<button
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import React from "react";
|
|
1
|
+
import React, { useCallback, useEffect, useState } from "react";
|
|
2
2
|
import { DatePicker } from "../../datepicker";
|
|
3
3
|
import { DatePickerHandlesProps } from "../types";
|
|
4
|
+
import { evaluateExpression } from "@grampro/headless-helpers";
|
|
4
5
|
|
|
5
6
|
export default function DatePickerHandles({
|
|
6
7
|
item,
|
|
@@ -8,7 +9,38 @@ export default function DatePickerHandles({
|
|
|
8
9
|
setRequirementError,
|
|
9
10
|
formRef,
|
|
10
11
|
onChangeEvent,
|
|
12
|
+
context,
|
|
13
|
+
updateContext,
|
|
11
14
|
}: DatePickerHandlesProps) {
|
|
15
|
+
const [isDisabled, setIsDisabled] = useState<boolean>(false);
|
|
16
|
+
const [isRequired, setIsRequired] = useState<boolean>(false);
|
|
17
|
+
|
|
18
|
+
// Evaluate expression with memoization
|
|
19
|
+
const evaluateCondition = useCallback(
|
|
20
|
+
(expression: string | boolean | undefined): boolean => {
|
|
21
|
+
if (typeof expression === "string") {
|
|
22
|
+
return evaluateExpression(expression, context);
|
|
23
|
+
}
|
|
24
|
+
return !!expression;
|
|
25
|
+
},
|
|
26
|
+
[context]
|
|
27
|
+
);
|
|
28
|
+
|
|
29
|
+
// Initialize context and handle dynamic states
|
|
30
|
+
useEffect(() => {
|
|
31
|
+
if (item?.name && item?.value !== undefined) {
|
|
32
|
+
updateContext("datepicker", item.name, item.value);
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const disabled = evaluateCondition(item?.disabled);
|
|
36
|
+
|
|
37
|
+
setIsDisabled(disabled);
|
|
38
|
+
|
|
39
|
+
// Only set required if not disabled
|
|
40
|
+
const required = disabled ? false : evaluateCondition(item?.required);
|
|
41
|
+
setIsRequired(required);
|
|
42
|
+
}, [item, context, evaluateCondition, updateContext]);
|
|
43
|
+
|
|
12
44
|
const handleSelectDate = (value: string[], key: string) => {
|
|
13
45
|
if (formRef && formRef.current) {
|
|
14
46
|
const hiddenInput = formRef.current.querySelector(
|
|
@@ -34,7 +66,7 @@ export default function DatePickerHandles({
|
|
|
34
66
|
{item?.label && (
|
|
35
67
|
<label htmlFor={item.name} className="font-medium text-sm">
|
|
36
68
|
{item.label}
|
|
37
|
-
{
|
|
69
|
+
{isRequired && <span className="text-red-500">*</span>}
|
|
38
70
|
</label>
|
|
39
71
|
)}
|
|
40
72
|
<DatePicker
|
|
@@ -29,11 +29,10 @@ export default function MultiHandles({
|
|
|
29
29
|
// Initialize context and handle dynamic states
|
|
30
30
|
useEffect(() => {
|
|
31
31
|
if (item?.name && item?.value !== undefined) {
|
|
32
|
-
updateContext("select", item.name, item.value);
|
|
32
|
+
updateContext("multi-select", item.name, item.value);
|
|
33
33
|
}
|
|
34
34
|
|
|
35
35
|
const disabled = evaluateCondition(item?.disabled);
|
|
36
|
-
console.log("disabled", disabled);
|
|
37
36
|
|
|
38
37
|
setIsDisabled(disabled);
|
|
39
38
|
|
|
@@ -1,3 +1,37 @@
|
|
|
1
|
+
import InputHandles from "./componentHandles/InputHandles";
|
|
2
|
+
import SelectHandles from "./componentHandles/SelectHandles";
|
|
3
|
+
import MultiHandles from "./componentHandles/MultiHandles";
|
|
4
|
+
import DatePickerHandles from "./componentHandles/DatePickerHandles";
|
|
5
|
+
import CheckboxHandles from "./componentHandles/CheckBoxHandles";
|
|
6
|
+
import { FormItem } from "./types";
|
|
7
|
+
|
|
8
|
+
// Component Map
|
|
9
|
+
export const COMPONENT_MAP = {
|
|
10
|
+
input: InputHandles,
|
|
11
|
+
select: SelectHandles,
|
|
12
|
+
"multi-select": MultiHandles,
|
|
13
|
+
datepicker: DatePickerHandles,
|
|
14
|
+
checkbox: CheckboxHandles,
|
|
15
|
+
} as const;
|
|
16
|
+
|
|
17
|
+
// Field Validation Helper
|
|
18
|
+
export const validateField = (
|
|
19
|
+
field: HTMLInputElement | null,
|
|
20
|
+
item: FormItem
|
|
21
|
+
): boolean => {
|
|
22
|
+
if (!item.required || !item.name || field?.disabled) {
|
|
23
|
+
return true;
|
|
24
|
+
}
|
|
25
|
+
// Explicitly check for null and empty value
|
|
26
|
+
if (!field) {
|
|
27
|
+
return false;
|
|
28
|
+
}
|
|
29
|
+
return field.value.trim() !== "";
|
|
30
|
+
};
|
|
31
|
+
|
|
32
|
+
// Input Validation functions starts here
|
|
33
|
+
// You can add more validation functions here or
|
|
34
|
+
// use zod for more complex validation
|
|
1
35
|
export const validateEmail = (email: string) => {
|
|
2
36
|
const emailRegex = /^[^\s@]+@[^\s@]+\.[^\s@]+$/;
|
|
3
37
|
return emailRegex.test(email);
|
|
@@ -8,19 +42,6 @@ export const validatePhoneNumber = (phone: string) => {
|
|
|
8
42
|
return phoneRegex.test(phone);
|
|
9
43
|
};
|
|
10
44
|
|
|
11
|
-
// In case of return as objects
|
|
12
|
-
export const formDataToObject = (formData: FormData) => {
|
|
13
|
-
const obj: Record<string, any> = {};
|
|
14
|
-
formData.forEach((value, key) => {
|
|
15
|
-
try {
|
|
16
|
-
obj[key] = JSON.parse(value as string);
|
|
17
|
-
} catch {
|
|
18
|
-
obj[key] = value;
|
|
19
|
-
}
|
|
20
|
-
});
|
|
21
|
-
return obj;
|
|
22
|
-
};
|
|
23
|
-
|
|
24
45
|
export const validateInput = (value: string, type?: string): string | null => {
|
|
25
46
|
if (!value) return null;
|
|
26
47
|
|
|
@@ -35,3 +56,17 @@ export const validateInput = (value: string, type?: string): string | null => {
|
|
|
35
56
|
return null;
|
|
36
57
|
}
|
|
37
58
|
};
|
|
59
|
+
// Input Validation functions ends here
|
|
60
|
+
|
|
61
|
+
// In case of return as objects
|
|
62
|
+
export const formDataToObject = (formData: FormData) => {
|
|
63
|
+
const obj: Record<string, any> = {};
|
|
64
|
+
formData.forEach((value, key) => {
|
|
65
|
+
try {
|
|
66
|
+
obj[key] = JSON.parse(value as string);
|
|
67
|
+
} catch {
|
|
68
|
+
obj[key] = value;
|
|
69
|
+
}
|
|
70
|
+
});
|
|
71
|
+
return obj;
|
|
72
|
+
};
|
|
@@ -1,39 +1,19 @@
|
|
|
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, FormEvent } from "react";
|
|
2
9
|
import { useFormContext } from "@grampro/headless-helpers";
|
|
3
|
-
import InputHandles from "./componentHandles/InputHandles";
|
|
4
|
-
import SelectHandles from "./componentHandles/SelectHandles";
|
|
5
|
-
import MultiHandles from "./componentHandles/MultiHandles";
|
|
6
|
-
import DatePickerHandles from "./componentHandles/DatePickerHandles";
|
|
7
|
-
import CheckboxHandles from "./componentHandles/CheckBoxHandles";
|
|
8
10
|
import { FormItem, FormRendererProps } from "./types";
|
|
9
|
-
|
|
10
|
-
// Component mapping
|
|
11
|
-
const COMPONENT_MAP = {
|
|
12
|
-
input: InputHandles,
|
|
13
|
-
select: SelectHandles,
|
|
14
|
-
"multi-select": MultiHandles,
|
|
15
|
-
datepicker: DatePickerHandles,
|
|
16
|
-
checkbox: CheckboxHandles,
|
|
17
|
-
} as const;
|
|
18
|
-
|
|
19
|
-
const validateField = (
|
|
20
|
-
field: HTMLInputElement | null,
|
|
21
|
-
item: FormItem
|
|
22
|
-
): boolean => {
|
|
23
|
-
if (!item.required || !item.name || field?.disabled) {
|
|
24
|
-
return true;
|
|
25
|
-
}
|
|
26
|
-
// Explicitly check for null and empty value
|
|
27
|
-
if (!field) {
|
|
28
|
-
return false;
|
|
29
|
-
}
|
|
30
|
-
return field.value.trim() !== "";
|
|
31
|
-
};
|
|
11
|
+
import { COMPONENT_MAP, validateField } from "./helperFunctions";
|
|
32
12
|
|
|
33
13
|
const FormRenderer: React.FC<FormRendererProps> = ({
|
|
34
14
|
onSubmit,
|
|
35
15
|
sourceData = [],
|
|
36
|
-
formFormationClass = "grid grid-cols-1
|
|
16
|
+
formFormationClass = "grid grid-cols-1 gap-2",
|
|
37
17
|
formParentClass = "w-96",
|
|
38
18
|
}) => {
|
|
39
19
|
const formRef = useRef<HTMLFormElement>(null);
|
|
@@ -89,6 +89,12 @@ export type DatePickerHandlesProps = {
|
|
|
89
89
|
setRequirementError?: React.Dispatch<React.SetStateAction<string[]>>;
|
|
90
90
|
formRef?: React.RefObject<HTMLFormElement | null>;
|
|
91
91
|
onChangeEvent?: (event: any) => void;
|
|
92
|
+
context: FormContext;
|
|
93
|
+
updateContext: (
|
|
94
|
+
componentName: string,
|
|
95
|
+
fieldName: string,
|
|
96
|
+
value: FieldValue
|
|
97
|
+
) => void;
|
|
92
98
|
};
|
|
93
99
|
|
|
94
100
|
export type SelectHandlesProps = {
|
|
@@ -139,7 +139,13 @@ const Select = forwardRef<SelectHandle, SelectProps>((props, ref) => {
|
|
|
139
139
|
{error && <p className={primary["error-primary"]}>{error}</p>}
|
|
140
140
|
</div>
|
|
141
141
|
|
|
142
|
-
<input
|
|
142
|
+
<input
|
|
143
|
+
type="hidden"
|
|
144
|
+
name={name}
|
|
145
|
+
value={selectedItem || ""}
|
|
146
|
+
readOnly
|
|
147
|
+
disabled={disabled}
|
|
148
|
+
/>
|
|
143
149
|
|
|
144
150
|
{showPopover && !disabled && (
|
|
145
151
|
<div className={popUp["pop-up-style"]}>
|