@buildnbuzz/buzzform 0.1.0
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/LICENSE +21 -0
- package/README.md +138 -0
- package/dist/adapter-BT9v2OVg.d.mts +1136 -0
- package/dist/adapter-BT9v2OVg.d.ts +1136 -0
- package/dist/chunk-DDDGBPVU.mjs +273 -0
- package/dist/chunk-DDDGBPVU.mjs.map +1 -0
- package/dist/chunk-K42S5YX3.mjs +599 -0
- package/dist/chunk-K42S5YX3.mjs.map +1 -0
- package/dist/index.d.mts +270 -0
- package/dist/index.d.ts +270 -0
- package/dist/index.js +1028 -0
- package/dist/index.js.map +1 -0
- package/dist/index.mjs +194 -0
- package/dist/index.mjs.map +1 -0
- package/dist/rhf.d.mts +70 -0
- package/dist/rhf.d.ts +70 -0
- package/dist/rhf.js +293 -0
- package/dist/rhf.js.map +1 -0
- package/dist/rhf.mjs +175 -0
- package/dist/rhf.mjs.map +1 -0
- package/dist/schema.d.mts +72 -0
- package/dist/schema.d.ts +72 -0
- package/dist/schema.js +768 -0
- package/dist/schema.js.map +1 -0
- package/dist/schema.mjs +63 -0
- package/dist/schema.mjs.map +1 -0
- package/dist/utils-BgwyUFGB.d.mts +233 -0
- package/dist/utils-DVLpbOoW.d.ts +233 -0
- package/dist/zod.d.mts +32 -0
- package/dist/zod.d.ts +32 -0
- package/dist/zod.js +88 -0
- package/dist/zod.js.map +1 -0
- package/dist/zod.mjs +62 -0
- package/dist/zod.mjs.map +1 -0
- package/package.json +109 -0
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"sources":["../src/schema/fields-to-schema.ts","../src/schema/builders/text.ts","../src/schema/helpers.ts","../src/schema/builders/number.ts","../src/schema/builders/date.ts","../src/schema/builders/select.ts","../src/schema/builders/boolean.ts","../src/schema/builders/upload.ts","../src/schema/builders/tags.ts","../src/schema/builders/composite.ts","../src/schema/create-schema.ts"],"sourcesContent":["import { z } from 'zod';\r\nimport type {\r\n Field,\r\n TabsField,\r\n TextField,\r\n EmailField,\r\n PasswordField,\r\n TextareaField,\r\n NumberField,\r\n DateField,\r\n DatetimeField,\r\n SelectField,\r\n RadioField,\r\n CheckboxField,\r\n SwitchField,\r\n UploadField,\r\n TagsField,\r\n ArrayField,\r\n GroupField,\r\n FieldsToShape,\r\n} from '../types';\r\nimport {\r\n createTextFieldSchema,\r\n createEmailFieldSchema,\r\n createPasswordFieldSchema,\r\n createNumberFieldSchema,\r\n createDateFieldSchema,\r\n createSelectFieldSchema,\r\n createRadioFieldSchema,\r\n createCheckboxFieldSchema,\r\n createSwitchFieldSchema,\r\n createUploadFieldSchema,\r\n createTagsFieldSchema,\r\n createArrayFieldSchema,\r\n createGroupFieldSchema,\r\n} from './builders';\r\n\r\n// =============================================================================\r\n// FIELD TO ZOD SCHEMA\r\n// =============================================================================\r\n\r\n/**\r\n * Converts a single field to a Zod schema.\r\n */\r\nfunction fieldToZod(field: Field): z.ZodTypeAny {\r\n // If field has a direct Zod schema override, use it\r\n if ('schema' in field && field.schema) {\r\n return field.schema as z.ZodTypeAny;\r\n }\r\n\r\n switch (field.type) {\r\n // Text-based fields\r\n case 'text':\r\n return createTextFieldSchema(field as TextField);\r\n case 'email':\r\n return createEmailFieldSchema(field as EmailField);\r\n case 'password':\r\n return createPasswordFieldSchema(field as PasswordField);\r\n case 'textarea':\r\n return createTextFieldSchema(field as TextareaField);\r\n\r\n // Number\r\n case 'number':\r\n return createNumberFieldSchema(field as NumberField);\r\n\r\n // Date\r\n case 'date':\r\n case 'datetime':\r\n return createDateFieldSchema(field as DateField | DatetimeField);\r\n\r\n // Selection\r\n case 'select':\r\n return createSelectFieldSchema(field as SelectField);\r\n case 'radio':\r\n return createRadioFieldSchema(field as RadioField);\r\n\r\n // Boolean\r\n case 'checkbox':\r\n return createCheckboxFieldSchema(field as CheckboxField);\r\n case 'switch':\r\n return createSwitchFieldSchema(field as SwitchField);\r\n\r\n // Upload\r\n case 'upload':\r\n return createUploadFieldSchema(field as UploadField);\r\n\r\n // Tags\r\n case 'tags':\r\n return createTagsFieldSchema(field as TagsField);\r\n\r\n // Composite (recursive)\r\n case 'array':\r\n return createArrayFieldSchema(field as ArrayField, fieldsToZodSchema);\r\n case 'group':\r\n return createGroupFieldSchema(field as GroupField, fieldsToZodSchema);\r\n\r\n // Layout fields don't produce schemas directly\r\n case 'row':\r\n case 'collapsible':\r\n case 'tabs':\r\n return z.any();\r\n\r\n default:\r\n return z.any();\r\n }\r\n}\r\n\r\n// =============================================================================\r\n// TABS FIELD HANDLING\r\n// =============================================================================\r\n\r\n/**\r\n * Processes a tabs field to extract schema shape.\r\n * Named tabs create nested objects, unnamed tabs flatten.\r\n */\r\nfunction processTabsField(field: TabsField): Record<string, z.ZodTypeAny> {\r\n const shape: Record<string, z.ZodTypeAny> = {};\r\n\r\n for (const tab of field.tabs) {\r\n if (tab.name) {\r\n // Named tab: create nested object under tab.name\r\n const tabSchema = fieldsToZodSchema(tab.fields);\r\n shape[tab.name] = tabSchema;\r\n } else {\r\n // Unnamed tab: flatten fields into parent shape\r\n const tabFieldsSchema = fieldsToZodSchema(tab.fields);\r\n if (tabFieldsSchema instanceof z.ZodObject) {\r\n Object.assign(shape, tabFieldsSchema.shape);\r\n }\r\n }\r\n }\r\n\r\n return shape;\r\n}\r\n\r\n// =============================================================================\r\n// FIELDS TO ZOD SCHEMA\r\n// =============================================================================\r\n\r\n/**\r\n * Converts an array of field definitions to a Zod object schema.\r\n * Handles all field types including layouts and nested structures.\r\n */\r\nexport function fieldsToZodSchema<T extends readonly Field[]>(\r\n fields: T\r\n): z.ZodObject<FieldsToShape<T>> {\r\n const shape: Record<string, z.ZodTypeAny> = {};\r\n\r\n for (const field of fields) {\r\n if ('name' in field && field.name) {\r\n // Data field with name - add to schema\r\n shape[field.name] = fieldToZod(field);\r\n } else if (field.type === 'tabs') {\r\n // Named tabs create nested, unnamed flatten\r\n const tabsShape = processTabsField(field);\r\n Object.assign(shape, tabsShape);\r\n } else if (field.type === 'row' || field.type === 'collapsible') {\r\n // Layout fields: flatten nested fields into parent\r\n const nestedSchema = fieldsToZodSchema(field.fields);\r\n if (nestedSchema instanceof z.ZodObject) {\r\n Object.assign(shape, nestedSchema.shape);\r\n }\r\n }\r\n // Other layout fields without name are skipped\r\n }\r\n\r\n return z.object(shape) as z.ZodObject<FieldsToShape<T>>;\r\n}\r\n","import { z } from 'zod';\r\nimport type { TextField, EmailField, TextareaField, PasswordField } from '../../types';\r\nimport { makeOptional, getPatternErrorMessage, applyCustomValidation } from '../helpers';\r\n\r\n/**\r\n * Creates Zod schema for text fields.\r\n */\r\nexport function createTextFieldSchema(field: TextField | TextareaField): z.ZodTypeAny {\r\n let schema = z.string();\r\n\r\n // Pattern validation (only for TextField)\r\n if ('pattern' in field && field.pattern) {\r\n const pattern = typeof field.pattern === 'string'\r\n ? new RegExp(field.pattern)\r\n : field.pattern;\r\n\r\n schema = schema.regex(pattern, {\r\n message: getPatternErrorMessage(field.pattern),\r\n });\r\n }\r\n\r\n // Length constraints\r\n if (field.minLength) {\r\n schema = schema.min(field.minLength, {\r\n message: `Must be at least ${field.minLength} characters`,\r\n });\r\n }\r\n if (field.maxLength) {\r\n schema = schema.max(field.maxLength, {\r\n message: `Must be no more than ${field.maxLength} characters`,\r\n });\r\n }\r\n\r\n // Required (for strings, use min(1) instead of just required)\r\n if (field.required) {\r\n schema = schema.min(1, { message: 'This field is required' });\r\n }\r\n\r\n // Trim preprocessing (only for TextField)\r\n let finalSchema: z.ZodTypeAny = schema;\r\n if ('trim' in field && field.trim) {\r\n finalSchema = z.preprocess((val) => {\r\n return typeof val === 'string' ? val.trim() : val;\r\n }, schema);\r\n }\r\n\r\n // Apply custom validation\r\n finalSchema = applyCustomValidation(finalSchema, field, field.name);\r\n\r\n // Return optional if not required\r\n if (!field.required) {\r\n return makeOptional(finalSchema, field.type);\r\n }\r\n\r\n return finalSchema;\r\n}\r\n\r\n/**\r\n * Creates Zod schema for email fields.\r\n */\r\nexport function createEmailFieldSchema(field: EmailField): z.ZodTypeAny {\r\n let schema = z.string().email({ message: 'Invalid email address' });\r\n\r\n // Length constraints (rare for email but supported)\r\n if (field.minLength) {\r\n schema = schema.min(field.minLength, {\r\n message: `Must be at least ${field.minLength} characters`,\r\n });\r\n }\r\n if (field.maxLength) {\r\n schema = schema.max(field.maxLength, {\r\n message: `Must be no more than ${field.maxLength} characters`,\r\n });\r\n }\r\n\r\n // Required\r\n if (field.required) {\r\n schema = schema.min(1, { message: 'Email is required' });\r\n }\r\n\r\n // Apply custom validation\r\n const finalSchema: z.ZodTypeAny = applyCustomValidation(schema, field, field.name);\r\n\r\n if (!field.required) {\r\n return makeOptional(finalSchema, 'email');\r\n }\r\n\r\n return finalSchema;\r\n}\r\n\r\n/**\r\n * Creates Zod schema for password fields.\r\n */\r\nexport function createPasswordFieldSchema(field: PasswordField): z.ZodTypeAny {\r\n let schema = z.string();\r\n\r\n if (field.minLength) {\r\n schema = schema.min(field.minLength, {\r\n message: `Password must be at least ${field.minLength} characters`,\r\n });\r\n }\r\n if (field.maxLength) {\r\n schema = schema.max(field.maxLength, {\r\n message: `Password must be no more than ${field.maxLength} characters`,\r\n });\r\n }\r\n if (field.required) {\r\n schema = schema.min(1, { message: 'Password is required' });\r\n }\r\n\r\n const finalSchema: z.ZodTypeAny = applyCustomValidation(schema, field, field.name);\r\n\r\n if (!field.required) {\r\n return makeOptional(finalSchema, 'password');\r\n }\r\n\r\n return finalSchema;\r\n}\r\n","import { z } from 'zod';\r\nimport type { Field, FieldType, ValidationContext } from '../types';\r\n\r\n// =============================================================================\r\n// VALIDATION CONFIG EXTRACTION\r\n// =============================================================================\r\n\r\n/**\r\n * A validation function that can be extracted from a field.\r\n */\r\ntype ExtractableValidationFn = (\r\n value: unknown,\r\n context: ValidationContext\r\n) => true | string | Promise<true | string>;\r\n\r\nexport interface ExtractedValidationConfig {\r\n /** The validation function (if any) */\r\n fn?: ExtractableValidationFn;\r\n /** Whether this is a live validation */\r\n isLive: boolean;\r\n /** Debounce milliseconds for live validation */\r\n debounceMs?: number;\r\n}\r\n\r\n/**\r\n * Extracts validation function and config from the unified validate property.\r\n */\r\nexport function extractValidationConfig(\r\n validate?: unknown\r\n): ExtractedValidationConfig {\r\n if (!validate) {\r\n return { fn: undefined, isLive: false };\r\n }\r\n\r\n // Simple function case\r\n if (typeof validate === 'function') {\r\n return { fn: validate as ExtractableValidationFn, isLive: false };\r\n }\r\n\r\n // Object case with potential live config\r\n if (typeof validate === 'object' && 'fn' in validate) {\r\n const obj = validate as { fn?: unknown; live?: boolean | { debounceMs?: number } };\r\n const fn = typeof obj.fn === 'function' ? obj.fn as ExtractableValidationFn : undefined;\r\n\r\n if (!obj.live) {\r\n return { fn, isLive: false };\r\n }\r\n\r\n const debounceMs = typeof obj.live === 'object' ? obj.live.debounceMs : undefined;\r\n return { fn, isLive: true, debounceMs };\r\n }\r\n\r\n return { fn: undefined, isLive: false };\r\n}\r\n\r\n// =============================================================================\r\n// CUSTOM VALIDATION WRAPPER\r\n// =============================================================================\r\n\r\n/**\r\n * Applies custom validation from field.validate to a Zod schema.\r\n * Standardizes the pattern across all field types.\r\n */\r\nexport function applyCustomValidation(\r\n schema: z.ZodTypeAny,\r\n field: Field,\r\n fieldPath: string = ''\r\n): z.ZodTypeAny {\r\n // Only data fields have validate\r\n if (!('validate' in field)) {\r\n return schema;\r\n }\r\n\r\n const fieldWithValidate = field as { validate?: unknown };\r\n if (!fieldWithValidate.validate) {\r\n return schema;\r\n }\r\n\r\n const config = extractValidationConfig(fieldWithValidate.validate);\r\n if (!config.fn) {\r\n return schema;\r\n }\r\n\r\n return schema.superRefine(async (val, ctx) => {\r\n const result = await config.fn!(val, {\r\n data: {},\r\n siblingData: {},\r\n path: fieldPath.split('.'),\r\n });\r\n\r\n if (result !== true) {\r\n ctx.addIssue({\r\n code: z.ZodIssueCode.custom,\r\n message: typeof result === 'string' ? result : 'Validation failed',\r\n });\r\n }\r\n });\r\n}\r\n\r\n// =============================================================================\r\n// OPTIONAL HANDLING\r\n// =============================================================================\r\n\r\n/**\r\n * Makes a schema optional based on field type.\r\n * Different field types have different \"empty\" representations.\r\n */\r\nexport function makeOptional(\r\n schema: z.ZodTypeAny,\r\n fieldType: FieldType\r\n): z.ZodTypeAny {\r\n switch (fieldType) {\r\n // String types: allow empty string\r\n case 'text':\r\n case 'textarea':\r\n case 'email':\r\n case 'password':\r\n return schema.optional().or(z.literal(''));\r\n\r\n // Nullable types\r\n case 'number':\r\n case 'date':\r\n case 'select':\r\n case 'radio':\r\n return schema.optional().nullable();\r\n\r\n // Boolean types: always have a value\r\n case 'checkbox':\r\n case 'switch':\r\n return schema; // Booleans are never \"optional\" in the traditional sense\r\n\r\n // Array types\r\n case 'tags':\r\n case 'array':\r\n return schema.optional().default([]);\r\n\r\n // Upload\r\n case 'upload':\r\n return schema.optional().nullable();\r\n\r\n // Default\r\n default:\r\n return schema.optional();\r\n }\r\n}\r\n\r\n// =============================================================================\r\n// COERCION HELPERS\r\n// =============================================================================\r\n\r\n/**\r\n * Coerces a value to a number.\r\n * Empty/null/undefined → undefined, otherwise Number().\r\n */\r\nexport function coerceToNumber(val: unknown): number | undefined {\r\n if (val === '' || val === null || val === undefined) {\r\n return undefined;\r\n }\r\n const num = Number(val);\r\n return isNaN(num) ? undefined : num;\r\n}\r\n\r\n/**\r\n * Coerces a value to a Date.\r\n * Handles strings, numbers, and Date objects.\r\n */\r\nexport function coerceToDate(val: unknown): Date | undefined {\r\n if (val === '' || val === null || val === undefined) {\r\n return undefined;\r\n }\r\n if (val instanceof Date) {\r\n return isNaN(val.getTime()) ? undefined : val;\r\n }\r\n if (typeof val === 'string' || typeof val === 'number') {\r\n const d = new Date(val);\r\n return isNaN(d.getTime()) ? undefined : d;\r\n }\r\n return undefined;\r\n}\r\n\r\n// =============================================================================\r\n// PATTERN VALIDATION\r\n// =============================================================================\r\n\r\n/**\r\n * Common regex patterns with their error messages.\r\n */\r\nconst PATTERN_MESSAGES: Record<string, string> = {\r\n '^[a-zA-Z0-9_]+$': 'Only letters, numbers, and underscores allowed',\r\n '^[a-z0-9-]+$': 'Only lowercase letters, numbers, and hyphens allowed',\r\n '^\\\\S+@\\\\S+\\\\.\\\\S+$': 'Invalid email format',\r\n '^https?://': 'Must start with http:// or https://',\r\n};\r\n\r\n/**\r\n * Gets a human-readable error message for a regex pattern.\r\n */\r\nexport function getPatternErrorMessage(pattern: string | RegExp): string {\r\n const patternStr = typeof pattern === 'string' ? pattern : pattern.source;\r\n return PATTERN_MESSAGES[patternStr] || `Must match pattern: ${patternStr}`;\r\n}\r\n\r\n// =============================================================================\r\n// FILE VALIDATION HELPERS\r\n// =============================================================================\r\n\r\n/**\r\n * Checks if a value is a File-like object.\r\n */\r\nexport function isFileLike(value: unknown): value is File {\r\n return (\r\n typeof value === 'object' &&\r\n value !== null &&\r\n 'name' in value &&\r\n 'size' in value &&\r\n 'type' in value\r\n );\r\n}\r\n\r\n/**\r\n * Validates file type against accept pattern.\r\n */\r\nexport function isFileTypeAccepted(\r\n file: File,\r\n accept: string\r\n): boolean {\r\n if (accept === '*' || !accept) return true;\r\n\r\n const acceptTypes = accept.split(',').map(t => t.trim().toLowerCase());\r\n const fileType = file.type.toLowerCase();\r\n const fileName = file.name.toLowerCase();\r\n\r\n return acceptTypes.some(acceptType => {\r\n // Wildcard: \"image/*\"\r\n if (acceptType.endsWith('/*')) {\r\n const category = acceptType.replace('/*', '');\r\n return fileType.startsWith(category + '/');\r\n }\r\n // Extension: \".pdf\"\r\n if (acceptType.startsWith('.')) {\r\n return fileName.endsWith(acceptType);\r\n }\r\n // Exact MIME type\r\n return fileType === acceptType;\r\n });\r\n}\r\n","import { z } from 'zod';\r\nimport type { NumberField } from '../../types';\r\nimport { coerceToNumber, makeOptional, applyCustomValidation } from '../helpers';\r\n\r\n/**\r\n * Creates Zod schema for number fields.\r\n */\r\nexport function createNumberFieldSchema(field: NumberField): z.ZodTypeAny {\r\n let numSchema = z.number({ invalid_type_error: 'Must be a number' });\r\n\r\n // Min/max constraints\r\n if (field.min !== undefined) {\r\n numSchema = numSchema.min(field.min, `Must be at least ${field.min}`);\r\n }\r\n if (field.max !== undefined) {\r\n numSchema = numSchema.max(field.max, `Must be at most ${field.max}`);\r\n }\r\n\r\n // Coercion: empty/null/undefined → undefined, otherwise Number()\r\n let schema: z.ZodTypeAny = z.preprocess(coerceToNumber, numSchema);\r\n\r\n // Apply custom validation\r\n schema = applyCustomValidation(schema, field, field.name);\r\n\r\n if (field.required) {\r\n return schema;\r\n }\r\n\r\n return makeOptional(schema, 'number');\r\n}\r\n","import { z } from 'zod';\r\nimport type { DateField, DatetimeField } from '../../types';\r\nimport { coerceToDate, makeOptional, applyCustomValidation } from '../helpers';\r\n\r\n/**\r\n * Parse a value to a Date object for constraint checking.\r\n */\r\nfunction toDate(value?: string | Date): Date | undefined {\r\n if (!value) return undefined;\r\n if (value instanceof Date) return isNaN(value.getTime()) ? undefined : value;\r\n const parsed = new Date(value);\r\n return isNaN(parsed.getTime()) ? undefined : parsed;\r\n}\r\n\r\n/**\r\n * Creates Zod schema for date and datetime fields.\r\n */\r\nexport function createDateFieldSchema(field: DateField | DatetimeField): z.ZodTypeAny {\r\n const isDatetime = field.type === 'datetime';\r\n\r\n // Parse min/max dates from field config\r\n const minDate = toDate(field.minDate);\r\n const maxDate = toDate(field.maxDate);\r\n\r\n // Build base date schema\r\n let dateSchema = z.date({ invalid_type_error: 'Please enter a valid date' });\r\n\r\n // Add min date constraint\r\n if (minDate) {\r\n const formattedDate = isDatetime ? minDate.toLocaleString() : minDate.toDateString();\r\n dateSchema = dateSchema.min(minDate, {\r\n message: `Date must be on or after ${formattedDate}`,\r\n });\r\n }\r\n\r\n // Add max date constraint\r\n if (maxDate) {\r\n const formattedDate = isDatetime ? maxDate.toLocaleString() : maxDate.toDateString();\r\n dateSchema = dateSchema.max(maxDate, {\r\n message: `Date must be on or before ${formattedDate}`,\r\n });\r\n }\r\n\r\n // Coercion from various input types\r\n let schema: z.ZodTypeAny = z.preprocess(coerceToDate, dateSchema);\r\n\r\n // Apply custom validation\r\n schema = applyCustomValidation(schema, field, field.name);\r\n\r\n if (field.required) {\r\n return schema.refine(\r\n (val) => val instanceof Date && !isNaN(val.getTime()),\r\n 'Date is required'\r\n );\r\n }\r\n\r\n return makeOptional(schema, 'date');\r\n}\r\n","import { z } from 'zod';\r\nimport type { SelectField, RadioField } from '../../types';\r\nimport { makeOptional, applyCustomValidation } from '../helpers';\r\n\r\n/**\r\n * Base schema for select/radio values.\r\n * Supports string, number, and boolean as per SelectOption.value type.\r\n */\r\nconst selectValueSchema = z.union([z.string(), z.number(), z.boolean()]);\r\n\r\n/**\r\n * Creates Zod schema for select fields.\r\n */\r\nexport function createSelectFieldSchema(field: SelectField): z.ZodTypeAny {\r\n // Handle hasMany (multi-select)\r\n if (field.hasMany) {\r\n let arraySchema = z.array(selectValueSchema);\r\n\r\n if (field.required) {\r\n arraySchema = arraySchema.min(1, 'Select at least one option');\r\n }\r\n\r\n const schema: z.ZodTypeAny = applyCustomValidation(arraySchema, field, field.name);\r\n\r\n if (!field.required) {\r\n return schema.optional().default([]);\r\n }\r\n return schema;\r\n }\r\n\r\n // Single select\r\n let schema: z.ZodTypeAny = selectValueSchema;\r\n\r\n if (field.required) {\r\n // For required fields, we need to ensure a value was selected\r\n schema = selectValueSchema.refine(\r\n (val) => val !== '' && val !== null && val !== undefined,\r\n 'Please select an option'\r\n );\r\n }\r\n\r\n schema = applyCustomValidation(schema, field, field.name);\r\n\r\n if (!field.required) {\r\n return makeOptional(schema, 'select');\r\n }\r\n\r\n return schema;\r\n}\r\n\r\n/**\r\n * Creates Zod schema for radio fields.\r\n */\r\nexport function createRadioFieldSchema(field: RadioField): z.ZodTypeAny {\r\n let schema: z.ZodTypeAny = selectValueSchema;\r\n\r\n if (field.required) {\r\n schema = selectValueSchema.refine(\r\n (val) => val !== '' && val !== null && val !== undefined,\r\n 'Please select an option'\r\n );\r\n }\r\n\r\n schema = applyCustomValidation(schema, field, field.name);\r\n\r\n if (!field.required) {\r\n return makeOptional(schema, 'radio');\r\n }\r\n\r\n return schema;\r\n}\r\n","import { z } from 'zod';\r\nimport type { CheckboxField, SwitchField } from '../../types';\r\nimport { applyCustomValidation } from '../helpers';\r\n\r\n/**\r\n * Creates Zod schema for checkbox fields.\r\n */\r\nexport function createCheckboxFieldSchema(field: CheckboxField): z.ZodTypeAny {\r\n let schema: z.ZodTypeAny = z.boolean();\r\n\r\n // Required checkbox must be checked\r\n if (field.required) {\r\n schema = z.boolean().refine(val => val === true, {\r\n message: 'This field is required',\r\n });\r\n }\r\n\r\n return applyCustomValidation(schema, field, field.name);\r\n}\r\n\r\n/**\r\n * Creates Zod schema for switch fields.\r\n */\r\nexport function createSwitchFieldSchema(field: SwitchField): z.ZodTypeAny {\r\n let schema: z.ZodTypeAny = z.boolean();\r\n\r\n // Required switch must be on\r\n if (field.required) {\r\n schema = z.boolean().refine(val => val === true, {\r\n message: 'This field is required',\r\n });\r\n }\r\n\r\n return applyCustomValidation(schema, field, field.name);\r\n}\r\n","import { z } from 'zod';\r\nimport type { UploadField } from '../../types';\r\nimport { isFileLike, isFileTypeAccepted } from '../helpers';\r\n\r\n/**\r\n * Validates a single file against field constraints.\r\n */\r\nfunction validateSingleFile(\r\n value: unknown,\r\n field: UploadField\r\n): { valid: boolean; message?: string } {\r\n // Allow null/undefined for non-required fields\r\n if (value === null || value === undefined || value === '') {\r\n return { valid: true };\r\n }\r\n\r\n // Allow string URLs (for existing uploads)\r\n if (typeof value === 'string') {\r\n return { valid: true };\r\n }\r\n\r\n // Must be a File-like object\r\n if (!isFileLike(value)) {\r\n return { valid: false, message: 'Invalid file' };\r\n }\r\n\r\n // Validate max size\r\n if (field.maxSize && value.size > field.maxSize) {\r\n const sizeMB = (field.maxSize / 1024 / 1024).toFixed(1);\r\n return {\r\n valid: false,\r\n message: `File must be smaller than ${sizeMB}MB`,\r\n };\r\n }\r\n\r\n // Validate file type (accept attribute)\r\n const accept = field.ui?.accept;\r\n if (accept && accept !== '*') {\r\n if (!isFileTypeAccepted(value, accept)) {\r\n return {\r\n valid: false,\r\n message: `File type not allowed. Accepted: ${accept}`,\r\n };\r\n }\r\n }\r\n\r\n return { valid: true };\r\n}\r\n\r\n/**\r\n * Creates Zod schema for upload fields.\r\n * Supports both single file and hasMany (array) modes.\r\n */\r\nexport function createUploadFieldSchema(field: UploadField): z.ZodTypeAny {\r\n if (field.hasMany) {\r\n // Array mode\r\n const schema = z.array(z.any()).superRefine((files, ctx) => {\r\n // Validate each file\r\n for (let i = 0; i < files.length; i++) {\r\n const file = files[i];\r\n const result = validateSingleFile(file, field);\r\n if (!result.valid) {\r\n ctx.addIssue({\r\n code: z.ZodIssueCode.custom,\r\n message: result.message || 'Invalid file',\r\n path: [i],\r\n });\r\n }\r\n }\r\n\r\n // Validate required\r\n if (field.required) {\r\n const validFiles = files.filter(f => f !== null && f !== undefined);\r\n if (validFiles.length === 0) {\r\n ctx.addIssue({\r\n code: z.ZodIssueCode.custom,\r\n message: 'At least one file is required',\r\n });\r\n }\r\n }\r\n\r\n // Validate minFiles\r\n if (field.minFiles !== undefined && field.minFiles > 0) {\r\n const validFiles = files.filter(f => f !== null && f !== undefined);\r\n if (validFiles.length < field.minFiles) {\r\n ctx.addIssue({\r\n code: z.ZodIssueCode.custom,\r\n message: `At least ${field.minFiles} file(s) required`,\r\n });\r\n }\r\n }\r\n\r\n // Validate maxFiles\r\n if (field.maxFiles !== undefined) {\r\n const validFiles = files.filter(f => f !== null && f !== undefined);\r\n if (validFiles.length > field.maxFiles) {\r\n ctx.addIssue({\r\n code: z.ZodIssueCode.custom,\r\n message: `Maximum ${field.maxFiles} file(s) allowed`,\r\n });\r\n }\r\n }\r\n });\r\n\r\n if (!field.required) {\r\n return schema.optional().default([]);\r\n }\r\n return schema;\r\n }\r\n\r\n // Single file mode\r\n const schema = z.any().superRefine((value, ctx) => {\r\n // Handle required\r\n if (field.required && (value === null || value === undefined || value === '')) {\r\n ctx.addIssue({\r\n code: z.ZodIssueCode.custom,\r\n message: 'File is required',\r\n });\r\n return;\r\n }\r\n\r\n // Skip further validation for empty non-required values\r\n if (value === null || value === undefined || value === '') {\r\n return;\r\n }\r\n\r\n const result = validateSingleFile(value, field);\r\n if (!result.valid) {\r\n ctx.addIssue({\r\n code: z.ZodIssueCode.custom,\r\n message: result.message || 'Invalid file',\r\n });\r\n }\r\n });\r\n\r\n if (!field.required) {\r\n return schema.optional().nullable();\r\n }\r\n\r\n return schema;\r\n}\r\n","import { z } from 'zod';\r\nimport type { TagsField } from '../../types';\r\nimport { applyCustomValidation } from '../helpers';\r\n\r\n/**\r\n * Creates Zod schema for tags fields.\r\n * Tags are always arrays of strings.\r\n */\r\nexport function createTagsFieldSchema(field: TagsField): z.ZodTypeAny {\r\n const tagSchema = z.string();\r\n let schema = z.array(tagSchema);\r\n\r\n // Min/max constraints (TagsField uses minTags/maxTags)\r\n if (field.minTags !== undefined) {\r\n schema = schema.min(field.minTags, `At least ${field.minTags} tag(s) required`);\r\n }\r\n if (field.maxTags !== undefined) {\r\n schema = schema.max(field.maxTags, `Maximum ${field.maxTags} tag(s) allowed`);\r\n }\r\n\r\n // Apply custom validation\r\n let finalSchema: z.ZodTypeAny = applyCustomValidation(schema, field, field.name);\r\n\r\n // Required: must have at least one tag\r\n if (field.required) {\r\n finalSchema = finalSchema.refine(\r\n (arr) => Array.isArray(arr) && arr.length > 0,\r\n 'At least one tag is required'\r\n );\r\n return finalSchema;\r\n }\r\n\r\n // Optional: default to empty array\r\n return finalSchema.optional().default([]);\r\n}\r\n","import { z } from 'zod';\r\nimport type { ArrayField, GroupField, Field } from '../../types';\r\n\r\n// Note: These import from the parent module to avoid circular deps\r\n// The fieldsToZodSchema function is passed as a parameter\r\n\r\ntype SchemaGenerator = (fields: readonly Field[]) => z.ZodObject<z.ZodRawShape>;\r\n\r\n/**\r\n * Creates Zod schema for array fields.\r\n * Uses passed-in schema generator to handle nested fields.\r\n */\r\nexport function createArrayFieldSchema(\r\n field: ArrayField,\r\n fieldsToZodSchema: SchemaGenerator\r\n): z.ZodTypeAny {\r\n const itemSchema = fieldsToZodSchema(field.fields);\r\n let schema = z.array(itemSchema);\r\n\r\n if (field.minRows !== undefined) {\r\n schema = schema.min(\r\n field.minRows,\r\n `At least ${field.minRows} row${field.minRows !== 1 ? 's' : ''} required`\r\n );\r\n }\r\n if (field.maxRows !== undefined) {\r\n schema = schema.max(\r\n field.maxRows,\r\n `Maximum ${field.maxRows} row${field.maxRows !== 1 ? 's' : ''} allowed`\r\n );\r\n }\r\n\r\n if (field.required) {\r\n return schema;\r\n }\r\n\r\n return schema.optional().default([]);\r\n}\r\n\r\n/**\r\n * Creates Zod schema for group fields.\r\n * Uses passed-in schema generator to handle nested fields.\r\n */\r\nexport function createGroupFieldSchema(\r\n field: GroupField,\r\n fieldsToZodSchema: SchemaGenerator\r\n): z.ZodTypeAny {\r\n const schema = fieldsToZodSchema(field.fields);\r\n\r\n if (!field.required) {\r\n return schema.optional();\r\n }\r\n\r\n return schema;\r\n}","import { type z } from 'zod';\r\nimport type { Field, FieldsToShape } from '../types';\r\nimport { fieldsToZodSchema } from './fields-to-schema';\r\n\r\n// =============================================================================\r\n// CREATE SCHEMA\r\n// =============================================================================\r\n\r\n/**\r\n * Creates a Zod schema from an array of field definitions.\r\n *\r\n * Provides full intellisense when writing field definitions inline.\r\n * The returned schema has `.fields` attached for use in rendering.\r\n *\r\n * @example\r\n * const loginSchema = createSchema([\r\n * { type: 'email', name: 'email', required: true }, // ← Full intellisense!\r\n * { type: 'password', name: 'password', minLength: 8 },\r\n * ]);\r\n *\r\n * type LoginData = z.infer<typeof loginSchema>;\r\n * // { email: string; password: string }\r\n *\r\n * // Use with useForm:\r\n * const form = useForm({ schema: loginSchema });\r\n *\r\n * // Access fields for rendering:\r\n * <FormRenderer fields={loginSchema.fields} />\r\n */\r\nexport function createSchema<const T extends readonly Field[]>(\r\n fields: [...{ [K in keyof T]: T[K] extends Field ? T[K] : Field }]\r\n): z.ZodObject<FieldsToShape<T>> & { fields: T } {\r\n const schema = fieldsToZodSchema(fields as T);\r\n\r\n // Attach fields to schema for rendering access\r\n return Object.assign(schema, { fields }) as z.ZodObject<FieldsToShape<T>> & { fields: T };\r\n}\r\n"],"mappings":"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","names":["z","z","z","z","z","z","z","z","z","schema","z","z","z","schema","z","z","z","z","fieldsToZodSchema","z"]}
|
package/dist/index.d.mts
ADDED
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
import { F as Field, a as FormConfig, U as UseFormOptions, b as FormAdapter } from './adapter-BT9v2OVg.mjs';
|
|
2
|
+
export { g as AdapterFactory, f as AdapterOptions, y as ArrayField, A as ArrayHelpers, B as BaseField, O as BuzzFormSchema, s as CheckboxField, J as CollapsibleField, C as ConditionContext, L as DataField, D as DateField, p as DatetimeField, E as EmailField, k as FieldComponentProps, j as FieldCondition, d as FieldError, l as FieldInputProps, m as FieldInputRenderFn, n as FieldStyle, K as FieldType, Q as FormSettings, c as FormState, G as GroupField, M as LayoutField, N as NumberField, P as PasswordField, u as RadioField, e as Resolver, R as ResolverResult, z as RowField, r as SelectField, q as SelectOption, S as SetValueOptions, t as SwitchField, H as Tab, I as TabsField, w as TagsField, T as TextField, o as TextareaField, x as UploadField, V as ValidationContext, i as ValidationFn, h as ValidationResult, v as validateAdapter } from './adapter-BT9v2OVg.mjs';
|
|
3
|
+
export { F as FieldToZod, a as FieldsToShape, I as InferSchema, S as SchemaBuilder, b as SchemaBuilderMap, d as applyCustomValidation, h as coerceToDate, g as coerceToNumber, l as createArrayHelpers, c as createSchema, e as extractValidationConfig, f as fieldsToZodSchema, p as formatBytes, n as generateFieldId, o as getNestedValue, i as getPatternErrorMessage, j as isFileLike, k as isFileTypeAccepted, m as makeOptional, s as setNestedValue } from './utils-BgwyUFGB.mjs';
|
|
4
|
+
import * as React from 'react';
|
|
5
|
+
import React__default, { ReactNode } from 'react';
|
|
6
|
+
import 'zod';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Recursively extracts all field paths from a field definition tree.
|
|
10
|
+
* Handles nested groups, arrays, and layout fields (rows, tabs, collapsibles).
|
|
11
|
+
*
|
|
12
|
+
* @param fields - Array of field definitions
|
|
13
|
+
* @param basePath - Base path prefix (e.g., "contacts.0" for array items)
|
|
14
|
+
* @returns Array of all field paths
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* const fields = [
|
|
18
|
+
* { type: 'text', name: 'name' },
|
|
19
|
+
* { type: 'group', name: 'address', fields: [
|
|
20
|
+
* { type: 'text', name: 'city' },
|
|
21
|
+
* { type: 'text', name: 'zip' }
|
|
22
|
+
* ]}
|
|
23
|
+
* ];
|
|
24
|
+
* getNestedFieldPaths(fields, 'contact')
|
|
25
|
+
* // => ['contact.name', 'contact.address', 'contact.address.city', 'contact.address.zip']
|
|
26
|
+
*/
|
|
27
|
+
declare function getNestedFieldPaths(fields: Field[], basePath: string): string[];
|
|
28
|
+
/**
|
|
29
|
+
* Count validation errors in nested fields.
|
|
30
|
+
* Useful for showing error badges on collapsible sections, array rows, tabs, etc.
|
|
31
|
+
*
|
|
32
|
+
* @param errors - Form errors object from FormAdapter.formState.errors
|
|
33
|
+
* @param fields - Field definitions to check
|
|
34
|
+
* @param basePath - Base path for the fields
|
|
35
|
+
* @returns Number of fields with errors
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* const errorCount = countNestedErrors(form.formState.errors, arrayField.fields, `items.0`);
|
|
39
|
+
*/
|
|
40
|
+
declare function countNestedErrors(errors: Record<string, unknown>, fields: Field[], basePath: string): number;
|
|
41
|
+
/**
|
|
42
|
+
* Resolve a potentially dynamic field property (disabled, readOnly, hidden).
|
|
43
|
+
* These properties can be boolean or a function that receives form data.
|
|
44
|
+
*
|
|
45
|
+
* @param value - The property value (boolean or function)
|
|
46
|
+
* @param formData - Current form data
|
|
47
|
+
* @param siblingData - Data at the same level (for arrays, this is the row data)
|
|
48
|
+
* @returns Resolved boolean value
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* const isDisabled = resolveFieldState(field.disabled, formData, siblingData);
|
|
52
|
+
*/
|
|
53
|
+
declare function resolveFieldState<TData = Record<string, unknown>>(value: boolean | ((data: TData, siblingData: Record<string, unknown>) => boolean) | undefined, formData: TData, siblingData?: Record<string, unknown>): boolean;
|
|
54
|
+
/**
|
|
55
|
+
* Get the label value for an array row based on field configuration.
|
|
56
|
+
* First checks for a specific rowLabelField in ui options, then falls back
|
|
57
|
+
* to the first named field's value.
|
|
58
|
+
*
|
|
59
|
+
* @param rowData - Data for the row
|
|
60
|
+
* @param fields - Field definitions for the array
|
|
61
|
+
* @param uiOptions - UI options that may contain rowLabelField
|
|
62
|
+
* @param fallbackLabel - Default label if no value found
|
|
63
|
+
* @returns Label string for the row
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* const label = getArrayRowLabel(rowData, field.fields, field.ui, `Item ${index + 1}`);
|
|
67
|
+
*/
|
|
68
|
+
declare function getArrayRowLabel(rowData: Record<string, unknown> | undefined, fields: Field[], uiOptions: {
|
|
69
|
+
rowLabelField?: string;
|
|
70
|
+
} | undefined, fallbackLabel: string): string;
|
|
71
|
+
/**
|
|
72
|
+
* Compute the inline style object for a field's width.
|
|
73
|
+
* Handles both numeric (px) and string (CSS) width values.
|
|
74
|
+
*
|
|
75
|
+
* @param style - Field style configuration
|
|
76
|
+
* @returns CSS properties object or undefined if no width specified
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* <Field style={getFieldWidthStyle(field.style)}>
|
|
80
|
+
* ...
|
|
81
|
+
* </Field>
|
|
82
|
+
*/
|
|
83
|
+
declare function getFieldWidthStyle(style: {
|
|
84
|
+
width?: number | string;
|
|
85
|
+
} | undefined): {
|
|
86
|
+
width: string;
|
|
87
|
+
} | undefined;
|
|
88
|
+
type SelectOptionLike = {
|
|
89
|
+
value: string | number | boolean;
|
|
90
|
+
label?: ReactNode;
|
|
91
|
+
description?: ReactNode;
|
|
92
|
+
icon?: ReactNode;
|
|
93
|
+
disabled?: boolean;
|
|
94
|
+
} | string;
|
|
95
|
+
/**
|
|
96
|
+
* Normalize a select option to always be an object.
|
|
97
|
+
* Converts string options to { value, label } objects.
|
|
98
|
+
*
|
|
99
|
+
* @param option - String or SelectOption object
|
|
100
|
+
* @returns Normalized SelectOption object
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* normalizeSelectOption('foo') // => { value: 'foo', label: 'foo' }
|
|
104
|
+
* normalizeSelectOption({ value: 'bar', label: 'Bar' }) // => { value: 'bar', label: 'Bar' }
|
|
105
|
+
*/
|
|
106
|
+
declare function normalizeSelectOption(option: SelectOptionLike): {
|
|
107
|
+
value: string | number | boolean;
|
|
108
|
+
label: ReactNode;
|
|
109
|
+
description?: ReactNode;
|
|
110
|
+
icon?: ReactNode;
|
|
111
|
+
disabled?: boolean;
|
|
112
|
+
};
|
|
113
|
+
/**
|
|
114
|
+
* Get the value from a select option (handles string or object).
|
|
115
|
+
*
|
|
116
|
+
* @param option - String or SelectOption object
|
|
117
|
+
* @returns The option's value as a string
|
|
118
|
+
*
|
|
119
|
+
* @example
|
|
120
|
+
* getSelectOptionValue('foo') // => 'foo'
|
|
121
|
+
* getSelectOptionValue({ value: 123, label: 'One Two Three' }) // => '123'
|
|
122
|
+
*/
|
|
123
|
+
declare function getSelectOptionValue(option: SelectOptionLike): string;
|
|
124
|
+
/**
|
|
125
|
+
* Get the label from a select option (handles string or object).
|
|
126
|
+
* Returns ReactNode to support JSX labels.
|
|
127
|
+
*
|
|
128
|
+
* @param option - String or SelectOption object
|
|
129
|
+
* @returns The option's label for display
|
|
130
|
+
*
|
|
131
|
+
* @example
|
|
132
|
+
* getSelectOptionLabel('foo') // => 'foo'
|
|
133
|
+
* getSelectOptionLabel({ value: 'bar', label: <strong>Bar</strong> }) // => <strong>Bar</strong>
|
|
134
|
+
*/
|
|
135
|
+
declare function getSelectOptionLabel(option: SelectOptionLike): ReactNode;
|
|
136
|
+
/**
|
|
137
|
+
* Get the string label from a select option (for filtering/comparison).
|
|
138
|
+
* Always returns a string, not ReactNode.
|
|
139
|
+
*
|
|
140
|
+
* @param option - String or SelectOption object
|
|
141
|
+
* @returns The option's label as a string
|
|
142
|
+
*/
|
|
143
|
+
declare function getSelectOptionLabelString(option: SelectOptionLike): string;
|
|
144
|
+
/**
|
|
145
|
+
* Check if a select option is disabled.
|
|
146
|
+
*
|
|
147
|
+
* @param option - String or SelectOption object
|
|
148
|
+
* @returns true if option is disabled
|
|
149
|
+
*/
|
|
150
|
+
declare function isSelectOptionDisabled(option: SelectOptionLike): boolean;
|
|
151
|
+
/**
|
|
152
|
+
* Clamp a number between min and max bounds.
|
|
153
|
+
*
|
|
154
|
+
* @param value - The number to clamp
|
|
155
|
+
* @param min - Minimum bound (optional)
|
|
156
|
+
* @param max - Maximum bound (optional)
|
|
157
|
+
* @returns Clamped number
|
|
158
|
+
*
|
|
159
|
+
* @example
|
|
160
|
+
* clampNumber(5, 0, 10) // => 5
|
|
161
|
+
* clampNumber(-5, 0, 10) // => 0
|
|
162
|
+
* clampNumber(15, 0, 10) // => 10
|
|
163
|
+
*/
|
|
164
|
+
declare function clampNumber(value: number, min?: number, max?: number): number;
|
|
165
|
+
/**
|
|
166
|
+
* Apply numeric precision (decimal places) to a number.
|
|
167
|
+
*
|
|
168
|
+
* @param value - The number to format
|
|
169
|
+
* @param precision - Number of decimal places
|
|
170
|
+
* @returns Formatted number or undefined if input is undefined
|
|
171
|
+
*
|
|
172
|
+
* @example
|
|
173
|
+
* applyNumericPrecision(3.14159, 2) // => 3.14
|
|
174
|
+
* applyNumericPrecision(10, 2) // => 10
|
|
175
|
+
*/
|
|
176
|
+
declare function applyNumericPrecision(value: number | undefined, precision?: number): number | undefined;
|
|
177
|
+
/**
|
|
178
|
+
* Format a number with thousand separators.
|
|
179
|
+
*
|
|
180
|
+
* @param value - The number to format
|
|
181
|
+
* @param separator - Separator character (default: ',')
|
|
182
|
+
* @returns Formatted string or empty string if value is undefined/NaN
|
|
183
|
+
*
|
|
184
|
+
* @example
|
|
185
|
+
* formatNumberWithSeparator(1234567.89) // => '1,234,567.89'
|
|
186
|
+
* formatNumberWithSeparator(1234567, ' ') // => '1 234 567'
|
|
187
|
+
*/
|
|
188
|
+
declare function formatNumberWithSeparator(value: number | undefined, separator?: string): string;
|
|
189
|
+
/**
|
|
190
|
+
* Parse a formatted number string back to a number.
|
|
191
|
+
*
|
|
192
|
+
* @param str - Formatted string with separators
|
|
193
|
+
* @param separator - Separator character to remove
|
|
194
|
+
* @returns Parsed number or undefined if invalid
|
|
195
|
+
*
|
|
196
|
+
* @example
|
|
197
|
+
* parseFormattedNumber('1,234,567.89') // => 1234567.89
|
|
198
|
+
* parseFormattedNumber('1 234 567', ' ') // => 1234567
|
|
199
|
+
*/
|
|
200
|
+
declare function parseFormattedNumber(str: string, separator?: string): number | undefined;
|
|
201
|
+
/**
|
|
202
|
+
* Safely parse a value to a Date object.
|
|
203
|
+
* Handles Date objects, ISO strings, and timestamps.
|
|
204
|
+
*
|
|
205
|
+
* @param value - Value to parse (Date, string, number, or unknown)
|
|
206
|
+
* @returns Date object or undefined if invalid
|
|
207
|
+
*
|
|
208
|
+
* @example
|
|
209
|
+
* parseToDate(new Date()) // => Date
|
|
210
|
+
* parseToDate('2024-01-15') // => Date
|
|
211
|
+
* parseToDate(null) // => undefined
|
|
212
|
+
*/
|
|
213
|
+
declare function parseToDate(value: unknown): Date | undefined;
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Provider for global form configuration.
|
|
217
|
+
* Set the adapter, resolver, and default mode for all forms in the app.
|
|
218
|
+
*
|
|
219
|
+
* @example
|
|
220
|
+
* import { FormProvider } from '@buildnbuzz/buzzform';
|
|
221
|
+
* import { useRhfAdapter } from '@buildnbuzz/buzzform/rhf';
|
|
222
|
+
* import { zodResolver } from '@buildnbuzz/buzzform/resolvers/zod';
|
|
223
|
+
*
|
|
224
|
+
* <FormProvider
|
|
225
|
+
* adapter={useRhfAdapter}
|
|
226
|
+
* resolver={zodResolver}
|
|
227
|
+
* mode="onBlur"
|
|
228
|
+
* >
|
|
229
|
+
* <App />
|
|
230
|
+
* </FormProvider>
|
|
231
|
+
*/
|
|
232
|
+
declare const FormProvider: React__default.FC<FormConfig & {
|
|
233
|
+
children: React__default.ReactNode;
|
|
234
|
+
}>;
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Context for global form configuration.
|
|
238
|
+
* Set via FormProvider, consumed by useForm.
|
|
239
|
+
*/
|
|
240
|
+
declare const FormConfigContext: React.Context<FormConfig | null>;
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Create a form instance with the specified options.
|
|
244
|
+
* Uses adapter and resolver from FormProvider context unless overridden.
|
|
245
|
+
*
|
|
246
|
+
* @example
|
|
247
|
+
* const loginSchema = createSchema([
|
|
248
|
+
* { type: 'email', name: 'email', required: true },
|
|
249
|
+
* { type: 'password', name: 'password', required: true },
|
|
250
|
+
* ]);
|
|
251
|
+
*
|
|
252
|
+
* const form = useForm({
|
|
253
|
+
* schema: loginSchema,
|
|
254
|
+
* onSubmit: async (data) => {
|
|
255
|
+
* await auth.login(data);
|
|
256
|
+
* },
|
|
257
|
+
* settings: {
|
|
258
|
+
* submitOnlyWhenDirty: true,
|
|
259
|
+
* },
|
|
260
|
+
* });
|
|
261
|
+
*
|
|
262
|
+
* return (
|
|
263
|
+
* <form onSubmit={form.handleSubmit}>
|
|
264
|
+
* ...
|
|
265
|
+
* </form>
|
|
266
|
+
* );
|
|
267
|
+
*/
|
|
268
|
+
declare function useForm<TData extends Record<string, unknown> = Record<string, unknown>>(options: UseFormOptions<TData>): FormAdapter<TData>;
|
|
269
|
+
|
|
270
|
+
export { Field, FormAdapter, FormConfig, FormConfigContext, FormProvider, UseFormOptions, applyNumericPrecision, clampNumber, countNestedErrors, formatNumberWithSeparator, getArrayRowLabel, getFieldWidthStyle, getNestedFieldPaths, getSelectOptionLabel, getSelectOptionLabelString, getSelectOptionValue, isSelectOptionDisabled, normalizeSelectOption, parseFormattedNumber, parseToDate, resolveFieldState, useForm };
|
package/dist/index.d.ts
ADDED
|
@@ -0,0 +1,270 @@
|
|
|
1
|
+
import { F as Field, a as FormConfig, U as UseFormOptions, b as FormAdapter } from './adapter-BT9v2OVg.js';
|
|
2
|
+
export { g as AdapterFactory, f as AdapterOptions, y as ArrayField, A as ArrayHelpers, B as BaseField, O as BuzzFormSchema, s as CheckboxField, J as CollapsibleField, C as ConditionContext, L as DataField, D as DateField, p as DatetimeField, E as EmailField, k as FieldComponentProps, j as FieldCondition, d as FieldError, l as FieldInputProps, m as FieldInputRenderFn, n as FieldStyle, K as FieldType, Q as FormSettings, c as FormState, G as GroupField, M as LayoutField, N as NumberField, P as PasswordField, u as RadioField, e as Resolver, R as ResolverResult, z as RowField, r as SelectField, q as SelectOption, S as SetValueOptions, t as SwitchField, H as Tab, I as TabsField, w as TagsField, T as TextField, o as TextareaField, x as UploadField, V as ValidationContext, i as ValidationFn, h as ValidationResult, v as validateAdapter } from './adapter-BT9v2OVg.js';
|
|
3
|
+
export { F as FieldToZod, a as FieldsToShape, I as InferSchema, S as SchemaBuilder, b as SchemaBuilderMap, d as applyCustomValidation, h as coerceToDate, g as coerceToNumber, l as createArrayHelpers, c as createSchema, e as extractValidationConfig, f as fieldsToZodSchema, p as formatBytes, n as generateFieldId, o as getNestedValue, i as getPatternErrorMessage, j as isFileLike, k as isFileTypeAccepted, m as makeOptional, s as setNestedValue } from './utils-DVLpbOoW.js';
|
|
4
|
+
import * as React from 'react';
|
|
5
|
+
import React__default, { ReactNode } from 'react';
|
|
6
|
+
import 'zod';
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Recursively extracts all field paths from a field definition tree.
|
|
10
|
+
* Handles nested groups, arrays, and layout fields (rows, tabs, collapsibles).
|
|
11
|
+
*
|
|
12
|
+
* @param fields - Array of field definitions
|
|
13
|
+
* @param basePath - Base path prefix (e.g., "contacts.0" for array items)
|
|
14
|
+
* @returns Array of all field paths
|
|
15
|
+
*
|
|
16
|
+
* @example
|
|
17
|
+
* const fields = [
|
|
18
|
+
* { type: 'text', name: 'name' },
|
|
19
|
+
* { type: 'group', name: 'address', fields: [
|
|
20
|
+
* { type: 'text', name: 'city' },
|
|
21
|
+
* { type: 'text', name: 'zip' }
|
|
22
|
+
* ]}
|
|
23
|
+
* ];
|
|
24
|
+
* getNestedFieldPaths(fields, 'contact')
|
|
25
|
+
* // => ['contact.name', 'contact.address', 'contact.address.city', 'contact.address.zip']
|
|
26
|
+
*/
|
|
27
|
+
declare function getNestedFieldPaths(fields: Field[], basePath: string): string[];
|
|
28
|
+
/**
|
|
29
|
+
* Count validation errors in nested fields.
|
|
30
|
+
* Useful for showing error badges on collapsible sections, array rows, tabs, etc.
|
|
31
|
+
*
|
|
32
|
+
* @param errors - Form errors object from FormAdapter.formState.errors
|
|
33
|
+
* @param fields - Field definitions to check
|
|
34
|
+
* @param basePath - Base path for the fields
|
|
35
|
+
* @returns Number of fields with errors
|
|
36
|
+
*
|
|
37
|
+
* @example
|
|
38
|
+
* const errorCount = countNestedErrors(form.formState.errors, arrayField.fields, `items.0`);
|
|
39
|
+
*/
|
|
40
|
+
declare function countNestedErrors(errors: Record<string, unknown>, fields: Field[], basePath: string): number;
|
|
41
|
+
/**
|
|
42
|
+
* Resolve a potentially dynamic field property (disabled, readOnly, hidden).
|
|
43
|
+
* These properties can be boolean or a function that receives form data.
|
|
44
|
+
*
|
|
45
|
+
* @param value - The property value (boolean or function)
|
|
46
|
+
* @param formData - Current form data
|
|
47
|
+
* @param siblingData - Data at the same level (for arrays, this is the row data)
|
|
48
|
+
* @returns Resolved boolean value
|
|
49
|
+
*
|
|
50
|
+
* @example
|
|
51
|
+
* const isDisabled = resolveFieldState(field.disabled, formData, siblingData);
|
|
52
|
+
*/
|
|
53
|
+
declare function resolveFieldState<TData = Record<string, unknown>>(value: boolean | ((data: TData, siblingData: Record<string, unknown>) => boolean) | undefined, formData: TData, siblingData?: Record<string, unknown>): boolean;
|
|
54
|
+
/**
|
|
55
|
+
* Get the label value for an array row based on field configuration.
|
|
56
|
+
* First checks for a specific rowLabelField in ui options, then falls back
|
|
57
|
+
* to the first named field's value.
|
|
58
|
+
*
|
|
59
|
+
* @param rowData - Data for the row
|
|
60
|
+
* @param fields - Field definitions for the array
|
|
61
|
+
* @param uiOptions - UI options that may contain rowLabelField
|
|
62
|
+
* @param fallbackLabel - Default label if no value found
|
|
63
|
+
* @returns Label string for the row
|
|
64
|
+
*
|
|
65
|
+
* @example
|
|
66
|
+
* const label = getArrayRowLabel(rowData, field.fields, field.ui, `Item ${index + 1}`);
|
|
67
|
+
*/
|
|
68
|
+
declare function getArrayRowLabel(rowData: Record<string, unknown> | undefined, fields: Field[], uiOptions: {
|
|
69
|
+
rowLabelField?: string;
|
|
70
|
+
} | undefined, fallbackLabel: string): string;
|
|
71
|
+
/**
|
|
72
|
+
* Compute the inline style object for a field's width.
|
|
73
|
+
* Handles both numeric (px) and string (CSS) width values.
|
|
74
|
+
*
|
|
75
|
+
* @param style - Field style configuration
|
|
76
|
+
* @returns CSS properties object or undefined if no width specified
|
|
77
|
+
*
|
|
78
|
+
* @example
|
|
79
|
+
* <Field style={getFieldWidthStyle(field.style)}>
|
|
80
|
+
* ...
|
|
81
|
+
* </Field>
|
|
82
|
+
*/
|
|
83
|
+
declare function getFieldWidthStyle(style: {
|
|
84
|
+
width?: number | string;
|
|
85
|
+
} | undefined): {
|
|
86
|
+
width: string;
|
|
87
|
+
} | undefined;
|
|
88
|
+
type SelectOptionLike = {
|
|
89
|
+
value: string | number | boolean;
|
|
90
|
+
label?: ReactNode;
|
|
91
|
+
description?: ReactNode;
|
|
92
|
+
icon?: ReactNode;
|
|
93
|
+
disabled?: boolean;
|
|
94
|
+
} | string;
|
|
95
|
+
/**
|
|
96
|
+
* Normalize a select option to always be an object.
|
|
97
|
+
* Converts string options to { value, label } objects.
|
|
98
|
+
*
|
|
99
|
+
* @param option - String or SelectOption object
|
|
100
|
+
* @returns Normalized SelectOption object
|
|
101
|
+
*
|
|
102
|
+
* @example
|
|
103
|
+
* normalizeSelectOption('foo') // => { value: 'foo', label: 'foo' }
|
|
104
|
+
* normalizeSelectOption({ value: 'bar', label: 'Bar' }) // => { value: 'bar', label: 'Bar' }
|
|
105
|
+
*/
|
|
106
|
+
declare function normalizeSelectOption(option: SelectOptionLike): {
|
|
107
|
+
value: string | number | boolean;
|
|
108
|
+
label: ReactNode;
|
|
109
|
+
description?: ReactNode;
|
|
110
|
+
icon?: ReactNode;
|
|
111
|
+
disabled?: boolean;
|
|
112
|
+
};
|
|
113
|
+
/**
|
|
114
|
+
* Get the value from a select option (handles string or object).
|
|
115
|
+
*
|
|
116
|
+
* @param option - String or SelectOption object
|
|
117
|
+
* @returns The option's value as a string
|
|
118
|
+
*
|
|
119
|
+
* @example
|
|
120
|
+
* getSelectOptionValue('foo') // => 'foo'
|
|
121
|
+
* getSelectOptionValue({ value: 123, label: 'One Two Three' }) // => '123'
|
|
122
|
+
*/
|
|
123
|
+
declare function getSelectOptionValue(option: SelectOptionLike): string;
|
|
124
|
+
/**
|
|
125
|
+
* Get the label from a select option (handles string or object).
|
|
126
|
+
* Returns ReactNode to support JSX labels.
|
|
127
|
+
*
|
|
128
|
+
* @param option - String or SelectOption object
|
|
129
|
+
* @returns The option's label for display
|
|
130
|
+
*
|
|
131
|
+
* @example
|
|
132
|
+
* getSelectOptionLabel('foo') // => 'foo'
|
|
133
|
+
* getSelectOptionLabel({ value: 'bar', label: <strong>Bar</strong> }) // => <strong>Bar</strong>
|
|
134
|
+
*/
|
|
135
|
+
declare function getSelectOptionLabel(option: SelectOptionLike): ReactNode;
|
|
136
|
+
/**
|
|
137
|
+
* Get the string label from a select option (for filtering/comparison).
|
|
138
|
+
* Always returns a string, not ReactNode.
|
|
139
|
+
*
|
|
140
|
+
* @param option - String or SelectOption object
|
|
141
|
+
* @returns The option's label as a string
|
|
142
|
+
*/
|
|
143
|
+
declare function getSelectOptionLabelString(option: SelectOptionLike): string;
|
|
144
|
+
/**
|
|
145
|
+
* Check if a select option is disabled.
|
|
146
|
+
*
|
|
147
|
+
* @param option - String or SelectOption object
|
|
148
|
+
* @returns true if option is disabled
|
|
149
|
+
*/
|
|
150
|
+
declare function isSelectOptionDisabled(option: SelectOptionLike): boolean;
|
|
151
|
+
/**
|
|
152
|
+
* Clamp a number between min and max bounds.
|
|
153
|
+
*
|
|
154
|
+
* @param value - The number to clamp
|
|
155
|
+
* @param min - Minimum bound (optional)
|
|
156
|
+
* @param max - Maximum bound (optional)
|
|
157
|
+
* @returns Clamped number
|
|
158
|
+
*
|
|
159
|
+
* @example
|
|
160
|
+
* clampNumber(5, 0, 10) // => 5
|
|
161
|
+
* clampNumber(-5, 0, 10) // => 0
|
|
162
|
+
* clampNumber(15, 0, 10) // => 10
|
|
163
|
+
*/
|
|
164
|
+
declare function clampNumber(value: number, min?: number, max?: number): number;
|
|
165
|
+
/**
|
|
166
|
+
* Apply numeric precision (decimal places) to a number.
|
|
167
|
+
*
|
|
168
|
+
* @param value - The number to format
|
|
169
|
+
* @param precision - Number of decimal places
|
|
170
|
+
* @returns Formatted number or undefined if input is undefined
|
|
171
|
+
*
|
|
172
|
+
* @example
|
|
173
|
+
* applyNumericPrecision(3.14159, 2) // => 3.14
|
|
174
|
+
* applyNumericPrecision(10, 2) // => 10
|
|
175
|
+
*/
|
|
176
|
+
declare function applyNumericPrecision(value: number | undefined, precision?: number): number | undefined;
|
|
177
|
+
/**
|
|
178
|
+
* Format a number with thousand separators.
|
|
179
|
+
*
|
|
180
|
+
* @param value - The number to format
|
|
181
|
+
* @param separator - Separator character (default: ',')
|
|
182
|
+
* @returns Formatted string or empty string if value is undefined/NaN
|
|
183
|
+
*
|
|
184
|
+
* @example
|
|
185
|
+
* formatNumberWithSeparator(1234567.89) // => '1,234,567.89'
|
|
186
|
+
* formatNumberWithSeparator(1234567, ' ') // => '1 234 567'
|
|
187
|
+
*/
|
|
188
|
+
declare function formatNumberWithSeparator(value: number | undefined, separator?: string): string;
|
|
189
|
+
/**
|
|
190
|
+
* Parse a formatted number string back to a number.
|
|
191
|
+
*
|
|
192
|
+
* @param str - Formatted string with separators
|
|
193
|
+
* @param separator - Separator character to remove
|
|
194
|
+
* @returns Parsed number or undefined if invalid
|
|
195
|
+
*
|
|
196
|
+
* @example
|
|
197
|
+
* parseFormattedNumber('1,234,567.89') // => 1234567.89
|
|
198
|
+
* parseFormattedNumber('1 234 567', ' ') // => 1234567
|
|
199
|
+
*/
|
|
200
|
+
declare function parseFormattedNumber(str: string, separator?: string): number | undefined;
|
|
201
|
+
/**
|
|
202
|
+
* Safely parse a value to a Date object.
|
|
203
|
+
* Handles Date objects, ISO strings, and timestamps.
|
|
204
|
+
*
|
|
205
|
+
* @param value - Value to parse (Date, string, number, or unknown)
|
|
206
|
+
* @returns Date object or undefined if invalid
|
|
207
|
+
*
|
|
208
|
+
* @example
|
|
209
|
+
* parseToDate(new Date()) // => Date
|
|
210
|
+
* parseToDate('2024-01-15') // => Date
|
|
211
|
+
* parseToDate(null) // => undefined
|
|
212
|
+
*/
|
|
213
|
+
declare function parseToDate(value: unknown): Date | undefined;
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Provider for global form configuration.
|
|
217
|
+
* Set the adapter, resolver, and default mode for all forms in the app.
|
|
218
|
+
*
|
|
219
|
+
* @example
|
|
220
|
+
* import { FormProvider } from '@buildnbuzz/buzzform';
|
|
221
|
+
* import { useRhfAdapter } from '@buildnbuzz/buzzform/rhf';
|
|
222
|
+
* import { zodResolver } from '@buildnbuzz/buzzform/resolvers/zod';
|
|
223
|
+
*
|
|
224
|
+
* <FormProvider
|
|
225
|
+
* adapter={useRhfAdapter}
|
|
226
|
+
* resolver={zodResolver}
|
|
227
|
+
* mode="onBlur"
|
|
228
|
+
* >
|
|
229
|
+
* <App />
|
|
230
|
+
* </FormProvider>
|
|
231
|
+
*/
|
|
232
|
+
declare const FormProvider: React__default.FC<FormConfig & {
|
|
233
|
+
children: React__default.ReactNode;
|
|
234
|
+
}>;
|
|
235
|
+
|
|
236
|
+
/**
|
|
237
|
+
* Context for global form configuration.
|
|
238
|
+
* Set via FormProvider, consumed by useForm.
|
|
239
|
+
*/
|
|
240
|
+
declare const FormConfigContext: React.Context<FormConfig | null>;
|
|
241
|
+
|
|
242
|
+
/**
|
|
243
|
+
* Create a form instance with the specified options.
|
|
244
|
+
* Uses adapter and resolver from FormProvider context unless overridden.
|
|
245
|
+
*
|
|
246
|
+
* @example
|
|
247
|
+
* const loginSchema = createSchema([
|
|
248
|
+
* { type: 'email', name: 'email', required: true },
|
|
249
|
+
* { type: 'password', name: 'password', required: true },
|
|
250
|
+
* ]);
|
|
251
|
+
*
|
|
252
|
+
* const form = useForm({
|
|
253
|
+
* schema: loginSchema,
|
|
254
|
+
* onSubmit: async (data) => {
|
|
255
|
+
* await auth.login(data);
|
|
256
|
+
* },
|
|
257
|
+
* settings: {
|
|
258
|
+
* submitOnlyWhenDirty: true,
|
|
259
|
+
* },
|
|
260
|
+
* });
|
|
261
|
+
*
|
|
262
|
+
* return (
|
|
263
|
+
* <form onSubmit={form.handleSubmit}>
|
|
264
|
+
* ...
|
|
265
|
+
* </form>
|
|
266
|
+
* );
|
|
267
|
+
*/
|
|
268
|
+
declare function useForm<TData extends Record<string, unknown> = Record<string, unknown>>(options: UseFormOptions<TData>): FormAdapter<TData>;
|
|
269
|
+
|
|
270
|
+
export { Field, FormAdapter, FormConfig, FormConfigContext, FormProvider, UseFormOptions, applyNumericPrecision, clampNumber, countNestedErrors, formatNumberWithSeparator, getArrayRowLabel, getFieldWidthStyle, getNestedFieldPaths, getSelectOptionLabel, getSelectOptionLabelString, getSelectOptionValue, isSelectOptionDisabled, normalizeSelectOption, parseFormattedNumber, parseToDate, resolveFieldState, useForm };
|