@buildnbuzz/buzzform 0.1.3 → 0.1.5
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/dist/{adapter-nQW28cyO.d.mts → adapter-u4raoNx9.d.mts} +76 -42
- package/dist/{adapter-nQW28cyO.d.ts → adapter-u4raoNx9.d.ts} +76 -42
- package/dist/{chunk-63LF7K4O.mjs → chunk-4SHWTNBE.mjs} +3 -1
- package/dist/chunk-4SHWTNBE.mjs.map +1 -0
- package/dist/{chunk-HWDQN57Q.mjs → chunk-ATZ2HTUS.mjs} +60 -11
- package/dist/chunk-ATZ2HTUS.mjs.map +1 -0
- package/dist/{chunk-IMJ5FRK5.mjs → chunk-VXG7KGOZ.mjs} +20 -14
- package/dist/chunk-VXG7KGOZ.mjs.map +1 -0
- package/dist/index.d.mts +3 -3
- package/dist/index.d.ts +3 -3
- package/dist/index.js +78 -22
- package/dist/index.js.map +1 -1
- package/dist/index.mjs +3 -3
- package/dist/rhf.d.mts +1 -1
- package/dist/rhf.d.ts +1 -1
- package/dist/rhf.js +19 -13
- package/dist/rhf.js.map +1 -1
- package/dist/rhf.mjs +1 -1
- package/dist/schema.d.mts +5 -4
- package/dist/schema.d.ts +5 -4
- package/dist/schema.js +80 -22
- package/dist/schema.js.map +1 -1
- package/dist/schema.mjs +5 -3
- package/dist/{utils-BRY27BLX.d.mts → utils-BksL2RlA.d.mts} +10 -3
- package/dist/{utils-DgwUn6tN.d.ts → utils-oLqFuT9W.d.ts} +10 -3
- package/dist/zod.d.mts +1 -1
- package/dist/zod.d.ts +1 -1
- package/dist/zod.js.map +1 -1
- package/dist/zod.mjs +1 -1
- package/package.json +1 -1
- package/dist/chunk-63LF7K4O.mjs.map +0 -1
- package/dist/chunk-HWDQN57Q.mjs.map +0 -1
- package/dist/chunk-IMJ5FRK5.mjs.map +0 -1
package/dist/rhf.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"sources":["../src/adapters/rhf.ts","../src/utils/array.ts","../src/lib/utils.ts"],"sourcesContent":["'use client';\n\nimport { useRef, useEffect } from 'react';\nimport { useForm, useWatch } from 'react-hook-form';\nimport type {\n Control,\n FieldValues,\n Path,\n PathValue,\n DefaultValues,\n FieldErrors,\n Resolver as RhfResolver\n} from 'react-hook-form';\nimport type {\n FormAdapter,\n AdapterOptions,\n FormState,\n FieldError,\n SetValueOptions,\n} from '../types';\nimport { createArrayHelpers } from '../utils';\nimport { getNestedValue, flattenNestedObject } from '../lib';\n\n// =============================================================================\n// RHF ADAPTER OPTIONS\n// =============================================================================\n\n/**\n * Options specific to the React Hook Form adapter.\n * Extends base AdapterOptions with RHF-specific features.\n */\nexport interface RhfAdapterOptions<TData extends FieldValues = FieldValues>\n extends AdapterOptions<TData> {\n /**\n * React Hook Form's reValidateMode.\n * When to re-validate after initial validation.\n * @default 'onChange'\n */\n reValidateMode?: 'onChange' | 'onBlur' | 'onSubmit';\n\n /**\n * Validation strategy before submit.\n * - 'firstError': Return first error only (faster)\n * - 'all': Return all errors (better UX for complex forms)\n * @default 'firstError'\n */\n criteriaMode?: 'firstError' | 'all';\n\n /**\n * Delay validation by specified ms (debounce).\n * Useful for expensive async validation.\n */\n delayError?: number;\n\n /**\n * Focus on the first field with an error after submit.\n * @default true\n */\n shouldFocusError?: boolean;\n}\n\n// =============================================================================\n// RHF ADAPTER\n// =============================================================================\n\n/**\n * React Hook Form adapter implementing the FormAdapter interface.\n * \n * This is the default adapter for BuzzForm. It provides full implementation\n * of all required and optional FormAdapter methods using React Hook Form.\n * \n * @example\n * // In FormProvider\n * import { useRhf } from '@buildnbuzz/buzzform/rhf';\n * \n * <FormProvider adapter={useRhf}>\n * <App />\n * </FormProvider>\n * \n * @example\n * // Direct usage\n * const form = useRhf({\n * defaultValues: { email: '', password: '' },\n * resolver: zodResolver(schema),\n * onSubmit: async (data) => {\n * await loginUser(data);\n * },\n * });\n */\nexport function useRhf<TData extends FieldValues = FieldValues>(\n options: RhfAdapterOptions<TData>\n): FormAdapter<TData> {\n const {\n defaultValues,\n values,\n resolver,\n mode = 'onChange',\n reValidateMode = 'onChange',\n criteriaMode,\n delayError,\n shouldFocusError = true,\n onSubmit,\n } = options;\n\n // -------------------------------------------------------------------------\n // Initialize React Hook Form\n // -------------------------------------------------------------------------\n\n const form = useForm<TData>({\n defaultValues: defaultValues as DefaultValues<TData>,\n values: values,\n resolver: resolver as unknown as RhfResolver<TData>,\n mode,\n reValidateMode,\n criteriaMode,\n delayError,\n shouldFocusError,\n });\n\n // -------------------------------------------------------------------------\n // Handle controlled values updates\n // -------------------------------------------------------------------------\n\n const prevValuesRef = useRef(values);\n\n useEffect(() => {\n if (values && JSON.stringify(values) !== JSON.stringify(prevValuesRef.current)) {\n prevValuesRef.current = values;\n }\n }, [values]);\n\n // -------------------------------------------------------------------------\n // Build submit handler\n // -------------------------------------------------------------------------\n\n const handleSubmit = form.handleSubmit(async (data) => {\n if (onSubmit) {\n await onSubmit(data as TData);\n }\n });\n\n // -------------------------------------------------------------------------\n // Build the adapter API\n // -------------------------------------------------------------------------\n\n const api: FormAdapter<TData> = {\n // ---------------------------------------------------------------------\n // CORE PROPERTIES\n // ---------------------------------------------------------------------\n\n control: form.control,\n\n get formState(): FormState {\n const state = form.formState;\n return {\n isSubmitting: state.isSubmitting,\n isValidating: state.isValidating,\n isDirty: state.isDirty,\n isValid: state.isValid,\n isLoading: state.isLoading,\n errors: normalizeErrors(state.errors),\n dirtyFields: flattenNestedObject(state.dirtyFields),\n touchedFields: flattenNestedObject(state.touchedFields),\n submitCount: state.submitCount,\n };\n },\n\n handleSubmit,\n\n // ---------------------------------------------------------------------\n // VALUE MANAGEMENT\n // ---------------------------------------------------------------------\n\n getValues: () => form.getValues(),\n\n setValue: (name: string, value: unknown, opts?: SetValueOptions) => {\n form.setValue(name as Path<TData>, value as PathValue<TData, Path<TData>>, {\n shouldValidate: opts?.shouldValidate,\n shouldDirty: opts?.shouldDirty ?? true,\n shouldTouch: opts?.shouldTouch,\n });\n },\n\n reset: (vals) => form.reset(vals as DefaultValues<TData>),\n\n watch: <T = unknown>(name?: string): T => {\n return form.watch(name as Path<TData>) as T;\n },\n\n // ---------------------------------------------------------------------\n // VALIDATION\n // ---------------------------------------------------------------------\n\n validate: async (name) => {\n if (name) {\n const names = Array.isArray(name) ? name : [name];\n return form.trigger(names as Path<TData>[]);\n }\n return form.trigger();\n },\n\n setError: (name: string, error: FieldError) => {\n form.setError(name as Path<TData>, {\n type: error.type || 'manual',\n message: error.message,\n });\n },\n\n clearErrors: (name) => {\n if (name) {\n const names = Array.isArray(name) ? name : [name];\n names.forEach(n => form.clearErrors(n as Path<TData>));\n } else {\n form.clearErrors();\n }\n },\n\n // ---------------------------------------------------------------------\n // ARRAYS\n // ---------------------------------------------------------------------\n\n array: createArrayHelpers(\n (path) => form.getValues(path as Path<TData>) as unknown[],\n (path, value) => form.setValue(\n path as Path<TData>,\n value as PathValue<TData, Path<TData>>,\n { shouldDirty: true }\n )\n ),\n\n // ---------------------------------------------------------------------\n // OPTIONAL ENHANCED FEATURES\n // ---------------------------------------------------------------------\n\n onBlur: (name: string) => {\n // Mark field as touched\n const hasError = !!getNestedValue(form.formState.errors, name);\n\n // Trigger validation based on mode\n if (mode === 'onBlur' || mode === 'all') {\n form.trigger(name as Path<TData>);\n } else if (hasError && reValidateMode === 'onBlur') {\n // Re-validate if field has error and reValidateMode is onBlur\n form.trigger(name as Path<TData>);\n }\n },\n\n getFieldState: (name: string) => {\n const state = form.getFieldState(name as Path<TData>, form.formState);\n return {\n isDirty: state.isDirty,\n isTouched: state.isTouched,\n invalid: state.invalid,\n error: state.error?.message,\n };\n },\n\n setFocus: (name: string, options?: { shouldSelect?: boolean }) => {\n form.setFocus(name as Path<TData>, options);\n },\n\n unregister: (name: string | string[]) => {\n const names = Array.isArray(name) ? name : [name];\n names.forEach(n => form.unregister(n as Path<TData>));\n },\n };\n\n return api;\n}\n\n// =============================================================================\n// HELPER: Watch hook for external use\n// =============================================================================\n\n/**\n * Hook to watch specific field values reactively.\n * Use this when you need to react to field changes outside of components.\n * \n * @param control - The control object from useRhf (form.control)\n * @param name - Field path(s) to watch\n */\nexport function useRhfWatch<TData extends FieldValues, TValue = unknown>(\n control: Control<TData>,\n name: string | string[]\n): TValue {\n if (Array.isArray(name)) {\n return useWatch({ control, name: name as unknown as Path<TData>[] }) as TValue;\n }\n return useWatch({ control, name: name as Path<TData> }) as TValue;\n}\n\n// =============================================================================\n// UTILITIES\n// =============================================================================\n\n/**\n * Normalize RHF's nested error structure to flat string map.\n */\nfunction normalizeErrors<TData extends FieldValues>(\n errors: FieldErrors<TData>\n): Record<string, string | string[] | undefined> {\n const result: Record<string, string | string[] | undefined> = {};\n\n function traverse(obj: Record<string, unknown>, prefix = '') {\n for (const key in obj) {\n const path = prefix ? `${prefix}.${key}` : key;\n const value = obj[key];\n\n if (isRecord(value) && 'message' in value && typeof value.message === 'string') {\n // Leaf error\n result[path] = value.message;\n } else if (\n isRecord(value) &&\n 'root' in value &&\n isRecord(value.root) &&\n 'message' in value.root &&\n typeof value.root.message === 'string'\n ) {\n // Array root error\n result[path] = value.root.message;\n } else if (isRecord(value)) {\n // Nested object, traverse deeper\n traverse(value, path);\n }\n }\n }\n\n traverse(errors as unknown as Record<string, unknown>);\n return result;\n}\n\n\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\n// =============================================================================\n// RE-EXPORTS FOR CONVENIENCE\n// =============================================================================\n\nexport type { UseFormReturn as RhfForm } from 'react-hook-form';","import { nanoid } from 'nanoid';\nimport type { ArrayHelpers } from '../types';\n\n/**\n * Creates a standardized set of array field manipulation methods.\n * Abstracts the difference between getting/setting values in different form libraries.\n * \n * @param getArray - Function to get current array value at a path\n * @param setArray - Function to set array value at a path\n */\nexport function createArrayHelpers(\n getArray: (path: string) => unknown[],\n setArray: (path: string, value: unknown[]) => void\n): ArrayHelpers {\n return {\n fields: <T = unknown>(path: string): Array<T & { id: string }> => {\n const arr = getArray(path);\n if (!Array.isArray(arr)) return [];\n return arr.map((item, index) => ({\n id: (item as Record<string, unknown>)?.id as string || `${path}-${index}`,\n ...item as T,\n }));\n },\n\n append: (path: string, value: unknown) => {\n const current = getArray(path) || [];\n const itemWithId = ensureId(value);\n setArray(path, [...current, itemWithId]);\n },\n\n prepend: (path: string, value: unknown) => {\n const current = getArray(path) || [];\n const itemWithId = ensureId(value);\n setArray(path, [itemWithId, ...current]);\n },\n\n insert: (path: string, index: number, value: unknown) => {\n const current = [...(getArray(path) || [])];\n const itemWithId = ensureId(value);\n current.splice(index, 0, itemWithId);\n setArray(path, current);\n },\n\n remove: (path: string, index: number) => {\n const current = [...(getArray(path) || [])];\n current.splice(index, 1);\n setArray(path, current);\n },\n\n move: (path: string, from: number, to: number) => {\n const current = [...(getArray(path) || [])];\n const [item] = current.splice(from, 1);\n current.splice(to, 0, item);\n setArray(path, current);\n },\n\n swap: (path: string, indexA: number, indexB: number) => {\n const current = [...(getArray(path) || [])];\n const temp = current[indexA];\n current[indexA] = current[indexB];\n current[indexB] = temp;\n setArray(path, current);\n },\n\n replace: (path: string, values: unknown[]) => {\n const itemsWithIds = values.map(ensureId);\n setArray(path, itemsWithIds);\n },\n\n update: (path: string, index: number, value: unknown) => {\n const current = [...(getArray(path) || [])];\n // Preserve existing ID if present\n const existingId = (current[index] as Record<string, unknown>)?.id;\n current[index] = {\n ...(typeof value === 'object' && value !== null ? value : {}),\n id: existingId || nanoid(),\n };\n setArray(path, current);\n },\n };\n}\n\n/**\n * Ensures an item has a unique ID for React keys.\n */\nfunction ensureId(value: unknown): unknown {\n if (typeof value === 'object' && value !== null) {\n const obj = value as Record<string, unknown>;\n if (!obj.id) {\n return { ...obj, id: nanoid() };\n }\n return obj;\n }\n return { value, id: nanoid() };\n}\n","// =============================================================================\n// COMMON UTILITIES\n// These are used by both the core package and registry field components.\n// =============================================================================\n\n/**\n * Generate a unique field ID from the field path.\n * Converts dot notation to dashes and prefixes with 'field-'.\n * Used for accessibility (htmlFor, id attributes).\n * \n * @example\n * generateFieldId('user.profile.email') => 'field-user-profile-email'\n * generateFieldId('items[0].name') => 'field-items-0-name'\n */\nexport function generateFieldId(path: string): string {\n return `field-${path.replace(/\\./g, \"-\").replace(/\\[/g, \"-\").replace(/\\]/g, \"\")}`;\n}\n\n/**\n * Safely retrieve a nested value from an object using a dot-notation path.\n * \n * @example\n * getNestedValue({ user: { name: 'John' } }, 'user.name') => 'John'\n * getNestedValue({ items: [{ id: 1 }] }, 'items.0.id') => 1\n */\nexport function getNestedValue(obj: unknown, path: string): unknown {\n if (!obj || !path) return undefined;\n return path.split(\".\").reduce<unknown>((acc: unknown, key: string) => {\n if (acc && typeof acc === \"object\" && acc !== null) {\n return (acc as Record<string, unknown>)[key];\n }\n return undefined;\n }, obj);\n}\n\n/**\n * Set a nested value in an object using a dot-notation path.\n * Creates intermediate objects/arrays as needed.\n * \n * @example\n * setNestedValue({}, 'user.name', 'John') => { user: { name: 'John' } }\n */\nexport function setNestedValue<T extends Record<string, unknown>>(\n obj: T,\n path: string,\n value: unknown\n): T {\n const keys = path.split(\".\");\n const result = { ...obj } as Record<string, unknown>;\n let current = result;\n\n for (let i = 0; i < keys.length - 1; i++) {\n const key = keys[i];\n if (!(key in current) || typeof current[key] !== \"object\") {\n // Check if next key is numeric (array index)\n const nextKey = keys[i + 1];\n current[key] = /^\\d+$/.test(nextKey) ? [] : {};\n } else {\n current[key] = Array.isArray(current[key])\n ? [...(current[key] as unknown[])]\n : { ...(current[key] as Record<string, unknown>) };\n }\n current = current[key] as Record<string, unknown>;\n }\n\n current[keys[keys.length - 1]] = value;\n return result as T;\n}\n\n/**\n * Format bytes into a human-readable string.\n * \n * @example\n * formatBytes(1024) => '1 KB'\n * formatBytes(1234567) => '1.18 MB'\n */\nexport function formatBytes(bytes: number, decimals = 2): string {\n if (bytes === 0) return '0 Bytes';\n\n const k = 1024;\n const dm = decimals < 0 ? 0 : decimals;\n const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];\n\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n\n return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`;\n}\n\n/**\n * Flatten a nested object to dot-notation paths.\n * Useful for converting form library state (like dirtyFields, touchedFields)\n * to the flat format expected by FormState.\n * \n * @example\n * flattenNestedObject({ user: { name: true, email: true } })\n * // => { 'user.name': true, 'user.email': true }\n * \n * flattenNestedObject({ items: { 0: { title: true } } })\n * // => { 'items.0.title': true }\n */\nexport function flattenNestedObject(\n obj: Record<string, unknown>,\n prefix = ''\n): Record<string, boolean> {\n const result: Record<string, boolean> = {};\n\n for (const key in obj) {\n const path = prefix ? `${prefix}.${key}` : key;\n const value = obj[key];\n\n if (typeof value === 'boolean') {\n result[path] = value;\n } else if (value !== null && typeof value === 'object' && !Array.isArray(value)) {\n Object.assign(result, flattenNestedObject(value as Record<string, unknown>, path));\n }\n }\n\n return result;\n}\n\n"],"mappings":"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","names":["options"]}
|
|
1
|
+
{"version":3,"sources":["../src/adapters/rhf.ts","../src/utils/array.ts","../src/lib/utils.ts"],"sourcesContent":["'use client';\n\nimport { useRef, useEffect } from 'react';\nimport { useForm, useWatch } from 'react-hook-form';\nimport type {\n Control,\n FieldValues,\n Path,\n PathValue,\n DefaultValues,\n FieldErrors,\n Resolver as RhfResolver\n} from 'react-hook-form';\nimport type {\n FormAdapter,\n AdapterOptions,\n FormState,\n FieldError,\n SetValueOptions,\n} from '../types';\nimport { createArrayHelpers } from '../utils';\nimport { getNestedValue, flattenNestedObject } from '../lib';\n\n// =============================================================================\n// RHF ADAPTER OPTIONS\n// =============================================================================\n\n/**\n * Options specific to the React Hook Form adapter.\n * Extends base AdapterOptions with RHF-specific features.\n */\nexport interface RhfAdapterOptions<TData extends FieldValues = FieldValues>\n extends AdapterOptions<TData> {\n /**\n * React Hook Form's reValidateMode.\n * When to re-validate after initial validation.\n * @default 'onChange'\n */\n reValidateMode?: 'onChange' | 'onBlur' | 'onSubmit';\n\n /**\n * Validation strategy before submit.\n * - 'firstError': Return first error only (faster)\n * - 'all': Return all errors (better UX for complex forms)\n * @default 'firstError'\n */\n criteriaMode?: 'firstError' | 'all';\n\n /**\n * Delay validation by specified ms (debounce).\n * Useful for expensive async validation.\n */\n delayError?: number;\n\n /**\n * Focus on the first field with an error after submit.\n * @default true\n */\n shouldFocusError?: boolean;\n}\n\n// =============================================================================\n// RHF ADAPTER\n// =============================================================================\n\n/**\n * React Hook Form adapter implementing the FormAdapter interface.\n * \n * This is the default adapter for BuzzForm. It provides full implementation\n * of all required and optional FormAdapter methods using React Hook Form.\n * \n * @example\n * // In FormProvider\n * import { useRhf } from '@buildnbuzz/buzzform/rhf';\n * \n * <FormProvider adapter={useRhf}>\n * <App />\n * </FormProvider>\n * \n * @example\n * // Direct usage\n * const form = useRhf({\n * defaultValues: { email: '', password: '' },\n * resolver: zodResolver(schema),\n * onSubmit: async (data) => {\n * await loginUser(data);\n * },\n * });\n */\nexport function useRhf<TData extends FieldValues = FieldValues>(\n options: RhfAdapterOptions<TData>\n): FormAdapter<TData> {\n const {\n defaultValues,\n values,\n resolver,\n mode = 'onChange',\n reValidateMode = 'onChange',\n criteriaMode,\n delayError,\n shouldFocusError = true,\n onSubmit,\n } = options;\n\n // -------------------------------------------------------------------------\n // Initialize React Hook Form\n // -------------------------------------------------------------------------\n\n const form = useForm<TData>({\n defaultValues: defaultValues as DefaultValues<TData>,\n values: values,\n resolver: resolver as unknown as RhfResolver<TData>,\n mode,\n reValidateMode,\n criteriaMode,\n delayError,\n shouldFocusError,\n });\n\n // -------------------------------------------------------------------------\n // Handle controlled values updates\n // -------------------------------------------------------------------------\n\n const prevValuesRef = useRef(values);\n\n useEffect(() => {\n if (values && JSON.stringify(values) !== JSON.stringify(prevValuesRef.current)) {\n prevValuesRef.current = values;\n }\n }, [values]);\n\n // -------------------------------------------------------------------------\n // Build submit handler\n // -------------------------------------------------------------------------\n\n const handleSubmit = form.handleSubmit(async (data) => {\n if (onSubmit) {\n await onSubmit(data as TData);\n }\n });\n\n // -------------------------------------------------------------------------\n // Build the adapter API\n // -------------------------------------------------------------------------\n\n const api: FormAdapter<TData> = {\n // ---------------------------------------------------------------------\n // CORE PROPERTIES\n // ---------------------------------------------------------------------\n\n control: form.control,\n\n get formState(): FormState {\n const state = form.formState;\n return {\n isSubmitting: state.isSubmitting,\n isValidating: state.isValidating,\n isDirty: state.isDirty,\n isValid: state.isValid,\n isLoading: state.isLoading,\n errors: normalizeErrors(state.errors),\n dirtyFields: flattenNestedObject(state.dirtyFields),\n touchedFields: flattenNestedObject(state.touchedFields),\n submitCount: state.submitCount,\n };\n },\n\n handleSubmit,\n\n // ---------------------------------------------------------------------\n // VALUE MANAGEMENT\n // ---------------------------------------------------------------------\n\n getValues: () => form.getValues(),\n\n setValue: (name: string, value: unknown, opts?: SetValueOptions) => {\n form.setValue(name as Path<TData>, value as PathValue<TData, Path<TData>>, {\n shouldValidate: opts?.shouldValidate,\n shouldDirty: opts?.shouldDirty ?? true,\n shouldTouch: opts?.shouldTouch,\n });\n },\n\n reset: (vals) => form.reset(vals as DefaultValues<TData>),\n\n watch: <T = unknown>(name?: string): T => {\n return form.watch(name as Path<TData>) as T;\n },\n\n // ---------------------------------------------------------------------\n // VALIDATION\n // ---------------------------------------------------------------------\n\n validate: async (name) => {\n if (name) {\n const names = Array.isArray(name) ? name : [name];\n return form.trigger(names as Path<TData>[]);\n }\n return form.trigger();\n },\n\n setError: (name: string, error: FieldError) => {\n form.setError(name as Path<TData>, {\n type: error.type || 'manual',\n message: error.message,\n });\n },\n\n clearErrors: (name) => {\n if (name) {\n const names = Array.isArray(name) ? name : [name];\n names.forEach(n => form.clearErrors(n as Path<TData>));\n } else {\n form.clearErrors();\n }\n },\n\n // ---------------------------------------------------------------------\n // ARRAYS\n // ---------------------------------------------------------------------\n\n array: createArrayHelpers(\n (path) => form.getValues(path as Path<TData>) as unknown[],\n (path, value) => form.setValue(\n path as Path<TData>,\n value as PathValue<TData, Path<TData>>,\n { shouldDirty: true }\n )\n ),\n\n // ---------------------------------------------------------------------\n // OPTIONAL ENHANCED FEATURES\n // ---------------------------------------------------------------------\n\n onBlur: (name: string) => {\n // Mark field as touched\n const hasError = !!getNestedValue(form.formState.errors, name);\n\n // Trigger validation based on mode\n if (mode === 'onBlur' || mode === 'all') {\n form.trigger(name as Path<TData>);\n } else if (hasError && reValidateMode === 'onBlur') {\n // Re-validate if field has error and reValidateMode is onBlur\n form.trigger(name as Path<TData>);\n }\n },\n\n getFieldState: (name: string) => {\n const state = form.getFieldState(name as Path<TData>, form.formState);\n return {\n isDirty: state.isDirty,\n isTouched: state.isTouched,\n invalid: state.invalid,\n error: state.error?.message,\n };\n },\n\n setFocus: (name: string, options?: { shouldSelect?: boolean }) => {\n form.setFocus(name as Path<TData>, options);\n },\n\n unregister: (name: string | string[]) => {\n const names = Array.isArray(name) ? name : [name];\n names.forEach(n => form.unregister(n as Path<TData>));\n },\n };\n\n return api;\n}\n\n// =============================================================================\n// HELPER: Watch hook for external use\n// =============================================================================\n\n/**\n * Hook to watch specific field values reactively.\n * Use this when you need to react to field changes outside of components.\n * \n * @param control - The control object from useRhf (form.control)\n * @param name - Field path(s) to watch\n */\nexport function useRhfWatch<TData extends FieldValues, TValue = unknown>(\n control: Control<TData>,\n name: string | string[]\n): TValue {\n if (Array.isArray(name)) {\n return useWatch({ control, name: name as unknown as Path<TData>[] }) as TValue;\n }\n return useWatch({ control, name: name as Path<TData> }) as TValue;\n}\n\n// =============================================================================\n// UTILITIES\n// =============================================================================\n\n/**\n * Normalize RHF's nested error structure to flat string map.\n */\nfunction normalizeErrors<TData extends FieldValues>(\n errors: FieldErrors<TData>\n): Record<string, string | string[] | undefined> {\n const result: Record<string, string | string[] | undefined> = {};\n\n function traverse(obj: Record<string, unknown>, prefix = '') {\n for (const key in obj) {\n const path = prefix ? `${prefix}.${key}` : key;\n const value = obj[key];\n\n if (isRecord(value) && 'message' in value && typeof value.message === 'string') {\n // Leaf error\n result[path] = value.message;\n } else if (\n isRecord(value) &&\n 'root' in value &&\n isRecord(value.root) &&\n 'message' in value.root &&\n typeof value.root.message === 'string'\n ) {\n // Array root error\n result[path] = value.root.message;\n } else if (isRecord(value)) {\n // Nested object, traverse deeper\n traverse(value, path);\n }\n }\n }\n\n traverse(errors as unknown as Record<string, unknown>);\n return result;\n}\n\n\n\nfunction isRecord(value: unknown): value is Record<string, unknown> {\n return typeof value === 'object' && value !== null;\n}\n\n// =============================================================================\n// RE-EXPORTS FOR CONVENIENCE\n// =============================================================================\n\nexport type { UseFormReturn as RhfForm } from 'react-hook-form';","import { nanoid } from 'nanoid';\nimport type { ArrayHelpers } from '../types';\n\n/**\n * Creates a standardized set of array field manipulation methods.\n * Abstracts the difference between getting/setting values in different form libraries.\n * \n * @param getArray - Function to get current array value at a path\n * @param setArray - Function to set array value at a path\n */\nexport function createArrayHelpers(\n getArray: (path: string) => unknown,\n setArray: (path: string, value: unknown[]) => void\n): ArrayHelpers {\n const readArray = (path: string): unknown[] => {\n const value = getArray(path);\n return Array.isArray(value) ? value : [];\n };\n\n return {\n fields: <T = unknown>(path: string): Array<T & { id: string }> => {\n const arr = readArray(path);\n return arr.map((item, index) => {\n const itemObject =\n typeof item === 'object' && item !== null\n ? (item as Record<string, unknown>)\n : ({ value: item } as Record<string, unknown>);\n\n return {\n id: (itemObject.id as string) || `${path}-${index}`,\n ...(itemObject as T),\n };\n });\n },\n\n append: (path: string, value: unknown) => {\n const current = readArray(path);\n const itemWithId = ensureId(value);\n setArray(path, [...current, itemWithId]);\n },\n\n prepend: (path: string, value: unknown) => {\n const current = readArray(path);\n const itemWithId = ensureId(value);\n setArray(path, [itemWithId, ...current]);\n },\n\n insert: (path: string, index: number, value: unknown) => {\n const current = [...readArray(path)];\n const itemWithId = ensureId(value);\n current.splice(index, 0, itemWithId);\n setArray(path, current);\n },\n\n remove: (path: string, index: number) => {\n const current = [...readArray(path)];\n current.splice(index, 1);\n setArray(path, current);\n },\n\n move: (path: string, from: number, to: number) => {\n const current = [...readArray(path)];\n const [item] = current.splice(from, 1);\n current.splice(to, 0, item);\n setArray(path, current);\n },\n\n swap: (path: string, indexA: number, indexB: number) => {\n const current = [...readArray(path)];\n const temp = current[indexA];\n current[indexA] = current[indexB];\n current[indexB] = temp;\n setArray(path, current);\n },\n\n replace: (path: string, values: unknown[]) => {\n const itemsWithIds = values.map(ensureId);\n setArray(path, itemsWithIds);\n },\n\n update: (path: string, index: number, value: unknown) => {\n const current = [...readArray(path)];\n // Preserve existing ID if present\n const existingId = (current[index] as Record<string, unknown>)?.id;\n current[index] = {\n ...(typeof value === 'object' && value !== null ? value : {}),\n id: existingId || nanoid(),\n };\n setArray(path, current);\n },\n };\n}\n\n/**\n * Ensures an item has a unique ID for React keys.\n */\nfunction ensureId(value: unknown): unknown {\n if (typeof value === 'object' && value !== null) {\n const obj = value as Record<string, unknown>;\n if (!obj.id) {\n return { ...obj, id: nanoid() };\n }\n return obj;\n }\n return { value, id: nanoid() };\n}\n","// =============================================================================\n// COMMON UTILITIES\n// These are used by both the core package and registry field components.\n// =============================================================================\n\n/**\n * Generate a unique field ID from the field path.\n * Converts dot notation to dashes and prefixes with 'field-'.\n * Used for accessibility (htmlFor, id attributes).\n * \n * @example\n * generateFieldId('user.profile.email') => 'field-user-profile-email'\n * generateFieldId('items[0].name') => 'field-items-0-name'\n */\nexport function generateFieldId(path: string): string {\n return `field-${path.replace(/\\./g, \"-\").replace(/\\[/g, \"-\").replace(/\\]/g, \"\")}`;\n}\n\n/**\n * Safely retrieve a nested value from an object using a dot-notation path.\n * \n * @example\n * getNestedValue({ user: { name: 'John' } }, 'user.name') => 'John'\n * getNestedValue({ items: [{ id: 1 }] }, 'items.0.id') => 1\n */\nexport function getNestedValue(obj: unknown, path: string): unknown {\n if (!obj || !path) return undefined;\n return path.split(\".\").reduce<unknown>((acc: unknown, key: string) => {\n if (acc && typeof acc === \"object\" && acc !== null) {\n return (acc as Record<string, unknown>)[key];\n }\n return undefined;\n }, obj);\n}\n\n/**\n * Set a nested value in an object using a dot-notation path.\n * Creates intermediate objects/arrays as needed.\n * \n * @example\n * setNestedValue({}, 'user.name', 'John') => { user: { name: 'John' } }\n */\nexport function setNestedValue<T extends Record<string, unknown>>(\n obj: T,\n path: string,\n value: unknown\n): T {\n const keys = path.split(\".\");\n const result = { ...obj } as Record<string, unknown>;\n let current = result;\n\n for (let i = 0; i < keys.length - 1; i++) {\n const key = keys[i];\n if (!(key in current) || typeof current[key] !== \"object\") {\n // Check if next key is numeric (array index)\n const nextKey = keys[i + 1];\n current[key] = /^\\d+$/.test(nextKey) ? [] : {};\n } else {\n current[key] = Array.isArray(current[key])\n ? [...(current[key] as unknown[])]\n : { ...(current[key] as Record<string, unknown>) };\n }\n current = current[key] as Record<string, unknown>;\n }\n\n current[keys[keys.length - 1]] = value;\n return result as T;\n}\n\n/**\n * Format bytes into a human-readable string.\n * \n * @example\n * formatBytes(1024) => '1 KB'\n * formatBytes(1234567) => '1.18 MB'\n */\nexport function formatBytes(bytes: number, decimals = 2): string {\n if (bytes === 0) return '0 Bytes';\n\n const k = 1024;\n const dm = decimals < 0 ? 0 : decimals;\n const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];\n\n const i = Math.floor(Math.log(bytes) / Math.log(k));\n\n return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`;\n}\n\n/**\n * Flatten a nested object to dot-notation paths.\n * Useful for converting form library state (like dirtyFields, touchedFields)\n * to the flat format expected by FormState.\n * \n * @example\n * flattenNestedObject({ user: { name: true, email: true } })\n * // => { 'user.name': true, 'user.email': true }\n * \n * flattenNestedObject({ items: { 0: { title: true } } })\n * // => { 'items.0.title': true }\n */\nexport function flattenNestedObject(\n obj: Record<string, unknown>,\n prefix = ''\n): Record<string, boolean> {\n const result: Record<string, boolean> = {};\n\n for (const key in obj) {\n const path = prefix ? `${prefix}.${key}` : key;\n const value = obj[key];\n\n if (typeof value === 'boolean') {\n result[path] = value;\n } else if (value !== null && typeof value === 'object' && !Array.isArray(value)) {\n Object.assign(result, flattenNestedObject(value as Record<string, unknown>, path));\n }\n }\n\n return result;\n}\n\n"],"mappings":"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","names":["options"]}
|
package/dist/rhf.mjs
CHANGED
package/dist/schema.d.mts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { T as TextField, o as TextareaField, E as EmailField, P as PasswordField, N as NumberField, D as DateField, p as DatetimeField, r as SelectField,
|
|
2
|
-
export { g as AdapterFactory, f as AdapterOptions, A as ArrayHelpers, B as BaseField,
|
|
3
|
-
export { F as FieldToZod, u as FieldValidator, a as FieldsToShape, c as InferSchema, I as InferType, S as SchemaBuilder, b as SchemaBuilderMap, h as coerceToDate, g as coerceToNumber, q as collectFieldValidators, l as createArrayHelpers, d as createSchema, e as extractValidationConfig, f as fieldsToZodSchema, p as formatBytes, n as generateFieldId, o as getNestedValue, i as getPatternErrorMessage, r as getSiblingData, t as getValueByPath, j as isFileLike, k as isFileTypeAccepted, m as makeOptional, s as setNestedValue } from './utils-
|
|
1
|
+
import { T as TextField, o as TextareaField, E as EmailField, P as PasswordField, N as NumberField, D as DateField, p as DatetimeField, r as SelectField, w as RadioField, s as CheckboxGroupField, t as CheckboxField, u as SwitchField, y as UploadField, x as TagsField, z as ArrayField, F as Field, G as GroupField } from './adapter-u4raoNx9.mjs';
|
|
2
|
+
export { g as AdapterFactory, f as AdapterOptions, A as ArrayHelpers, B as BaseField, Q as BuzzFormSchema, K as CollapsibleField, C as ConditionContext, M as DataField, k as FieldComponentProps, j as FieldCondition, d as FieldError, l as FieldInputProps, m as FieldInputRenderFn, n as FieldStyle, L as FieldType, b as FormAdapter, a as FormConfig, W as FormSettings, c as FormState, O as LayoutField, e as Resolver, R as ResolverResult, H as RowField, q as SelectOption, S as SetValueOptions, I as Tab, J as TabsField, U as UseFormOptions, V as ValidationContext, i as ValidationFn, h as ValidationResult } from './adapter-u4raoNx9.mjs';
|
|
3
|
+
export { F as FieldToZod, u as FieldValidator, a as FieldsToShape, c as InferSchema, I as InferType, S as SchemaBuilder, b as SchemaBuilderMap, h as coerceToDate, g as coerceToNumber, q as collectFieldValidators, l as createArrayHelpers, d as createSchema, e as extractValidationConfig, f as fieldsToZodSchema, p as formatBytes, n as generateFieldId, o as getNestedValue, i as getPatternErrorMessage, r as getSiblingData, t as getValueByPath, j as isFileLike, k as isFileTypeAccepted, m as makeOptional, s as setNestedValue } from './utils-BksL2RlA.mjs';
|
|
4
4
|
import { z } from 'zod';
|
|
5
5
|
import 'react';
|
|
6
6
|
|
|
@@ -22,6 +22,7 @@ declare function createDateFieldSchema(field: DateField | DatetimeField): z.ZodT
|
|
|
22
22
|
|
|
23
23
|
declare function createSelectFieldSchema(field: SelectField): z.ZodTypeAny;
|
|
24
24
|
declare function createRadioFieldSchema(field: RadioField): z.ZodTypeAny;
|
|
25
|
+
declare function createCheckboxGroupFieldSchema(field: CheckboxGroupField): z.ZodTypeAny;
|
|
25
26
|
|
|
26
27
|
declare function createCheckboxFieldSchema(field: CheckboxField): z.ZodTypeAny;
|
|
27
28
|
declare function createSwitchFieldSchema(field: SwitchField): z.ZodTypeAny;
|
|
@@ -42,4 +43,4 @@ declare function createArrayFieldSchema(field: ArrayField, fieldsToZodSchema: Sc
|
|
|
42
43
|
*/
|
|
43
44
|
declare function createGroupFieldSchema(field: GroupField, fieldsToZodSchema: SchemaGenerator): z.ZodTypeAny;
|
|
44
45
|
|
|
45
|
-
export { ArrayField, CheckboxField, DateField, DatetimeField, EmailField, Field, GroupField, NumberField, PasswordField, RadioField, SelectField, SwitchField, TagsField, TextField, TextareaField, UploadField, createArrayFieldSchema, createCheckboxFieldSchema, createDateFieldSchema, createEmailFieldSchema, createGroupFieldSchema, createNumberFieldSchema, createPasswordFieldSchema, createRadioFieldSchema, createSelectFieldSchema, createSwitchFieldSchema, createTagsFieldSchema, createTextFieldSchema, createUploadFieldSchema };
|
|
46
|
+
export { ArrayField, CheckboxField, DateField, DatetimeField, EmailField, Field, GroupField, NumberField, PasswordField, RadioField, SelectField, SwitchField, TagsField, TextField, TextareaField, UploadField, createArrayFieldSchema, createCheckboxFieldSchema, createCheckboxGroupFieldSchema, createDateFieldSchema, createEmailFieldSchema, createGroupFieldSchema, createNumberFieldSchema, createPasswordFieldSchema, createRadioFieldSchema, createSelectFieldSchema, createSwitchFieldSchema, createTagsFieldSchema, createTextFieldSchema, createUploadFieldSchema };
|
package/dist/schema.d.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
import { T as TextField, o as TextareaField, E as EmailField, P as PasswordField, N as NumberField, D as DateField, p as DatetimeField, r as SelectField,
|
|
2
|
-
export { g as AdapterFactory, f as AdapterOptions, A as ArrayHelpers, B as BaseField,
|
|
3
|
-
export { F as FieldToZod, u as FieldValidator, a as FieldsToShape, c as InferSchema, I as InferType, S as SchemaBuilder, b as SchemaBuilderMap, h as coerceToDate, g as coerceToNumber, q as collectFieldValidators, l as createArrayHelpers, d as createSchema, e as extractValidationConfig, f as fieldsToZodSchema, p as formatBytes, n as generateFieldId, o as getNestedValue, i as getPatternErrorMessage, r as getSiblingData, t as getValueByPath, j as isFileLike, k as isFileTypeAccepted, m as makeOptional, s as setNestedValue } from './utils-
|
|
1
|
+
import { T as TextField, o as TextareaField, E as EmailField, P as PasswordField, N as NumberField, D as DateField, p as DatetimeField, r as SelectField, w as RadioField, s as CheckboxGroupField, t as CheckboxField, u as SwitchField, y as UploadField, x as TagsField, z as ArrayField, F as Field, G as GroupField } from './adapter-u4raoNx9.js';
|
|
2
|
+
export { g as AdapterFactory, f as AdapterOptions, A as ArrayHelpers, B as BaseField, Q as BuzzFormSchema, K as CollapsibleField, C as ConditionContext, M as DataField, k as FieldComponentProps, j as FieldCondition, d as FieldError, l as FieldInputProps, m as FieldInputRenderFn, n as FieldStyle, L as FieldType, b as FormAdapter, a as FormConfig, W as FormSettings, c as FormState, O as LayoutField, e as Resolver, R as ResolverResult, H as RowField, q as SelectOption, S as SetValueOptions, I as Tab, J as TabsField, U as UseFormOptions, V as ValidationContext, i as ValidationFn, h as ValidationResult } from './adapter-u4raoNx9.js';
|
|
3
|
+
export { F as FieldToZod, u as FieldValidator, a as FieldsToShape, c as InferSchema, I as InferType, S as SchemaBuilder, b as SchemaBuilderMap, h as coerceToDate, g as coerceToNumber, q as collectFieldValidators, l as createArrayHelpers, d as createSchema, e as extractValidationConfig, f as fieldsToZodSchema, p as formatBytes, n as generateFieldId, o as getNestedValue, i as getPatternErrorMessage, r as getSiblingData, t as getValueByPath, j as isFileLike, k as isFileTypeAccepted, m as makeOptional, s as setNestedValue } from './utils-oLqFuT9W.js';
|
|
4
4
|
import { z } from 'zod';
|
|
5
5
|
import 'react';
|
|
6
6
|
|
|
@@ -22,6 +22,7 @@ declare function createDateFieldSchema(field: DateField | DatetimeField): z.ZodT
|
|
|
22
22
|
|
|
23
23
|
declare function createSelectFieldSchema(field: SelectField): z.ZodTypeAny;
|
|
24
24
|
declare function createRadioFieldSchema(field: RadioField): z.ZodTypeAny;
|
|
25
|
+
declare function createCheckboxGroupFieldSchema(field: CheckboxGroupField): z.ZodTypeAny;
|
|
25
26
|
|
|
26
27
|
declare function createCheckboxFieldSchema(field: CheckboxField): z.ZodTypeAny;
|
|
27
28
|
declare function createSwitchFieldSchema(field: SwitchField): z.ZodTypeAny;
|
|
@@ -42,4 +43,4 @@ declare function createArrayFieldSchema(field: ArrayField, fieldsToZodSchema: Sc
|
|
|
42
43
|
*/
|
|
43
44
|
declare function createGroupFieldSchema(field: GroupField, fieldsToZodSchema: SchemaGenerator): z.ZodTypeAny;
|
|
44
45
|
|
|
45
|
-
export { ArrayField, CheckboxField, DateField, DatetimeField, EmailField, Field, GroupField, NumberField, PasswordField, RadioField, SelectField, SwitchField, TagsField, TextField, TextareaField, UploadField, createArrayFieldSchema, createCheckboxFieldSchema, createDateFieldSchema, createEmailFieldSchema, createGroupFieldSchema, createNumberFieldSchema, createPasswordFieldSchema, createRadioFieldSchema, createSelectFieldSchema, createSwitchFieldSchema, createTagsFieldSchema, createTextFieldSchema, createUploadFieldSchema };
|
|
46
|
+
export { ArrayField, CheckboxField, DateField, DatetimeField, EmailField, Field, GroupField, NumberField, PasswordField, RadioField, SelectField, SwitchField, TagsField, TextField, TextareaField, UploadField, createArrayFieldSchema, createCheckboxFieldSchema, createCheckboxGroupFieldSchema, createDateFieldSchema, createEmailFieldSchema, createGroupFieldSchema, createNumberFieldSchema, createPasswordFieldSchema, createRadioFieldSchema, createSelectFieldSchema, createSwitchFieldSchema, createTagsFieldSchema, createTextFieldSchema, createUploadFieldSchema };
|
package/dist/schema.js
CHANGED
|
@@ -26,6 +26,7 @@ __export(schema_exports, {
|
|
|
26
26
|
createArrayFieldSchema: () => createArrayFieldSchema,
|
|
27
27
|
createArrayHelpers: () => createArrayHelpers,
|
|
28
28
|
createCheckboxFieldSchema: () => createCheckboxFieldSchema,
|
|
29
|
+
createCheckboxGroupFieldSchema: () => createCheckboxGroupFieldSchema,
|
|
29
30
|
createDateFieldSchema: () => createDateFieldSchema,
|
|
30
31
|
createEmailFieldSchema: () => createEmailFieldSchema,
|
|
31
32
|
createGroupFieldSchema: () => createGroupFieldSchema,
|
|
@@ -158,6 +159,8 @@ function makeOptional(schema, fieldType) {
|
|
|
158
159
|
case "checkbox":
|
|
159
160
|
case "switch":
|
|
160
161
|
return schema;
|
|
162
|
+
case "checkbox-group":
|
|
163
|
+
return schema.optional().default([]);
|
|
161
164
|
case "tags":
|
|
162
165
|
case "array":
|
|
163
166
|
return schema.optional().default([]);
|
|
@@ -345,17 +348,51 @@ function createDateFieldSchema(field) {
|
|
|
345
348
|
|
|
346
349
|
// src/schema/builders/select.ts
|
|
347
350
|
var import_zod5 = require("zod");
|
|
348
|
-
var selectValueSchema = import_zod5.z.union(
|
|
349
|
-
|
|
350
|
-
|
|
351
|
-
|
|
352
|
-
|
|
351
|
+
var selectValueSchema = import_zod5.z.union(
|
|
352
|
+
[
|
|
353
|
+
import_zod5.z.string({ error: "Please select an option" }),
|
|
354
|
+
import_zod5.z.number({ error: "Please select an option" }),
|
|
355
|
+
import_zod5.z.boolean({ error: "Please select an option" })
|
|
356
|
+
],
|
|
357
|
+
{ error: "Please select an option" }
|
|
358
|
+
);
|
|
359
|
+
function applyMultiSelectConstraints(schema, config) {
|
|
360
|
+
const { minSelected, maxSelected, required } = config;
|
|
361
|
+
let next = schema;
|
|
362
|
+
if (minSelected !== void 0 && minSelected > 0) {
|
|
363
|
+
const minMsg = `Select at least ${minSelected} option${minSelected !== 1 ? "s" : ""}`;
|
|
364
|
+
if (required) {
|
|
365
|
+
next = next.min(minSelected, minMsg);
|
|
366
|
+
} else {
|
|
367
|
+
next = next.refine(
|
|
368
|
+
(val) => val.length === 0 || val.length >= minSelected,
|
|
369
|
+
{
|
|
370
|
+
message: minMsg
|
|
371
|
+
}
|
|
372
|
+
);
|
|
373
|
+
}
|
|
374
|
+
}
|
|
375
|
+
if (required && (minSelected === void 0 || minSelected === 0)) {
|
|
376
|
+
next = next.min(1, "Select at least one option");
|
|
377
|
+
}
|
|
378
|
+
if (maxSelected !== void 0) {
|
|
379
|
+
next = next.max(
|
|
380
|
+
maxSelected,
|
|
381
|
+
`Select at most ${maxSelected} option${maxSelected !== 1 ? "s" : ""}`
|
|
382
|
+
);
|
|
383
|
+
}
|
|
384
|
+
return next;
|
|
385
|
+
}
|
|
353
386
|
function createSelectFieldSchema(field) {
|
|
354
387
|
if (field.hasMany) {
|
|
355
|
-
let arraySchema = import_zod5.z.array(selectValueSchema, {
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
388
|
+
let arraySchema = import_zod5.z.array(selectValueSchema, {
|
|
389
|
+
error: "Invalid selection"
|
|
390
|
+
});
|
|
391
|
+
arraySchema = applyMultiSelectConstraints(arraySchema, {
|
|
392
|
+
minSelected: field.minSelected,
|
|
393
|
+
maxSelected: field.maxSelected,
|
|
394
|
+
required: field.required
|
|
395
|
+
});
|
|
359
396
|
if (!field.required) {
|
|
360
397
|
return arraySchema.optional().default([]);
|
|
361
398
|
}
|
|
@@ -386,6 +423,18 @@ function createRadioFieldSchema(field) {
|
|
|
386
423
|
}
|
|
387
424
|
return schema;
|
|
388
425
|
}
|
|
426
|
+
function createCheckboxGroupFieldSchema(field) {
|
|
427
|
+
let schema = import_zod5.z.array(selectValueSchema, { error: "Invalid selection" });
|
|
428
|
+
schema = applyMultiSelectConstraints(schema, {
|
|
429
|
+
minSelected: field.minSelected,
|
|
430
|
+
maxSelected: field.maxSelected,
|
|
431
|
+
required: field.required
|
|
432
|
+
});
|
|
433
|
+
if (!field.required) {
|
|
434
|
+
return makeOptional(schema, "checkbox-group");
|
|
435
|
+
}
|
|
436
|
+
return schema;
|
|
437
|
+
}
|
|
389
438
|
|
|
390
439
|
// src/schema/builders/boolean.ts
|
|
391
440
|
var import_zod6 = require("zod");
|
|
@@ -550,6 +599,8 @@ function fieldToZod(field) {
|
|
|
550
599
|
return createDateFieldSchema(field);
|
|
551
600
|
case "select":
|
|
552
601
|
return createSelectFieldSchema(field);
|
|
602
|
+
case "checkbox-group":
|
|
603
|
+
return createCheckboxGroupFieldSchema(field);
|
|
553
604
|
case "radio":
|
|
554
605
|
return createRadioFieldSchema(field);
|
|
555
606
|
case "checkbox":
|
|
@@ -614,44 +665,50 @@ function createSchema(fields) {
|
|
|
614
665
|
// src/utils/array.ts
|
|
615
666
|
var import_nanoid = require("nanoid");
|
|
616
667
|
function createArrayHelpers(getArray, setArray) {
|
|
668
|
+
const readArray = (path) => {
|
|
669
|
+
const value = getArray(path);
|
|
670
|
+
return Array.isArray(value) ? value : [];
|
|
671
|
+
};
|
|
617
672
|
return {
|
|
618
673
|
fields: (path) => {
|
|
619
|
-
const arr =
|
|
620
|
-
|
|
621
|
-
|
|
622
|
-
|
|
623
|
-
|
|
624
|
-
|
|
674
|
+
const arr = readArray(path);
|
|
675
|
+
return arr.map((item, index) => {
|
|
676
|
+
const itemObject = typeof item === "object" && item !== null ? item : { value: item };
|
|
677
|
+
return {
|
|
678
|
+
id: itemObject.id || `${path}-${index}`,
|
|
679
|
+
...itemObject
|
|
680
|
+
};
|
|
681
|
+
});
|
|
625
682
|
},
|
|
626
683
|
append: (path, value) => {
|
|
627
|
-
const current =
|
|
684
|
+
const current = readArray(path);
|
|
628
685
|
const itemWithId = ensureId(value);
|
|
629
686
|
setArray(path, [...current, itemWithId]);
|
|
630
687
|
},
|
|
631
688
|
prepend: (path, value) => {
|
|
632
|
-
const current =
|
|
689
|
+
const current = readArray(path);
|
|
633
690
|
const itemWithId = ensureId(value);
|
|
634
691
|
setArray(path, [itemWithId, ...current]);
|
|
635
692
|
},
|
|
636
693
|
insert: (path, index, value) => {
|
|
637
|
-
const current = [...
|
|
694
|
+
const current = [...readArray(path)];
|
|
638
695
|
const itemWithId = ensureId(value);
|
|
639
696
|
current.splice(index, 0, itemWithId);
|
|
640
697
|
setArray(path, current);
|
|
641
698
|
},
|
|
642
699
|
remove: (path, index) => {
|
|
643
|
-
const current = [...
|
|
700
|
+
const current = [...readArray(path)];
|
|
644
701
|
current.splice(index, 1);
|
|
645
702
|
setArray(path, current);
|
|
646
703
|
},
|
|
647
704
|
move: (path, from, to) => {
|
|
648
|
-
const current = [...
|
|
705
|
+
const current = [...readArray(path)];
|
|
649
706
|
const [item] = current.splice(from, 1);
|
|
650
707
|
current.splice(to, 0, item);
|
|
651
708
|
setArray(path, current);
|
|
652
709
|
},
|
|
653
710
|
swap: (path, indexA, indexB) => {
|
|
654
|
-
const current = [...
|
|
711
|
+
const current = [...readArray(path)];
|
|
655
712
|
const temp = current[indexA];
|
|
656
713
|
current[indexA] = current[indexB];
|
|
657
714
|
current[indexB] = temp;
|
|
@@ -662,7 +719,7 @@ function createArrayHelpers(getArray, setArray) {
|
|
|
662
719
|
setArray(path, itemsWithIds);
|
|
663
720
|
},
|
|
664
721
|
update: (path, index, value) => {
|
|
665
|
-
const current = [...
|
|
722
|
+
const current = [...readArray(path)];
|
|
666
723
|
const existingId = current[index]?.id;
|
|
667
724
|
current[index] = {
|
|
668
725
|
...typeof value === "object" && value !== null ? value : {},
|
|
@@ -729,6 +786,7 @@ function formatBytes(bytes, decimals = 2) {
|
|
|
729
786
|
createArrayFieldSchema,
|
|
730
787
|
createArrayHelpers,
|
|
731
788
|
createCheckboxFieldSchema,
|
|
789
|
+
createCheckboxGroupFieldSchema,
|
|
732
790
|
createDateFieldSchema,
|
|
733
791
|
createEmailFieldSchema,
|
|
734
792
|
createGroupFieldSchema,
|