) {
+ const { t } = useLocale();
+ const fieldType = getCurrentFieldType(fieldForm);
+ if (!fieldType.supportsLengthCheck) {
+ return null;
+ }
+ const supportsLengthCheck = fieldType.supportsLengthCheck;
+ const maxAllowedMaxLength = supportsLengthCheck.maxLength;
+
+ return (
+
+ {
+ fieldForm.setValue("minLength", parseInt(e.target.value ?? 0));
+ // Ensure that maxLength field adjusts its restrictions
+ fieldForm.trigger("maxLength");
+ }}
+ min={0}
+ max={fieldForm.getValues("maxLength") || maxAllowedMaxLength}
+ />
+ {
+ if (!supportsLengthCheck) {
+ return;
+ }
+ fieldForm.setValue("maxLength", parseInt(e.target.value ?? maxAllowedMaxLength));
+ // Ensure that minLength field adjusts its restrictions
+ fieldForm.trigger("minLength");
+ }}
+ min={fieldForm.getValues("minLength") || 0}
+ max={maxAllowedMaxLength}
+ />
+
+ );
+}
+
/**
* Shows the label of the field, taking into account the current variant selected
*/
diff --git a/packages/features/form-builder/FormBuilderField.tsx b/packages/features/form-builder/FormBuilderField.tsx
index 26b9960ef2..e3699dd642 100644
--- a/packages/features/form-builder/FormBuilderField.tsx
+++ b/packages/features/form-builder/FormBuilderField.tsx
@@ -230,6 +230,8 @@ export const ComponentForField = ({
, "
label: "Long Text",
value: "textarea",
isTextType: true,
+ supportsLengthCheck: {
+ // Keep it as small as possible. It is easier to change to a higher value but coming back to a lower value(due to any reason) would be problematic for users who have saved higher value.
+ maxLength: 1000,
+ },
},
select: {
label: "Select",
diff --git a/packages/features/form-builder/schema.ts b/packages/features/form-builder/schema.ts
index 859095c296..f94d145b93 100644
--- a/packages/features/form-builder/schema.ts
+++ b/packages/features/form-builder/schema.ts
@@ -83,6 +83,21 @@ const baseFieldSchema = z.object({
})
)
.optional(),
+
+ /**
+ * It is the minimum number of characters that can be entered in the field.
+ * It is used for types with `supportsLengthCheck= true`.
+ * @default 0
+ * @requires supportsLengthCheck = true
+ */
+ minLength: z.number().optional(),
+
+ /**
+ * It is the maximum number of characters that can be entered in the field.
+ * It is used for types with `supportsLengthCheck= true`.
+ * @requires supportsLengthCheck = true
+ */
+ maxLength: z.number().optional(),
});
export const variantsConfigSchema = z.object({
@@ -116,6 +131,11 @@ export const fieldTypeConfigSchema = z
isTextType: z.boolean().default(false).optional(),
systemOnly: z.boolean().default(false).optional(),
needsOptions: z.boolean().default(false).optional(),
+ supportsLengthCheck: z
+ .object({
+ maxLength: z.number(),
+ })
+ .optional(),
propsType: z.enum([
"text",
"textList",
@@ -233,7 +253,7 @@ export const fieldTypesSchemaMap: Partial<
*/
preprocess: (data: {
field: z.infer;
- response: any;
+ response: string;
isPartialSchema: boolean;
}) => unknown;
/**
@@ -243,7 +263,7 @@ export const fieldTypesSchemaMap: Partial<
*/
superRefine: (data: {
field: z.infer;
- response: any;
+ response: string;
isPartialSchema: boolean;
ctx: z.RefinementCtx;
m: (key: string) => string;
@@ -318,6 +338,36 @@ export const fieldTypesSchemaMap: Partial<
});
},
},
+ textarea: {
+ preprocess: ({ response }) => {
+ return response.trim();
+ },
+ superRefine: ({ field, response, ctx, m }) => {
+ const fieldTypeConfig = fieldTypesConfigMap[field.type];
+ const value = response ?? "";
+ const maxLength = field.maxLength ?? fieldTypeConfig.supportsLengthCheck?.maxLength;
+ const minLength = field.minLength ?? 0;
+ if (!maxLength) {
+ throw new Error("maxLength must be there for textarea field");
+ }
+ const hasExceededMaxLength = value.length > maxLength;
+ const hasNotReachedMinLength = value.length < minLength;
+ if (hasExceededMaxLength) {
+ ctx.addIssue({
+ code: z.ZodIssueCode.custom,
+ message: m(`Max. ${maxLength} characters allowed`),
+ });
+ return;
+ }
+ if (hasNotReachedMinLength) {
+ ctx.addIssue({
+ code: z.ZodIssueCode.custom,
+ message: m(`Min. ${minLength} characters required`),
+ });
+ return;
+ }
+ },
+ },
};
/**