mirror of
https://github.com/formbricks/formbricks.git
synced 2026-04-03 21:20:42 -05:00
fix: build and test
This commit is contained in:
@@ -3,13 +3,11 @@
|
||||
import { PlusIcon } from "lucide-react";
|
||||
import { type JSX, useEffect, useState } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { TSurveyCalElement, TSurveyElementTypeEnum } from "@formbricks/types/surveys/elements";
|
||||
import { TSurveyCalElement } from "@formbricks/types/surveys/elements";
|
||||
import { TSurvey } from "@formbricks/types/surveys/types";
|
||||
import { TValidationRulesForCal } from "@formbricks/types/surveys/validation-rules";
|
||||
import { TUserLocale } from "@formbricks/types/user";
|
||||
import { createI18nString, extractLanguageCodes } from "@/lib/i18n/utils";
|
||||
import { ElementFormInput } from "@/modules/survey/components/element-form-input";
|
||||
import { ValidationRulesEditor } from "@/modules/survey/editor/components/validation-rules-editor";
|
||||
import { AdvancedOptionToggle } from "@/modules/ui/components/advanced-option-toggle";
|
||||
import { Button } from "@/modules/ui/components/button";
|
||||
import { Input } from "@/modules/ui/components/input";
|
||||
@@ -145,16 +143,6 @@ export const CalElementForm = ({
|
||||
</AdvancedOptionToggle>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<ValidationRulesEditor
|
||||
elementType={TSurveyElementTypeEnum.Cal}
|
||||
validation={element.validation}
|
||||
onUpdateValidation={(validation) => {
|
||||
updateElement(elementIdx, {
|
||||
validation,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -4,13 +4,11 @@ import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
import { PlusIcon } from "lucide-react";
|
||||
import { type JSX } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { TSurveyConsentElement, TSurveyElementTypeEnum } from "@formbricks/types/surveys/elements";
|
||||
import { TSurveyConsentElement } from "@formbricks/types/surveys/elements";
|
||||
import { TSurvey } from "@formbricks/types/surveys/types";
|
||||
import { TValidationRulesForConsent } from "@formbricks/types/surveys/validation-rules";
|
||||
import { TUserLocale } from "@formbricks/types/user";
|
||||
import { createI18nString, extractLanguageCodes } from "@/lib/i18n/utils";
|
||||
import { ElementFormInput } from "@/modules/survey/components/element-form-input";
|
||||
import { ValidationRulesEditor } from "@/modules/survey/editor/components/validation-rules-editor";
|
||||
import { Button } from "@/modules/ui/components/button";
|
||||
|
||||
interface ConsentElementFormProps {
|
||||
@@ -104,16 +102,6 @@ export const ConsentElementForm = ({
|
||||
placeholder="I agree to the terms and conditions"
|
||||
value={element.label}
|
||||
/>
|
||||
|
||||
<ValidationRulesEditor
|
||||
elementType={TSurveyElementTypeEnum.Consent}
|
||||
validation={element.validation}
|
||||
onUpdateValidation={(validation) => {
|
||||
updateElement(elementIdx, {
|
||||
validation,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -6,7 +6,6 @@ import { type JSX, useEffect } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { TSurveyContactInfoElement, TSurveyElementTypeEnum } from "@formbricks/types/surveys/elements";
|
||||
import { TSurvey } from "@formbricks/types/surveys/types";
|
||||
import { TValidationRulesForContactInfo } from "@formbricks/types/surveys/validation-rules";
|
||||
import { TUserLocale } from "@formbricks/types/user";
|
||||
import { createI18nString, extractLanguageCodes } from "@/lib/i18n/utils";
|
||||
import { ElementFormInput } from "@/modules/survey/components/element-form-input";
|
||||
@@ -162,11 +161,11 @@ export const ContactInfoElementForm = ({
|
||||
<ValidationRulesEditor
|
||||
elementType={TSurveyElementTypeEnum.ContactInfo}
|
||||
validation={element.validation}
|
||||
onUpdateValidation={(validation) => {
|
||||
updateElement(elementIdx, {
|
||||
validation,
|
||||
});
|
||||
}}
|
||||
onUpdateValidation={(validation) => {
|
||||
updateElement(elementIdx, {
|
||||
validation,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</form>
|
||||
);
|
||||
|
||||
@@ -6,7 +6,6 @@ import { type JSX } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { TSurveyDateElement, TSurveyElementTypeEnum } from "@formbricks/types/surveys/elements";
|
||||
import { TSurvey } from "@formbricks/types/surveys/types";
|
||||
import { TValidationRulesForDate } from "@formbricks/types/surveys/validation-rules";
|
||||
import { TUserLocale } from "@formbricks/types/user";
|
||||
import { createI18nString, extractLanguageCodes } from "@/lib/i18n/utils";
|
||||
import { ElementFormInput } from "@/modules/survey/components/element-form-input";
|
||||
@@ -132,11 +131,11 @@ export const DateElementForm = ({
|
||||
<ValidationRulesEditor
|
||||
elementType={TSurveyElementTypeEnum.Date}
|
||||
validation={element.validation}
|
||||
onUpdateValidation={(validation) => {
|
||||
updateElement(elementIdx, {
|
||||
validation,
|
||||
});
|
||||
}}
|
||||
onUpdateValidation={(validation) => {
|
||||
updateElement(elementIdx, {
|
||||
validation,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</form>
|
||||
);
|
||||
|
||||
@@ -7,7 +7,6 @@ import { type JSX } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { TSurveyElementTypeEnum, TSurveyFileUploadElement } from "@formbricks/types/surveys/elements";
|
||||
import { TSurvey } from "@formbricks/types/surveys/types";
|
||||
import { TValidationRulesForFileUpload } from "@formbricks/types/surveys/validation-rules";
|
||||
import { TUserLocale } from "@formbricks/types/user";
|
||||
import { createI18nString, extractLanguageCodes } from "@/lib/i18n/utils";
|
||||
import { ElementFormInput } from "@/modules/survey/components/element-form-input";
|
||||
@@ -117,11 +116,11 @@ export const FileUploadElementForm = ({
|
||||
<ValidationRulesEditor
|
||||
elementType={TSurveyElementTypeEnum.FileUpload}
|
||||
validation={element.validation}
|
||||
onUpdateValidation={(validation) => {
|
||||
updateElement(elementIdx, {
|
||||
validation,
|
||||
});
|
||||
}}
|
||||
onUpdateValidation={(validation) => {
|
||||
updateElement(elementIdx, {
|
||||
validation,
|
||||
});
|
||||
}}
|
||||
element={element}
|
||||
projectOrganizationId={project?.organizationId}
|
||||
isFormbricksCloud={isFormbricksCloud}
|
||||
|
||||
@@ -4,12 +4,11 @@ import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
import { PlusIcon } from "lucide-react";
|
||||
import { type JSX } from "react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { TSurveyElementTypeEnum, TSurveyNPSElement } from "@formbricks/types/surveys/elements";
|
||||
import { TSurveyNPSElement } from "@formbricks/types/surveys/elements";
|
||||
import { TSurvey } from "@formbricks/types/surveys/types";
|
||||
import { TUserLocale } from "@formbricks/types/user";
|
||||
import { createI18nString, extractLanguageCodes } from "@/lib/i18n/utils";
|
||||
import { ElementFormInput } from "@/modules/survey/components/element-form-input";
|
||||
import { ValidationRulesEditor } from "@/modules/survey/editor/components/validation-rules-editor";
|
||||
import { AdvancedOptionToggle } from "@/modules/ui/components/advanced-option-toggle";
|
||||
import { Button } from "@/modules/ui/components/button";
|
||||
|
||||
@@ -141,16 +140,6 @@ export const NPSElementForm = ({
|
||||
childBorder
|
||||
customContainerClass="p-0 mt-4"
|
||||
/>
|
||||
|
||||
<ValidationRulesEditor
|
||||
elementType={TSurveyElementTypeEnum.NPS}
|
||||
validation={element.validation}
|
||||
onUpdateValidation={(validation) => {
|
||||
updateElement(elementIdx, {
|
||||
validation,
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -3,13 +3,12 @@
|
||||
import { useAutoAnimate } from "@formkit/auto-animate/react";
|
||||
import { HashIcon, PlusIcon, SmileIcon, StarIcon } from "lucide-react";
|
||||
import { useTranslation } from "react-i18next";
|
||||
import { TSurveyElementTypeEnum, TSurveyRatingElement } from "@formbricks/types/surveys/elements";
|
||||
import { TSurveyRatingElement } from "@formbricks/types/surveys/elements";
|
||||
import { TSurvey } from "@formbricks/types/surveys/types";
|
||||
import { TUserLocale } from "@formbricks/types/user";
|
||||
import { createI18nString, extractLanguageCodes } from "@/lib/i18n/utils";
|
||||
import { ElementFormInput } from "@/modules/survey/components/element-form-input";
|
||||
import { Dropdown } from "@/modules/survey/editor/components/rating-type-dropdown";
|
||||
import { ValidationRulesEditor } from "@/modules/survey/editor/components/validation-rules-editor";
|
||||
import { AdvancedOptionToggle } from "@/modules/ui/components/advanced-option-toggle";
|
||||
import { Button } from "@/modules/ui/components/button";
|
||||
import { Label } from "@/modules/ui/components/label";
|
||||
@@ -190,19 +189,6 @@ export const RatingElementForm = ({
|
||||
customContainerClass="p-0 mt-4"
|
||||
/>
|
||||
)}
|
||||
|
||||
<ValidationRulesEditor
|
||||
elementType={TSurveyElementTypeEnum.Rating}
|
||||
validation={element.validation}
|
||||
onUpdateValidation={(validation) => {
|
||||
updateElement(elementIdx, {
|
||||
validation: {
|
||||
rules: validation.rules,
|
||||
logic: validation.logic ?? "and",
|
||||
},
|
||||
});
|
||||
}}
|
||||
/>
|
||||
</form>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -32,7 +32,6 @@ interface ValidationRuleRowProps {
|
||||
fieldOptions: { value: TAddressField | TContactInfoField; label: string }[];
|
||||
needsFieldSelector: boolean;
|
||||
validationRules: TValidationRule[];
|
||||
effectiveMaxSizeInMB?: number;
|
||||
ruleLabels: Record<string, string>;
|
||||
onFieldChange: (ruleId: string, field: TAddressField | TContactInfoField | undefined) => void;
|
||||
onRuleTypeChange: (ruleId: string, newType: TValidationRuleType) => void;
|
||||
@@ -54,7 +53,6 @@ export const ValidationRuleRow = ({
|
||||
fieldOptions,
|
||||
needsFieldSelector,
|
||||
validationRules,
|
||||
effectiveMaxSizeInMB,
|
||||
ruleLabels,
|
||||
onFieldChange,
|
||||
onRuleTypeChange,
|
||||
@@ -130,7 +128,6 @@ export const ValidationRuleRow = ({
|
||||
onChange={(value) => onRuleValueChange(rule.id, value)}
|
||||
onFileExtensionChange={handleFileExtensionChange}
|
||||
element={element}
|
||||
effectiveMaxSizeInMB={effectiveMaxSizeInMB}
|
||||
/>
|
||||
|
||||
{/* Unit selector (if applicable) */}
|
||||
|
||||
@@ -23,7 +23,6 @@ interface ValidationRuleValueInputProps {
|
||||
onChange: (value: string) => void;
|
||||
onFileExtensionChange: (extensions: TAllowedFileExtension[]) => void;
|
||||
element?: TSurveyElement;
|
||||
effectiveMaxSizeInMB?: number;
|
||||
}
|
||||
|
||||
export const ValidationRuleValueInput = ({
|
||||
@@ -34,7 +33,6 @@ export const ValidationRuleValueInput = ({
|
||||
onChange,
|
||||
onFileExtensionChange,
|
||||
element,
|
||||
effectiveMaxSizeInMB,
|
||||
}: ValidationRuleValueInputProps) => {
|
||||
const { t } = useTranslation();
|
||||
|
||||
|
||||
@@ -400,7 +400,6 @@ export const ValidationRulesEditor = ({
|
||||
fieldOptions={fieldOptions}
|
||||
needsFieldSelector={needsFieldSelector}
|
||||
validationRules={validationRules}
|
||||
effectiveMaxSizeInMB={effectiveMaxSizeInMB}
|
||||
ruleLabels={ruleLabels}
|
||||
onFieldChange={handleFieldChange}
|
||||
onRuleTypeChange={handleRuleTypeChange}
|
||||
|
||||
@@ -5,7 +5,6 @@ import { RULE_TYPE_CONFIG } from "./validation-rules-config";
|
||||
describe("RULE_TYPE_CONFIG", () => {
|
||||
test("should have config for all validation rule types", () => {
|
||||
const allRuleTypes: TValidationRuleType[] = [
|
||||
"required",
|
||||
"minLength",
|
||||
"maxLength",
|
||||
"pattern",
|
||||
@@ -151,7 +150,6 @@ describe("RULE_TYPE_CONFIG", () => {
|
||||
});
|
||||
|
||||
test("should not have valueType for rules that don't need values", () => {
|
||||
expect(RULE_TYPE_CONFIG.required.valueType).toBeUndefined();
|
||||
expect(RULE_TYPE_CONFIG.email.valueType).toBeUndefined();
|
||||
expect(RULE_TYPE_CONFIG.url.valueType).toBeUndefined();
|
||||
expect(RULE_TYPE_CONFIG.phone.valueType).toBeUndefined();
|
||||
@@ -167,7 +165,6 @@ describe("RULE_TYPE_CONFIG", () => {
|
||||
});
|
||||
|
||||
test("should not have unitOptions for other rules", () => {
|
||||
expect(RULE_TYPE_CONFIG.required.unitOptions).toBeUndefined();
|
||||
expect(RULE_TYPE_CONFIG.pattern.unitOptions).toBeUndefined();
|
||||
expect(RULE_TYPE_CONFIG.email.unitOptions).toBeUndefined();
|
||||
expect(RULE_TYPE_CONFIG.url.unitOptions).toBeUndefined();
|
||||
|
||||
@@ -1,7 +1,4 @@
|
||||
import {
|
||||
TSurveyElementTypeEnum,
|
||||
TSurveyOpenTextElementInputType,
|
||||
} from "@formbricks/types/surveys/elements";
|
||||
import { TSurveyElementTypeEnum, TSurveyOpenTextElementInputType } from "@formbricks/types/surveys/elements";
|
||||
import {
|
||||
APPLICABLE_RULES,
|
||||
TAddressField,
|
||||
@@ -10,7 +7,15 @@ import {
|
||||
TValidationRuleType,
|
||||
} from "@formbricks/types/surveys/validation-rules";
|
||||
|
||||
const stringRules: TValidationRuleType[] = ["minLength", "maxLength", "pattern", "equals", "doesNotEqual", "contains", "doesNotContain"];
|
||||
const stringRules: TValidationRuleType[] = [
|
||||
"minLength",
|
||||
"maxLength",
|
||||
"pattern",
|
||||
"equals",
|
||||
"doesNotEqual",
|
||||
"contains",
|
||||
"doesNotContain",
|
||||
];
|
||||
|
||||
// Rules applicable per field for Address elements
|
||||
// General text fields don't support format-specific validators (email, url, phone)
|
||||
@@ -40,9 +45,7 @@ export const RULES_BY_INPUT_TYPE: Record<TSurveyOpenTextElementInputType, TValid
|
||||
"minLength",
|
||||
"maxLength",
|
||||
"pattern",
|
||||
"email",
|
||||
"url",
|
||||
"phone",
|
||||
// "email", "url", "phone" excluded - redundant for text inputType
|
||||
"equals",
|
||||
"doesNotEqual",
|
||||
"contains",
|
||||
@@ -78,14 +81,7 @@ export const RULES_BY_INPUT_TYPE: Record<TSurveyOpenTextElementInputType, TValid
|
||||
"contains",
|
||||
"doesNotContain",
|
||||
],
|
||||
number: [
|
||||
"minValue",
|
||||
"maxValue",
|
||||
"isGreaterThan",
|
||||
"isLessThan",
|
||||
"equals",
|
||||
"doesNotEqual",
|
||||
],
|
||||
number: ["minValue", "maxValue", "isGreaterThan", "isLessThan", "equals", "doesNotEqual"],
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -109,14 +105,22 @@ export const getAvailableRuleTypes = (
|
||||
}
|
||||
|
||||
// For Address elements, use field-based filtering
|
||||
if (elementType === TSurveyElementTypeEnum.Address && field) {
|
||||
if (elementType === TSurveyElementTypeEnum.Address) {
|
||||
if (!field) {
|
||||
// Address elements require a field to be specified for validation rules
|
||||
return [];
|
||||
}
|
||||
const applicable = RULES_BY_ADDRESS_FIELD[field as TAddressField] ?? [];
|
||||
const existingTypes = new Set(existingRules.map((r) => r.type));
|
||||
return applicable.filter((ruleType) => !existingTypes.has(ruleType));
|
||||
}
|
||||
|
||||
// For Contact Info elements, use field-based filtering
|
||||
if (elementType === TSurveyElementTypeEnum.ContactInfo && field) {
|
||||
if (elementType === TSurveyElementTypeEnum.ContactInfo) {
|
||||
if (!field) {
|
||||
// Contact Info elements require a field to be specified for validation rules
|
||||
return [];
|
||||
}
|
||||
const applicable = RULES_BY_CONTACT_INFO_FIELD[field as TContactInfoField] ?? [];
|
||||
const existingTypes = new Set(existingRules.map((r) => r.type));
|
||||
return applicable.filter((ruleType) => !existingTypes.has(ruleType));
|
||||
|
||||
@@ -82,7 +82,7 @@ function CTA({
|
||||
<div className="relative space-y-2">
|
||||
<ElementError errorMessage={errorMessage} dir={dir} />
|
||||
|
||||
{buttonExternal && (
|
||||
{buttonExternal ? (
|
||||
<div className="flex w-full justify-start">
|
||||
<Button
|
||||
id={inputId}
|
||||
@@ -95,7 +95,7 @@ function CTA({
|
||||
<SquareArrowOutUpRightIcon className="size-4" />
|
||||
</Button>
|
||||
</div>
|
||||
)}
|
||||
) : null}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
|
||||
@@ -56,13 +56,10 @@ export type TValidationLogic = z.infer<typeof ZValidationLogic>;
|
||||
|
||||
// Combined validation object that includes both rules and logic
|
||||
// Uses general TValidationRule[] type instead of element-specific narrowed types
|
||||
export const createZValidation = () =>
|
||||
z
|
||||
.object({
|
||||
rules: ZValidationRules,
|
||||
logic: ZValidationLogic.optional().default("and"),
|
||||
})
|
||||
.optional();
|
||||
export const ZValidation = z.object({
|
||||
rules: ZValidationRules,
|
||||
logic: ZValidationLogic.default("and"),
|
||||
});
|
||||
|
||||
// Base element (like ZSurveyQuestionBase but WITHOUT logic, buttonLabel, backButtonLabel)
|
||||
// Note: validation is not included in base - each element type will add its own narrowed schema
|
||||
@@ -96,7 +93,7 @@ export const ZSurveyOpenTextElement = ZSurveyElementBase.extend({
|
||||
max: z.number().optional(),
|
||||
})
|
||||
.default({ enabled: false }),
|
||||
validation: createZValidation(),
|
||||
validation: ZValidation.optional(),
|
||||
}).superRefine((data, ctx) => {
|
||||
if (data.charLimit.enabled && data.charLimit.min === undefined && data.charLimit.max === undefined) {
|
||||
ctx.addIssue({
|
||||
@@ -133,7 +130,7 @@ export type TSurveyOpenTextElement = z.infer<typeof ZSurveyOpenTextElement>;
|
||||
export const ZSurveyConsentElement = ZSurveyElementBase.extend({
|
||||
type: z.literal(TSurveyElementTypeEnum.Consent),
|
||||
label: ZI18nString,
|
||||
validation: createZValidation(),
|
||||
validation: ZValidation.optional(),
|
||||
});
|
||||
|
||||
export type TSurveyConsentElement = z.infer<typeof ZSurveyConsentElement>;
|
||||
@@ -167,7 +164,7 @@ export const ZSurveyMultipleChoiceMultiElement = ZSurveyElementBase.extend({
|
||||
.min(2, { message: "Multiple Choice Element must have at least two choices" }),
|
||||
shuffleOption: ZShuffleOption.optional(),
|
||||
otherOptionPlaceholder: ZI18nString.optional(),
|
||||
validation: createZValidation(),
|
||||
validation: ZValidation.optional(),
|
||||
});
|
||||
|
||||
// Union type for Multiple Choice Elements
|
||||
@@ -184,7 +181,6 @@ export const ZSurveyNPSElement = ZSurveyElementBase.extend({
|
||||
lowerLabel: ZI18nString.optional(),
|
||||
upperLabel: ZI18nString.optional(),
|
||||
isColorCodingEnabled: z.boolean().optional().default(false),
|
||||
validation: createZValidation(),
|
||||
});
|
||||
|
||||
export type TSurveyNPSElement = z.infer<typeof ZSurveyNPSElement>;
|
||||
@@ -236,7 +232,6 @@ export const ZSurveyRatingElement = ZSurveyElementBase.extend({
|
||||
lowerLabel: ZI18nString.optional(),
|
||||
upperLabel: ZI18nString.optional(),
|
||||
isColorCodingEnabled: z.boolean().optional().default(false),
|
||||
validation: createZValidation(),
|
||||
});
|
||||
|
||||
export type TSurveyRatingElement = z.infer<typeof ZSurveyRatingElement>;
|
||||
@@ -255,7 +250,7 @@ export const ZSurveyPictureSelectionElement = ZSurveyElementBase.extend({
|
||||
choices: z
|
||||
.array(ZSurveyPictureChoice)
|
||||
.min(2, { message: "Picture Selection element must have a minimum of 2 choices" }),
|
||||
validation: createZValidation(),
|
||||
validation: ZValidation.optional(),
|
||||
});
|
||||
|
||||
export type TSurveyPictureSelectionElement = z.infer<typeof ZSurveyPictureSelectionElement>;
|
||||
@@ -265,7 +260,7 @@ export const ZSurveyDateElement = ZSurveyElementBase.extend({
|
||||
type: z.literal(TSurveyElementTypeEnum.Date),
|
||||
html: ZI18nString.optional(),
|
||||
format: z.enum(["M-d-y", "d-M-y", "y-M-d"]),
|
||||
validation: createZValidation(),
|
||||
validation: ZValidation.optional(),
|
||||
});
|
||||
|
||||
export type TSurveyDateElement = z.infer<typeof ZSurveyDateElement>;
|
||||
@@ -276,7 +271,7 @@ export const ZSurveyFileUploadElement = ZSurveyElementBase.extend({
|
||||
allowMultipleFiles: z.boolean(),
|
||||
maxSizeInMB: z.number().optional(),
|
||||
allowedFileExtensions: z.array(ZAllowedFileExtension).optional(),
|
||||
validation: createZValidation(),
|
||||
validation: ZValidation.optional(),
|
||||
});
|
||||
|
||||
export type TSurveyFileUploadElement = z.infer<typeof ZSurveyFileUploadElement>;
|
||||
@@ -286,7 +281,6 @@ export const ZSurveyCalElement = ZSurveyElementBase.extend({
|
||||
type: z.literal(TSurveyElementTypeEnum.Cal),
|
||||
calUserName: z.string().min(1, { message: "Cal user name is required" }),
|
||||
calHost: z.string().optional(),
|
||||
validation: createZValidation(),
|
||||
});
|
||||
|
||||
export type TSurveyCalElement = z.infer<typeof ZSurveyCalElement>;
|
||||
@@ -304,7 +298,7 @@ export const ZSurveyMatrixElement = ZSurveyElementBase.extend({
|
||||
rows: z.array(ZSurveyMatrixElementChoice),
|
||||
columns: z.array(ZSurveyMatrixElementChoice),
|
||||
shuffleOption: ZShuffleOption.optional().default("none"),
|
||||
validation: createZValidation(),
|
||||
validation: ZValidation.optional(),
|
||||
});
|
||||
|
||||
export type TSurveyMatrixElement = z.infer<typeof ZSurveyMatrixElement>;
|
||||
@@ -326,7 +320,7 @@ export const ZSurveyAddressElement = ZSurveyElementBase.extend({
|
||||
state: ZToggleInputConfig,
|
||||
zip: ZToggleInputConfig,
|
||||
country: ZToggleInputConfig,
|
||||
validation: createZValidation(),
|
||||
validation: ZValidation.optional(),
|
||||
});
|
||||
|
||||
export type TSurveyAddressElement = z.infer<typeof ZSurveyAddressElement>;
|
||||
@@ -340,7 +334,7 @@ export const ZSurveyRankingElement = ZSurveyElementBase.extend({
|
||||
.max(25, { message: "Ranking Element can have at most 25 options" }),
|
||||
otherOptionPlaceholder: ZI18nString.optional(),
|
||||
shuffleOption: ZShuffleOption.optional(),
|
||||
validation: createZValidation(),
|
||||
validation: ZValidation.optional(),
|
||||
});
|
||||
|
||||
export type TSurveyRankingElement = z.infer<typeof ZSurveyRankingElement>;
|
||||
@@ -353,7 +347,7 @@ export const ZSurveyContactInfoElement = ZSurveyElementBase.extend({
|
||||
email: ZToggleInputConfig,
|
||||
phone: ZToggleInputConfig,
|
||||
company: ZToggleInputConfig,
|
||||
validation: createZValidation(),
|
||||
validation: ZValidation.optional(),
|
||||
});
|
||||
|
||||
export type TSurveyContactInfoElement = z.infer<typeof ZSurveyContactInfoElement>;
|
||||
|
||||
@@ -224,190 +224,13 @@ export type TValidationRuleParamsFileExtensionIsNot = z.infer<typeof ZValidation
|
||||
|
||||
// Validation rule stored on element - discriminated union with type at top level
|
||||
// Field property is optional and used for address/contact info elements to target specific sub-fields
|
||||
export const ZValidationRule = z.discriminatedUnion("type", [
|
||||
z.object({
|
||||
id: z.string(),
|
||||
type: z.literal("minLength"),
|
||||
params: ZValidationRuleParamsMinLength,
|
||||
customErrorMessage: ZI18nString.optional(),
|
||||
field: ZValidationRuleField.optional(),
|
||||
}),
|
||||
z.object({
|
||||
id: z.string(),
|
||||
type: z.literal("maxLength"),
|
||||
params: ZValidationRuleParamsMaxLength,
|
||||
customErrorMessage: ZI18nString.optional(),
|
||||
field: ZValidationRuleField.optional(),
|
||||
}),
|
||||
z.object({
|
||||
id: z.string(),
|
||||
type: z.literal("pattern"),
|
||||
params: ZValidationRuleParamsPattern,
|
||||
customErrorMessage: ZI18nString.optional(),
|
||||
field: ZValidationRuleField.optional(),
|
||||
}),
|
||||
z.object({
|
||||
id: z.string(),
|
||||
type: z.literal("email"),
|
||||
params: ZValidationRuleParamsEmail,
|
||||
customErrorMessage: ZI18nString.optional(),
|
||||
field: ZValidationRuleField.optional(),
|
||||
}),
|
||||
z.object({
|
||||
id: z.string(),
|
||||
type: z.literal("url"),
|
||||
params: ZValidationRuleParamsUrl,
|
||||
customErrorMessage: ZI18nString.optional(),
|
||||
field: ZValidationRuleField.optional(),
|
||||
}),
|
||||
z.object({
|
||||
id: z.string(),
|
||||
type: z.literal("phone"),
|
||||
params: ZValidationRuleParamsPhone,
|
||||
customErrorMessage: ZI18nString.optional(),
|
||||
field: ZValidationRuleField.optional(),
|
||||
}),
|
||||
z.object({
|
||||
id: z.string(),
|
||||
type: z.literal("minValue"),
|
||||
params: ZValidationRuleParamsMinValue,
|
||||
customErrorMessage: ZI18nString.optional(),
|
||||
field: ZValidationRuleField.optional(),
|
||||
}),
|
||||
z.object({
|
||||
id: z.string(),
|
||||
type: z.literal("maxValue"),
|
||||
params: ZValidationRuleParamsMaxValue,
|
||||
customErrorMessage: ZI18nString.optional(),
|
||||
field: ZValidationRuleField.optional(),
|
||||
}),
|
||||
z.object({
|
||||
id: z.string(),
|
||||
type: z.literal("minSelections"),
|
||||
params: ZValidationRuleParamsMinSelections,
|
||||
customErrorMessage: ZI18nString.optional(),
|
||||
field: ZValidationRuleField.optional(),
|
||||
}),
|
||||
z.object({
|
||||
id: z.string(),
|
||||
type: z.literal("maxSelections"),
|
||||
params: ZValidationRuleParamsMaxSelections,
|
||||
customErrorMessage: ZI18nString.optional(),
|
||||
field: ZValidationRuleField.optional(),
|
||||
}),
|
||||
z.object({
|
||||
id: z.string(),
|
||||
type: z.literal("equals"),
|
||||
params: ZValidationRuleParamsEquals,
|
||||
customErrorMessage: ZI18nString.optional(),
|
||||
field: ZValidationRuleField.optional(),
|
||||
}),
|
||||
z.object({
|
||||
id: z.string(),
|
||||
type: z.literal("doesNotEqual"),
|
||||
params: ZValidationRuleParamsDoesNotEqual,
|
||||
customErrorMessage: ZI18nString.optional(),
|
||||
field: ZValidationRuleField.optional(),
|
||||
}),
|
||||
z.object({
|
||||
id: z.string(),
|
||||
type: z.literal("contains"),
|
||||
params: ZValidationRuleParamsContains,
|
||||
customErrorMessage: ZI18nString.optional(),
|
||||
field: ZValidationRuleField.optional(),
|
||||
}),
|
||||
z.object({
|
||||
id: z.string(),
|
||||
type: z.literal("doesNotContain"),
|
||||
params: ZValidationRuleParamsDoesNotContain,
|
||||
customErrorMessage: ZI18nString.optional(),
|
||||
field: ZValidationRuleField.optional(),
|
||||
}),
|
||||
z.object({
|
||||
id: z.string(),
|
||||
type: z.literal("isGreaterThan"),
|
||||
params: ZValidationRuleParamsIsGreaterThan,
|
||||
customErrorMessage: ZI18nString.optional(),
|
||||
field: ZValidationRuleField.optional(),
|
||||
}),
|
||||
z.object({
|
||||
id: z.string(),
|
||||
type: z.literal("isLessThan"),
|
||||
params: ZValidationRuleParamsIsLessThan,
|
||||
customErrorMessage: ZI18nString.optional(),
|
||||
field: ZValidationRuleField.optional(),
|
||||
}),
|
||||
z.object({
|
||||
id: z.string(),
|
||||
type: z.literal("isLaterThan"),
|
||||
params: ZValidationRuleParamsIsLaterThan,
|
||||
customErrorMessage: ZI18nString.optional(),
|
||||
field: ZValidationRuleField.optional(),
|
||||
}),
|
||||
z.object({
|
||||
id: z.string(),
|
||||
type: z.literal("isEarlierThan"),
|
||||
params: ZValidationRuleParamsIsEarlierThan,
|
||||
customErrorMessage: ZI18nString.optional(),
|
||||
field: ZValidationRuleField.optional(),
|
||||
}),
|
||||
z.object({
|
||||
id: z.string(),
|
||||
type: z.literal("isBetween"),
|
||||
params: ZValidationRuleParamsIsBetween,
|
||||
customErrorMessage: ZI18nString.optional(),
|
||||
field: ZValidationRuleField.optional(),
|
||||
}),
|
||||
z.object({
|
||||
id: z.string(),
|
||||
type: z.literal("isNotBetween"),
|
||||
params: ZValidationRuleParamsIsNotBetween,
|
||||
customErrorMessage: ZI18nString.optional(),
|
||||
field: ZValidationRuleField.optional(),
|
||||
}),
|
||||
z.object({
|
||||
id: z.string(),
|
||||
type: z.literal("minRanked"),
|
||||
params: ZValidationRuleParamsMinRanked,
|
||||
customErrorMessage: ZI18nString.optional(),
|
||||
field: ZValidationRuleField.optional(),
|
||||
}),
|
||||
z.object({
|
||||
id: z.string(),
|
||||
type: z.literal("minRowsAnswered"),
|
||||
params: ZValidationRuleParamsMinRowsAnswered,
|
||||
customErrorMessage: ZI18nString.optional(),
|
||||
field: ZValidationRuleField.optional(),
|
||||
}),
|
||||
z.object({
|
||||
id: z.string(),
|
||||
type: z.literal("fileSizeAtLeast"),
|
||||
params: ZValidationRuleParamsFileSizeAtLeast,
|
||||
customErrorMessage: ZI18nString.optional(),
|
||||
field: ZValidationRuleField.optional(),
|
||||
}),
|
||||
z.object({
|
||||
id: z.string(),
|
||||
type: z.literal("fileSizeAtMost"),
|
||||
params: ZValidationRuleParamsFileSizeAtMost,
|
||||
customErrorMessage: ZI18nString.optional(),
|
||||
field: ZValidationRuleField.optional(),
|
||||
}),
|
||||
z.object({
|
||||
id: z.string(),
|
||||
type: z.literal("fileExtensionIs"),
|
||||
params: ZValidationRuleParamsFileExtensionIs,
|
||||
customErrorMessage: ZI18nString.optional(),
|
||||
field: ZValidationRuleField.optional(),
|
||||
}),
|
||||
z.object({
|
||||
id: z.string(),
|
||||
type: z.literal("fileExtensionIsNot"),
|
||||
params: ZValidationRuleParamsFileExtensionIsNot,
|
||||
customErrorMessage: ZI18nString.optional(),
|
||||
field: ZValidationRuleField.optional(),
|
||||
}),
|
||||
]);
|
||||
export const ZValidationRule = z.object({
|
||||
id: z.string(),
|
||||
type: ZValidationRuleType,
|
||||
params: ZValidationRuleParams,
|
||||
customErrorMessage: ZI18nString.optional(),
|
||||
field: ZValidationRuleField.optional(),
|
||||
});
|
||||
|
||||
export type TValidationRule = z.infer<typeof ZValidationRule>;
|
||||
|
||||
@@ -433,23 +256,16 @@ const OPEN_TEXT_RULES = [
|
||||
"isLessThan",
|
||||
] as const;
|
||||
|
||||
const MULTIPLE_CHOICE_SINGLE_RULES = [] as const;
|
||||
const MULTIPLE_CHOICE_MULTI_RULES = [
|
||||
"minSelections",
|
||||
"maxSelections",
|
||||
] as const;
|
||||
const RATING_RULES = [] as const;
|
||||
const NPS_RULES = [] as const;
|
||||
const DATE_RULES = [
|
||||
"isLaterThan",
|
||||
"isEarlierThan",
|
||||
"isBetween",
|
||||
"isNotBetween",
|
||||
] as const;
|
||||
const CONSENT_RULES = [] as const;
|
||||
const MULTIPLE_CHOICE_MULTI_RULES = ["minSelections", "maxSelections"] as const;
|
||||
const DATE_RULES = ["isLaterThan", "isEarlierThan", "isBetween", "isNotBetween"] as const;
|
||||
const MATRIX_RULES = ["minRowsAnswered"] as const;
|
||||
const RANKING_RULES = ["minRanked"] as const;
|
||||
const FILE_UPLOAD_RULES = ["fileSizeAtLeast", "fileSizeAtMost", "fileExtensionIs", "fileExtensionIsNot"] as const;
|
||||
const FILE_UPLOAD_RULES = [
|
||||
"fileSizeAtLeast",
|
||||
"fileSizeAtMost",
|
||||
"fileExtensionIs",
|
||||
"fileExtensionIsNot",
|
||||
] as const;
|
||||
const PICTURE_SELECTION_RULES = ["minSelections", "maxSelections"] as const;
|
||||
// Address and Contact Info can use text-based validation rules on specific fields
|
||||
const ADDRESS_RULES = [
|
||||
@@ -476,26 +292,18 @@ const CONTACT_INFO_RULES = [
|
||||
"contains",
|
||||
"doesNotContain",
|
||||
] as const;
|
||||
const CAL_RULES = [] as const;
|
||||
const CTA_RULES = [] as const;
|
||||
|
||||
// Applicable rules per element type
|
||||
export const APPLICABLE_RULES: Record<string, TValidationRuleType[]> = {
|
||||
openText: [...OPEN_TEXT_RULES],
|
||||
multipleChoiceSingle: [...MULTIPLE_CHOICE_SINGLE_RULES],
|
||||
multipleChoiceMulti: [...MULTIPLE_CHOICE_MULTI_RULES],
|
||||
rating: [...RATING_RULES],
|
||||
nps: [...NPS_RULES],
|
||||
date: [...DATE_RULES],
|
||||
consent: [...CONSENT_RULES],
|
||||
matrix: [...MATRIX_RULES],
|
||||
ranking: [...RANKING_RULES],
|
||||
fileUpload: [...FILE_UPLOAD_RULES],
|
||||
pictureSelection: [...PICTURE_SELECTION_RULES],
|
||||
address: [...ADDRESS_RULES],
|
||||
contactInfo: [...CONTACT_INFO_RULES],
|
||||
cal: [...CAL_RULES],
|
||||
cta: [...CTA_RULES], // CTA never validates
|
||||
};
|
||||
|
||||
// Type helper to filter validation rules by allowed types
|
||||
@@ -510,16 +318,10 @@ export type TValidationRulesForElementType<T extends readonly TValidationRuleTyp
|
||||
|
||||
// Specific validation rule types for each element type
|
||||
export type TValidationRulesForOpenText = TValidationRulesForElementType<typeof OPEN_TEXT_RULES>;
|
||||
export type TValidationRulesForMultipleChoiceSingle = TValidationRulesForElementType<
|
||||
typeof MULTIPLE_CHOICE_SINGLE_RULES
|
||||
>;
|
||||
export type TValidationRulesForMultipleChoiceMulti = TValidationRulesForElementType<
|
||||
typeof MULTIPLE_CHOICE_MULTI_RULES
|
||||
>;
|
||||
export type TValidationRulesForRating = TValidationRulesForElementType<typeof RATING_RULES>;
|
||||
export type TValidationRulesForNPS = TValidationRulesForElementType<typeof NPS_RULES>;
|
||||
export type TValidationRulesForDate = TValidationRulesForElementType<typeof DATE_RULES>;
|
||||
export type TValidationRulesForConsent = TValidationRulesForElementType<typeof CONSENT_RULES>;
|
||||
export type TValidationRulesForMatrix = TValidationRulesForElementType<typeof MATRIX_RULES>;
|
||||
export type TValidationRulesForRanking = TValidationRulesForElementType<typeof RANKING_RULES>;
|
||||
export type TValidationRulesForFileUpload = TValidationRulesForElementType<typeof FILE_UPLOAD_RULES>;
|
||||
@@ -528,8 +330,6 @@ export type TValidationRulesForPictureSelection = TValidationRulesForElementType
|
||||
>;
|
||||
export type TValidationRulesForAddress = TValidationRulesForElementType<typeof ADDRESS_RULES>;
|
||||
export type TValidationRulesForContactInfo = TValidationRulesForElementType<typeof CONTACT_INFO_RULES>;
|
||||
export type TValidationRulesForCal = TValidationRulesForElementType<typeof CAL_RULES>;
|
||||
export type TValidationRulesForCTA = TValidationRulesForElementType<typeof CTA_RULES>;
|
||||
|
||||
// Validation error returned by evaluator
|
||||
export interface TValidationError {
|
||||
@@ -546,224 +346,3 @@ export interface TValidationResult {
|
||||
|
||||
// Error map for block-level validation (keyed by elementId)
|
||||
export type TValidationErrorMap = Record<string, TValidationError[]>;
|
||||
|
||||
// Element-specific validation rules schemas (manually created for type safety)
|
||||
// These are narrowed versions of ZValidationRule that only include applicable rule types
|
||||
export const ZValidationRulesForOpenText: z.ZodType<TValidationRulesForOpenText> = z.array(
|
||||
z.discriminatedUnion("type", [
|
||||
z.object({
|
||||
id: z.string(),
|
||||
type: z.literal("minLength"),
|
||||
params: ZValidationRuleParamsMinLength,
|
||||
customErrorMessage: ZI18nString.optional(),
|
||||
}),
|
||||
z.object({
|
||||
id: z.string(),
|
||||
type: z.literal("maxLength"),
|
||||
params: ZValidationRuleParamsMaxLength,
|
||||
customErrorMessage: ZI18nString.optional(),
|
||||
}),
|
||||
z.object({
|
||||
id: z.string(),
|
||||
type: z.literal("pattern"),
|
||||
params: ZValidationRuleParamsPattern,
|
||||
customErrorMessage: ZI18nString.optional(),
|
||||
}),
|
||||
z.object({
|
||||
id: z.string(),
|
||||
type: z.literal("email"),
|
||||
params: ZValidationRuleParamsEmail,
|
||||
customErrorMessage: ZI18nString.optional(),
|
||||
}),
|
||||
z.object({
|
||||
id: z.string(),
|
||||
type: z.literal("url"),
|
||||
params: ZValidationRuleParamsUrl,
|
||||
customErrorMessage: ZI18nString.optional(),
|
||||
}),
|
||||
z.object({
|
||||
id: z.string(),
|
||||
type: z.literal("phone"),
|
||||
params: ZValidationRuleParamsPhone,
|
||||
customErrorMessage: ZI18nString.optional(),
|
||||
}),
|
||||
z.object({
|
||||
id: z.string(),
|
||||
type: z.literal("minValue"),
|
||||
params: ZValidationRuleParamsMinValue,
|
||||
customErrorMessage: ZI18nString.optional(),
|
||||
}),
|
||||
z.object({
|
||||
id: z.string(),
|
||||
type: z.literal("maxValue"),
|
||||
params: ZValidationRuleParamsMaxValue,
|
||||
customErrorMessage: ZI18nString.optional(),
|
||||
}),
|
||||
z.object({
|
||||
id: z.string(),
|
||||
type: z.literal("equals"),
|
||||
params: ZValidationRuleParamsEquals,
|
||||
customErrorMessage: ZI18nString.optional(),
|
||||
}),
|
||||
z.object({
|
||||
id: z.string(),
|
||||
type: z.literal("doesNotEqual"),
|
||||
params: ZValidationRuleParamsDoesNotEqual,
|
||||
customErrorMessage: ZI18nString.optional(),
|
||||
}),
|
||||
z.object({
|
||||
id: z.string(),
|
||||
type: z.literal("contains"),
|
||||
params: ZValidationRuleParamsContains,
|
||||
customErrorMessage: ZI18nString.optional(),
|
||||
}),
|
||||
z.object({
|
||||
id: z.string(),
|
||||
type: z.literal("doesNotContain"),
|
||||
params: ZValidationRuleParamsDoesNotContain,
|
||||
customErrorMessage: ZI18nString.optional(),
|
||||
}),
|
||||
z.object({
|
||||
id: z.string(),
|
||||
type: z.literal("isGreaterThan"),
|
||||
params: ZValidationRuleParamsIsGreaterThan,
|
||||
customErrorMessage: ZI18nString.optional(),
|
||||
}),
|
||||
z.object({
|
||||
id: z.string(),
|
||||
type: z.literal("isLessThan"),
|
||||
params: ZValidationRuleParamsIsLessThan,
|
||||
customErrorMessage: ZI18nString.optional(),
|
||||
}),
|
||||
])
|
||||
);
|
||||
|
||||
|
||||
export const ZValidationRulesForMultipleChoiceMulti: z.ZodType<TValidationRulesForMultipleChoiceMulti> =
|
||||
z.array(
|
||||
z.discriminatedUnion("type", [
|
||||
z.object({
|
||||
id: z.string(),
|
||||
type: z.literal("minSelections"),
|
||||
params: ZValidationRuleParamsMinSelections,
|
||||
customErrorMessage: ZI18nString.optional(),
|
||||
}),
|
||||
z.object({
|
||||
id: z.string(),
|
||||
type: z.literal("maxSelections"),
|
||||
params: ZValidationRuleParamsMaxSelections,
|
||||
customErrorMessage: ZI18nString.optional(),
|
||||
}),
|
||||
])
|
||||
);
|
||||
|
||||
export const ZValidationRulesForRating: z.ZodType<TValidationRulesForRating> = z.array(z.never());
|
||||
|
||||
export const ZValidationRulesForNPS: z.ZodType<TValidationRulesForNPS> = z.array(z.never());
|
||||
|
||||
export const ZValidationRulesForDate: z.ZodType<TValidationRulesForDate> = z.array(
|
||||
z.discriminatedUnion("type", [
|
||||
z.object({
|
||||
id: z.string(),
|
||||
type: z.literal("isLaterThan"),
|
||||
params: ZValidationRuleParamsIsLaterThan,
|
||||
customErrorMessage: ZI18nString.optional(),
|
||||
}),
|
||||
z.object({
|
||||
id: z.string(),
|
||||
type: z.literal("isEarlierThan"),
|
||||
params: ZValidationRuleParamsIsEarlierThan,
|
||||
customErrorMessage: ZI18nString.optional(),
|
||||
}),
|
||||
z.object({
|
||||
id: z.string(),
|
||||
type: z.literal("isBetween"),
|
||||
params: ZValidationRuleParamsIsBetween,
|
||||
customErrorMessage: ZI18nString.optional(),
|
||||
}),
|
||||
z.object({
|
||||
id: z.string(),
|
||||
type: z.literal("isNotBetween"),
|
||||
params: ZValidationRuleParamsIsNotBetween,
|
||||
customErrorMessage: ZI18nString.optional(),
|
||||
}),
|
||||
])
|
||||
);
|
||||
|
||||
export const ZValidationRulesForConsent: z.ZodType<TValidationRulesForConsent> = z.array(z.never());
|
||||
|
||||
export const ZValidationRulesForMatrix: z.ZodType<TValidationRulesForMatrix> = z.array(
|
||||
z.discriminatedUnion("type", [
|
||||
z.object({
|
||||
id: z.string(),
|
||||
type: z.literal("minRowsAnswered"),
|
||||
params: ZValidationRuleParamsMinRowsAnswered,
|
||||
customErrorMessage: ZI18nString.optional(),
|
||||
}),
|
||||
])
|
||||
);
|
||||
|
||||
export const ZValidationRulesForRanking: z.ZodType<TValidationRulesForRanking> = z.array(
|
||||
z.discriminatedUnion("type", [
|
||||
z.object({
|
||||
id: z.string(),
|
||||
type: z.literal("minRanked"),
|
||||
params: ZValidationRuleParamsMinRanked,
|
||||
customErrorMessage: ZI18nString.optional(),
|
||||
}),
|
||||
])
|
||||
);
|
||||
|
||||
export const ZValidationRulesForFileUpload: z.ZodType<TValidationRulesForFileUpload> = z.array(
|
||||
z.discriminatedUnion("type", [
|
||||
z.object({
|
||||
id: z.string(),
|
||||
type: z.literal("fileSizeAtLeast"),
|
||||
params: ZValidationRuleParamsFileSizeAtLeast,
|
||||
customErrorMessage: ZI18nString.optional(),
|
||||
}),
|
||||
z.object({
|
||||
id: z.string(),
|
||||
type: z.literal("fileSizeAtMost"),
|
||||
params: ZValidationRuleParamsFileSizeAtMost,
|
||||
customErrorMessage: ZI18nString.optional(),
|
||||
}),
|
||||
z.object({
|
||||
id: z.string(),
|
||||
type: z.literal("fileExtensionIs"),
|
||||
params: ZValidationRuleParamsFileExtensionIs,
|
||||
customErrorMessage: ZI18nString.optional(),
|
||||
}),
|
||||
z.object({
|
||||
id: z.string(),
|
||||
type: z.literal("fileExtensionIsNot"),
|
||||
params: ZValidationRuleParamsFileExtensionIsNot,
|
||||
customErrorMessage: ZI18nString.optional(),
|
||||
}),
|
||||
])
|
||||
);
|
||||
|
||||
export const ZValidationRulesForPictureSelection: z.ZodType<TValidationRulesForPictureSelection> = z.array(
|
||||
z.discriminatedUnion("type", [
|
||||
z.object({
|
||||
id: z.string(),
|
||||
type: z.literal("minSelections"),
|
||||
params: ZValidationRuleParamsMinSelections,
|
||||
customErrorMessage: ZI18nString.optional(),
|
||||
}),
|
||||
z.object({
|
||||
id: z.string(),
|
||||
type: z.literal("maxSelections"),
|
||||
params: ZValidationRuleParamsMaxSelections,
|
||||
customErrorMessage: ZI18nString.optional(),
|
||||
}),
|
||||
])
|
||||
);
|
||||
|
||||
export const ZValidationRulesForAddress: z.ZodType<TValidationRulesForAddress> = z.array(z.never());
|
||||
|
||||
export const ZValidationRulesForContactInfo: z.ZodType<TValidationRulesForContactInfo> = z.array(z.never());
|
||||
|
||||
export const ZValidationRulesForCal: z.ZodType<TValidationRulesForCal> = z.array(z.never());
|
||||
|
||||
export const ZValidationRulesForCTA: z.ZodType<TValidationRulesForCTA> = z.array(z.never());
|
||||
|
||||
Reference in New Issue
Block a user