@buildnbuzz/buzzform 0.1.0 → 0.1.2

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/zod.mjs CHANGED
@@ -1,24 +1,71 @@
1
+ import {
2
+ collectFieldValidators,
3
+ getSiblingData,
4
+ getValueByPath
5
+ } from "./chunk-63LF7K4O.mjs";
6
+
1
7
  // src/resolvers/zod.ts
2
8
  import { z } from "zod";
3
9
  function zodResolver(schema) {
10
+ const schemaWithFields = schema;
11
+ const fieldValidators = schemaWithFields.fields ? collectFieldValidators(schemaWithFields.fields) : [];
4
12
  return async (values) => {
13
+ const errors = {};
14
+ let parsedValues;
5
15
  try {
6
- const parsed = await schema.parseAsync(values);
7
- return {
8
- values: parsed,
9
- errors: {}
10
- };
16
+ parsedValues = await schema.parseAsync(values);
11
17
  } catch (error) {
12
18
  if (isZodError(error)) {
13
- return {
14
- values: {},
15
- errors: mapZodErrors(error)
16
- };
19
+ Object.assign(errors, mapZodErrors(error));
20
+ } else {
21
+ throw error;
22
+ }
23
+ }
24
+ if (fieldValidators.length > 0) {
25
+ const customErrors = await runFieldValidators(
26
+ fieldValidators,
27
+ values
28
+ );
29
+ for (const [path, error] of Object.entries(customErrors)) {
30
+ if (!errors[path]) {
31
+ errors[path] = error;
32
+ }
17
33
  }
18
- throw error;
19
34
  }
35
+ if (Object.keys(errors).length === 0 && parsedValues !== void 0) {
36
+ return { values: parsedValues, errors: {} };
37
+ }
38
+ return { values: {}, errors };
20
39
  };
21
40
  }
41
+ async function runFieldValidators(validators, data) {
42
+ const errors = {};
43
+ await Promise.all(
44
+ validators.map(async ({ path, fn }) => {
45
+ const value = getValueByPath(data, path);
46
+ const siblingData = getSiblingData(data, path);
47
+ try {
48
+ const result = await fn(value, {
49
+ data,
50
+ siblingData,
51
+ path: path.split(".")
52
+ });
53
+ if (result !== true) {
54
+ errors[path] = {
55
+ type: "custom",
56
+ message: typeof result === "string" ? result : "Validation failed"
57
+ };
58
+ }
59
+ } catch (error) {
60
+ errors[path] = {
61
+ type: "custom",
62
+ message: error instanceof Error ? error.message : "Validation error"
63
+ };
64
+ }
65
+ })
66
+ );
67
+ return errors;
68
+ }
22
69
  function mapZodErrors(error) {
23
70
  const errors = {};
24
71
  for (const issue of error.issues) {
@@ -38,18 +85,24 @@ function issuePath(issue) {
38
85
  function issueType(issue) {
39
86
  switch (issue.code) {
40
87
  case "invalid_type":
41
- if (issue.received === "undefined") return "required";
88
+ if ("received" in issue && issue.received === "undefined") return "required";
42
89
  return "type";
43
90
  case "too_small":
44
- return issue.type === "string" ? "minLength" : "min";
91
+ if ("origin" in issue && issue.origin === "string") return "minLength";
92
+ return "min";
45
93
  case "too_big":
46
- return issue.type === "string" ? "maxLength" : "max";
47
- case "invalid_string":
48
- return issue.validation?.toString() || "pattern";
94
+ if ("origin" in issue && issue.origin === "string") return "maxLength";
95
+ return "max";
96
+ case "invalid_format": {
97
+ const formatIssue = issue;
98
+ if (formatIssue.format === "regex") return "pattern";
99
+ if (typeof formatIssue.format === "string") return formatIssue.format;
100
+ return "pattern";
101
+ }
49
102
  case "custom":
50
103
  return "custom";
51
104
  default:
52
- return issue.code;
105
+ return issue.code ?? "validation";
53
106
  }
54
107
  }
55
108
  function isZodError(error) {
package/dist/zod.mjs.map CHANGED
@@ -1 +1 @@
1
- {"version":3,"sources":["../src/resolvers/zod.ts"],"sourcesContent":["import type { ZodSchema, ZodError, ZodIssue } from 'zod';\r\nimport type { Resolver, FieldError, ResolverResult } from '../types';\r\n\r\n// =============================================================================\r\n// ZOD RESOLVER\r\n// =============================================================================\r\n\r\n/**\r\n * Creates a validation resolver from a Zod schema.\r\n * \r\n * The resolver validates form values against the schema and returns:\r\n * - `{ values }` if validation passes (with transformed/parsed data)\r\n * - `{ errors }` if validation fails (with field-level error messages)\r\n * \r\n * @param schema - A Zod schema to validate against\r\n * @returns A Resolver function compatible with BuzzForm adapters\r\n * \r\n * @example\r\n * import { z } from '@buildnbuzz/buzzform/zod';\r\n * import { zodResolver } from '@buildnbuzz/buzzform';\r\n * \r\n * const schema = z.object({\r\n * email: z.string().email('Invalid email'),\r\n * age: z.number().min(18, 'Must be at least 18'),\r\n * });\r\n * \r\n * const form = useRhf({\r\n * resolver: zodResolver(schema),\r\n * defaultValues: { email: '', age: 0 },\r\n * });\r\n */\r\nexport function zodResolver<TData>(\r\n schema: ZodSchema<TData>\r\n): Resolver<TData> {\r\n return async (values: TData): Promise<ResolverResult<TData>> => {\r\n try {\r\n // Parse and validate - this also transforms the data\r\n const parsed = await schema.parseAsync(values);\r\n\r\n return {\r\n values: parsed,\r\n errors: {},\r\n };\r\n } catch (error) {\r\n // Handle Zod validation errors\r\n if (isZodError(error)) {\r\n return {\r\n values: {} as TData,\r\n errors: mapZodErrors(error),\r\n };\r\n }\r\n\r\n // Re-throw unexpected errors\r\n throw error;\r\n }\r\n };\r\n}\r\n\r\n// =============================================================================\r\n// ERROR MAPPING\r\n// =============================================================================\r\n\r\n/**\r\n * Maps Zod validation errors to our FieldError format.\r\n * Handles nested paths (e.g., \"address.city\", \"items.0.name\").\r\n */\r\nfunction mapZodErrors(error: ZodError): Record<string, FieldError> {\r\n const errors: Record<string, FieldError> = {};\r\n\r\n for (const issue of error.issues) {\r\n const path = issuePath(issue);\r\n\r\n // Only set the first error for each path\r\n if (!errors[path]) {\r\n errors[path] = {\r\n type: issueType(issue),\r\n message: issue.message,\r\n };\r\n }\r\n }\r\n\r\n return errors;\r\n}\r\n\r\n/**\r\n * Convert Zod issue path to dot-notation string.\r\n * ['address', 'city'] → 'address.city'\r\n * ['items', 0, 'name'] → 'items.0.name'\r\n */\r\nfunction issuePath(issue: ZodIssue): string {\r\n return issue.path.map(String).join('.');\r\n}\r\n\r\n/**\r\n * Map Zod issue code to a simpler type string.\r\n */\r\nfunction issueType(issue: ZodIssue): string {\r\n switch (issue.code) {\r\n case 'invalid_type':\r\n if (issue.received === 'undefined') return 'required';\r\n return 'type';\r\n case 'too_small':\r\n return issue.type === 'string' ? 'minLength' : 'min';\r\n case 'too_big':\r\n return issue.type === 'string' ? 'maxLength' : 'max';\r\n case 'invalid_string':\r\n return issue.validation?.toString() || 'pattern';\r\n case 'custom':\r\n return 'custom';\r\n default:\r\n return issue.code;\r\n }\r\n}\r\n\r\n/**\r\n * Type guard to check if an error is a ZodError.\r\n */\r\nfunction isZodError(error: unknown): error is ZodError {\r\n return (\r\n typeof error === 'object' &&\r\n error !== null &&\r\n 'issues' in error &&\r\n Array.isArray((error as ZodError).issues)\r\n );\r\n}\r\n\r\n// =============================================================================\r\n// RE-EXPORTS FOR CONVENIENCE\r\n// =============================================================================\r\n\r\nexport type { ZodSchema } from 'zod';\r\nexport { z } from 'zod';"],"mappings":";AAmIA,SAAS,SAAS;AApGX,SAAS,YACZ,QACe;AACf,SAAO,OAAO,WAAkD;AAC5D,QAAI;AAEA,YAAM,SAAS,MAAM,OAAO,WAAW,MAAM;AAE7C,aAAO;AAAA,QACH,QAAQ;AAAA,QACR,QAAQ,CAAC;AAAA,MACb;AAAA,IACJ,SAAS,OAAO;AAEZ,UAAI,WAAW,KAAK,GAAG;AACnB,eAAO;AAAA,UACH,QAAQ,CAAC;AAAA,UACT,QAAQ,aAAa,KAAK;AAAA,QAC9B;AAAA,MACJ;AAGA,YAAM;AAAA,IACV;AAAA,EACJ;AACJ;AAUA,SAAS,aAAa,OAA6C;AAC/D,QAAM,SAAqC,CAAC;AAE5C,aAAW,SAAS,MAAM,QAAQ;AAC9B,UAAM,OAAO,UAAU,KAAK;AAG5B,QAAI,CAAC,OAAO,IAAI,GAAG;AACf,aAAO,IAAI,IAAI;AAAA,QACX,MAAM,UAAU,KAAK;AAAA,QACrB,SAAS,MAAM;AAAA,MACnB;AAAA,IACJ;AAAA,EACJ;AAEA,SAAO;AACX;AAOA,SAAS,UAAU,OAAyB;AACxC,SAAO,MAAM,KAAK,IAAI,MAAM,EAAE,KAAK,GAAG;AAC1C;AAKA,SAAS,UAAU,OAAyB;AACxC,UAAQ,MAAM,MAAM;AAAA,IAChB,KAAK;AACD,UAAI,MAAM,aAAa,YAAa,QAAO;AAC3C,aAAO;AAAA,IACX,KAAK;AACD,aAAO,MAAM,SAAS,WAAW,cAAc;AAAA,IACnD,KAAK;AACD,aAAO,MAAM,SAAS,WAAW,cAAc;AAAA,IACnD,KAAK;AACD,aAAO,MAAM,YAAY,SAAS,KAAK;AAAA,IAC3C,KAAK;AACD,aAAO;AAAA,IACX;AACI,aAAO,MAAM;AAAA,EACrB;AACJ;AAKA,SAAS,WAAW,OAAmC;AACnD,SACI,OAAO,UAAU,YACjB,UAAU,QACV,YAAY,SACZ,MAAM,QAAS,MAAmB,MAAM;AAEhD;","names":[]}
1
+ {"version":3,"sources":["../src/resolvers/zod.ts"],"sourcesContent":["import { type z } from 'zod';\nimport type { Resolver, FieldError, ResolverResult, Field } from '../types';\nimport { collectFieldValidators, getSiblingData, getValueByPath, type FieldValidator } from '../schema/helpers';\n\n// =============================================================================\n// ZOD RESOLVER\n// =============================================================================\n\ntype ZodIssue = z.core.$ZodIssue;\ntype ZodError = z.ZodError;\n\n// Schema with attached fields from createSchema()\ntype SchemaWithFields = z.ZodType & { fields?: readonly Field[] };\n\n/**\n * Creates a validation resolver from a Zod schema.\n * \n * Custom field validators (field.validate) are run separately from the base schema\n * to ensure they execute even when other fields have errors.\n */\nexport function zodResolver<TData>(\n schema: z.ZodType<TData>\n): Resolver<TData> {\n // Extract field validators from schema.fields (if present)\n const schemaWithFields = schema as SchemaWithFields;\n const fieldValidators = schemaWithFields.fields\n ? collectFieldValidators(schemaWithFields.fields)\n : [];\n\n return async (values: TData): Promise<ResolverResult<TData>> => {\n const errors: Record<string, FieldError> = {};\n let parsedValues: TData | undefined;\n\n // Phase 1: Run base schema validation\n try {\n parsedValues = await schema.parseAsync(values);\n } catch (error) {\n if (isZodError(error)) {\n Object.assign(errors, mapZodErrors(error));\n } else {\n throw error;\n }\n }\n\n // Phase 2: Run custom field validators (always runs, even if base fails)\n if (fieldValidators.length > 0) {\n const customErrors = await runFieldValidators(\n fieldValidators,\n values as Record<string, unknown>\n );\n // Merge, but don't overwrite existing errors\n for (const [path, error] of Object.entries(customErrors)) {\n if (!errors[path]) {\n errors[path] = error;\n }\n }\n }\n\n // Return result\n if (Object.keys(errors).length === 0 && parsedValues !== undefined) {\n return { values: parsedValues, errors: {} };\n }\n\n return { values: {} as TData, errors };\n };\n}\n\n/**\n * Run all field validators and collect errors.\n */\nasync function runFieldValidators(\n validators: FieldValidator[],\n data: Record<string, unknown>\n): Promise<Record<string, FieldError>> {\n const errors: Record<string, FieldError> = {};\n\n await Promise.all(\n validators.map(async ({ path, fn }) => {\n const value = getValueByPath(data, path);\n const siblingData = getSiblingData(data, path);\n\n try {\n const result = await fn(value, {\n data,\n siblingData,\n path: path.split('.'),\n });\n\n if (result !== true) {\n errors[path] = {\n type: 'custom',\n message: typeof result === 'string' ? result : 'Validation failed',\n };\n }\n } catch (error) {\n errors[path] = {\n type: 'custom',\n message: error instanceof Error ? error.message : 'Validation error',\n };\n }\n })\n );\n\n return errors;\n}\n\n// =============================================================================\n// ERROR MAPPING\n// =============================================================================\n\nfunction mapZodErrors(error: ZodError): Record<string, FieldError> {\n const errors: Record<string, FieldError> = {};\n\n for (const issue of error.issues) {\n const path = issuePath(issue);\n if (!errors[path]) {\n errors[path] = {\n type: issueType(issue),\n message: issue.message,\n };\n }\n }\n\n return errors;\n}\n\nfunction issuePath(issue: ZodIssue): string {\n return issue.path.map(String).join('.');\n}\n\nfunction issueType(issue: ZodIssue): string {\n switch (issue.code) {\n case 'invalid_type':\n if ('received' in issue && issue.received === 'undefined') return 'required';\n return 'type';\n case 'too_small':\n if ('origin' in issue && issue.origin === 'string') return 'minLength';\n return 'min';\n case 'too_big':\n if ('origin' in issue && issue.origin === 'string') return 'maxLength';\n return 'max';\n case 'invalid_format': {\n const formatIssue = issue as { format?: string };\n if (formatIssue.format === 'regex') return 'pattern';\n if (typeof formatIssue.format === 'string') return formatIssue.format;\n return 'pattern';\n }\n case 'custom':\n return 'custom';\n default:\n return issue.code ?? 'validation';\n }\n}\n\nfunction isZodError(error: unknown): error is ZodError {\n return (\n typeof error === 'object' &&\n error !== null &&\n 'issues' in error &&\n Array.isArray((error as ZodError).issues)\n );\n}\n\n// =============================================================================\n// RE-EXPORTS\n// =============================================================================\n\nexport type { ZodType as ZodSchema } from 'zod';\nexport { z } from 'zod';"],"mappings":";;;;;;;AAwKA,SAAS,SAAS;AApJX,SAAS,YACZ,QACe;AAEf,QAAM,mBAAmB;AACzB,QAAM,kBAAkB,iBAAiB,SACnC,uBAAuB,iBAAiB,MAAM,IAC9C,CAAC;AAEP,SAAO,OAAO,WAAkD;AAC5D,UAAM,SAAqC,CAAC;AAC5C,QAAI;AAGJ,QAAI;AACA,qBAAe,MAAM,OAAO,WAAW,MAAM;AAAA,IACjD,SAAS,OAAO;AACZ,UAAI,WAAW,KAAK,GAAG;AACnB,eAAO,OAAO,QAAQ,aAAa,KAAK,CAAC;AAAA,MAC7C,OAAO;AACH,cAAM;AAAA,MACV;AAAA,IACJ;AAGA,QAAI,gBAAgB,SAAS,GAAG;AAC5B,YAAM,eAAe,MAAM;AAAA,QACvB;AAAA,QACA;AAAA,MACJ;AAEA,iBAAW,CAAC,MAAM,KAAK,KAAK,OAAO,QAAQ,YAAY,GAAG;AACtD,YAAI,CAAC,OAAO,IAAI,GAAG;AACf,iBAAO,IAAI,IAAI;AAAA,QACnB;AAAA,MACJ;AAAA,IACJ;AAGA,QAAI,OAAO,KAAK,MAAM,EAAE,WAAW,KAAK,iBAAiB,QAAW;AAChE,aAAO,EAAE,QAAQ,cAAc,QAAQ,CAAC,EAAE;AAAA,IAC9C;AAEA,WAAO,EAAE,QAAQ,CAAC,GAAY,OAAO;AAAA,EACzC;AACJ;AAKA,eAAe,mBACX,YACA,MACmC;AACnC,QAAM,SAAqC,CAAC;AAE5C,QAAM,QAAQ;AAAA,IACV,WAAW,IAAI,OAAO,EAAE,MAAM,GAAG,MAAM;AACnC,YAAM,QAAQ,eAAe,MAAM,IAAI;AACvC,YAAM,cAAc,eAAe,MAAM,IAAI;AAE7C,UAAI;AACA,cAAM,SAAS,MAAM,GAAG,OAAO;AAAA,UAC3B;AAAA,UACA;AAAA,UACA,MAAM,KAAK,MAAM,GAAG;AAAA,QACxB,CAAC;AAED,YAAI,WAAW,MAAM;AACjB,iBAAO,IAAI,IAAI;AAAA,YACX,MAAM;AAAA,YACN,SAAS,OAAO,WAAW,WAAW,SAAS;AAAA,UACnD;AAAA,QACJ;AAAA,MACJ,SAAS,OAAO;AACZ,eAAO,IAAI,IAAI;AAAA,UACX,MAAM;AAAA,UACN,SAAS,iBAAiB,QAAQ,MAAM,UAAU;AAAA,QACtD;AAAA,MACJ;AAAA,IACJ,CAAC;AAAA,EACL;AAEA,SAAO;AACX;AAMA,SAAS,aAAa,OAA6C;AAC/D,QAAM,SAAqC,CAAC;AAE5C,aAAW,SAAS,MAAM,QAAQ;AAC9B,UAAM,OAAO,UAAU,KAAK;AAC5B,QAAI,CAAC,OAAO,IAAI,GAAG;AACf,aAAO,IAAI,IAAI;AAAA,QACX,MAAM,UAAU,KAAK;AAAA,QACrB,SAAS,MAAM;AAAA,MACnB;AAAA,IACJ;AAAA,EACJ;AAEA,SAAO;AACX;AAEA,SAAS,UAAU,OAAyB;AACxC,SAAO,MAAM,KAAK,IAAI,MAAM,EAAE,KAAK,GAAG;AAC1C;AAEA,SAAS,UAAU,OAAyB;AACxC,UAAQ,MAAM,MAAM;AAAA,IAChB,KAAK;AACD,UAAI,cAAc,SAAS,MAAM,aAAa,YAAa,QAAO;AAClE,aAAO;AAAA,IACX,KAAK;AACD,UAAI,YAAY,SAAS,MAAM,WAAW,SAAU,QAAO;AAC3D,aAAO;AAAA,IACX,KAAK;AACD,UAAI,YAAY,SAAS,MAAM,WAAW,SAAU,QAAO;AAC3D,aAAO;AAAA,IACX,KAAK,kBAAkB;AACnB,YAAM,cAAc;AACpB,UAAI,YAAY,WAAW,QAAS,QAAO;AAC3C,UAAI,OAAO,YAAY,WAAW,SAAU,QAAO,YAAY;AAC/D,aAAO;AAAA,IACX;AAAA,IACA,KAAK;AACD,aAAO;AAAA,IACX;AACI,aAAO,MAAM,QAAQ;AAAA,EAC7B;AACJ;AAEA,SAAS,WAAW,OAAmC;AACnD,SACI,OAAO,UAAU,YACjB,UAAU,QACV,YAAY,SACZ,MAAM,QAAS,MAAmB,MAAM;AAEhD;","names":[]}
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@buildnbuzz/buzzform",
3
- "version": "0.1.0",
3
+ "version": "0.1.2",
4
4
  "description": "Simple React form library for shadcn/ui. Declare fields, customize rendering, get live validation with minimal boilerplate.",
5
5
  "author": "Parth Lad <parth@buildnbuzz.com>",
6
6
  "license": "MIT",
@@ -74,7 +74,7 @@
74
74
  "peerDependencies": {
75
75
  "react": "^18 || ^19",
76
76
  "react-hook-form": "^7.0.0",
77
- "zod": "^3.0.0"
77
+ "zod": "^4.0.0"
78
78
  },
79
79
  "peerDependenciesMeta": {
80
80
  "zod": {
@@ -93,9 +93,10 @@
93
93
  "react": "^19.0.0",
94
94
  "react-hook-form": "^7.69.0",
95
95
  "tsup": "^8.3.5",
96
+ "tsx": "^4.21.0",
96
97
  "typescript": "^5.9.2",
97
98
  "typescript-eslint": "^8.51.0",
98
- "zod": "^3.25.0"
99
+ "zod": "^4.0.0"
99
100
  },
100
101
  "publishConfig": {
101
102
  "access": "public"
@@ -1 +0,0 @@
1
- {"version":3,"sources":["../src/utils/array.ts","../src/lib/utils.ts","../src/lib/field.ts"],"sourcesContent":["import { nanoid } from 'nanoid';\r\nimport type { ArrayHelpers } from '../types';\r\n\r\n/**\r\n * Creates a standardized set of array field manipulation methods.\r\n * Abstracts the difference between getting/setting values in different form libraries.\r\n * \r\n * @param getArray - Function to get current array value at a path\r\n * @param setArray - Function to set array value at a path\r\n */\r\nexport function createArrayHelpers(\r\n getArray: (path: string) => unknown[],\r\n setArray: (path: string, value: unknown[]) => void\r\n): ArrayHelpers {\r\n return {\r\n fields: <T = unknown>(path: string): Array<T & { id: string }> => {\r\n const arr = getArray(path);\r\n if (!Array.isArray(arr)) return [];\r\n return arr.map((item, index) => ({\r\n id: (item as Record<string, unknown>)?.id as string || `${path}-${index}`,\r\n ...item as T,\r\n }));\r\n },\r\n\r\n append: (path: string, value: unknown) => {\r\n const current = getArray(path) || [];\r\n const itemWithId = ensureId(value);\r\n setArray(path, [...current, itemWithId]);\r\n },\r\n\r\n prepend: (path: string, value: unknown) => {\r\n const current = getArray(path) || [];\r\n const itemWithId = ensureId(value);\r\n setArray(path, [itemWithId, ...current]);\r\n },\r\n\r\n insert: (path: string, index: number, value: unknown) => {\r\n const current = [...(getArray(path) || [])];\r\n const itemWithId = ensureId(value);\r\n current.splice(index, 0, itemWithId);\r\n setArray(path, current);\r\n },\r\n\r\n remove: (path: string, index: number) => {\r\n const current = [...(getArray(path) || [])];\r\n current.splice(index, 1);\r\n setArray(path, current);\r\n },\r\n\r\n move: (path: string, from: number, to: number) => {\r\n const current = [...(getArray(path) || [])];\r\n const [item] = current.splice(from, 1);\r\n current.splice(to, 0, item);\r\n setArray(path, current);\r\n },\r\n\r\n swap: (path: string, indexA: number, indexB: number) => {\r\n const current = [...(getArray(path) || [])];\r\n const temp = current[indexA];\r\n current[indexA] = current[indexB];\r\n current[indexB] = temp;\r\n setArray(path, current);\r\n },\r\n\r\n replace: (path: string, values: unknown[]) => {\r\n const itemsWithIds = values.map(ensureId);\r\n setArray(path, itemsWithIds);\r\n },\r\n\r\n update: (path: string, index: number, value: unknown) => {\r\n const current = [...(getArray(path) || [])];\r\n // Preserve existing ID if present\r\n const existingId = (current[index] as Record<string, unknown>)?.id;\r\n current[index] = {\r\n ...(typeof value === 'object' && value !== null ? value : {}),\r\n id: existingId || nanoid(),\r\n };\r\n setArray(path, current);\r\n },\r\n };\r\n}\r\n\r\n/**\r\n * Ensures an item has a unique ID for React keys.\r\n */\r\nfunction ensureId(value: unknown): unknown {\r\n if (typeof value === 'object' && value !== null) {\r\n const obj = value as Record<string, unknown>;\r\n if (!obj.id) {\r\n return { ...obj, id: nanoid() };\r\n }\r\n return obj;\r\n }\r\n return { value, id: nanoid() };\r\n}\r\n","// =============================================================================\r\n// COMMON UTILITIES\r\n// These are used by both the core package and registry field components.\r\n// =============================================================================\r\n\r\n/**\r\n * Generate a unique field ID from the field path.\r\n * Converts dot notation to dashes and prefixes with 'field-'.\r\n * Used for accessibility (htmlFor, id attributes).\r\n * \r\n * @example\r\n * generateFieldId('user.profile.email') => 'field-user-profile-email'\r\n * generateFieldId('items[0].name') => 'field-items-0-name'\r\n */\r\nexport function generateFieldId(path: string): string {\r\n return `field-${path.replace(/\\./g, \"-\").replace(/\\[/g, \"-\").replace(/\\]/g, \"\")}`;\r\n}\r\n\r\n/**\r\n * Safely retrieve a nested value from an object using a dot-notation path.\r\n * \r\n * @example\r\n * getNestedValue({ user: { name: 'John' } }, 'user.name') => 'John'\r\n * getNestedValue({ items: [{ id: 1 }] }, 'items.0.id') => 1\r\n */\r\nexport function getNestedValue(obj: unknown, path: string): unknown {\r\n if (!obj || !path) return undefined;\r\n return path.split(\".\").reduce<unknown>((acc: unknown, key: string) => {\r\n if (acc && typeof acc === \"object\" && acc !== null) {\r\n return (acc as Record<string, unknown>)[key];\r\n }\r\n return undefined;\r\n }, obj);\r\n}\r\n\r\n/**\r\n * Set a nested value in an object using a dot-notation path.\r\n * Creates intermediate objects/arrays as needed.\r\n * \r\n * @example\r\n * setNestedValue({}, 'user.name', 'John') => { user: { name: 'John' } }\r\n */\r\nexport function setNestedValue<T extends Record<string, unknown>>(\r\n obj: T,\r\n path: string,\r\n value: unknown\r\n): T {\r\n const keys = path.split(\".\");\r\n const result = { ...obj } as Record<string, unknown>;\r\n let current = result;\r\n\r\n for (let i = 0; i < keys.length - 1; i++) {\r\n const key = keys[i];\r\n if (!(key in current) || typeof current[key] !== \"object\") {\r\n // Check if next key is numeric (array index)\r\n const nextKey = keys[i + 1];\r\n current[key] = /^\\d+$/.test(nextKey) ? [] : {};\r\n } else {\r\n current[key] = Array.isArray(current[key])\r\n ? [...(current[key] as unknown[])]\r\n : { ...(current[key] as Record<string, unknown>) };\r\n }\r\n current = current[key] as Record<string, unknown>;\r\n }\r\n\r\n current[keys[keys.length - 1]] = value;\r\n return result as T;\r\n}\r\n\r\n/**\r\n * Format bytes into a human-readable string.\r\n * \r\n * @example\r\n * formatBytes(1024) => '1 KB'\r\n * formatBytes(1234567) => '1.18 MB'\r\n */\r\nexport function formatBytes(bytes: number, decimals = 2): string {\r\n if (bytes === 0) return '0 Bytes';\r\n\r\n const k = 1024;\r\n const dm = decimals < 0 ? 0 : decimals;\r\n const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB'];\r\n\r\n const i = Math.floor(Math.log(bytes) / Math.log(k));\r\n\r\n return `${parseFloat((bytes / Math.pow(k, i)).toFixed(dm))} ${sizes[i]}`;\r\n}\r\n\r\n/**\r\n * Flatten a nested object to dot-notation paths.\r\n * Useful for converting form library state (like dirtyFields, touchedFields)\r\n * to the flat format expected by FormState.\r\n * \r\n * @example\r\n * flattenNestedObject({ user: { name: true, email: true } })\r\n * // => { 'user.name': true, 'user.email': true }\r\n * \r\n * flattenNestedObject({ items: { 0: { title: true } } })\r\n * // => { 'items.0.title': true }\r\n */\r\nexport function flattenNestedObject(\r\n obj: Record<string, unknown>,\r\n prefix = ''\r\n): Record<string, boolean> {\r\n const result: Record<string, boolean> = {};\r\n\r\n for (const key in obj) {\r\n const path = prefix ? `${prefix}.${key}` : key;\r\n const value = obj[key];\r\n\r\n if (typeof value === 'boolean') {\r\n result[path] = value;\r\n } else if (value !== null && typeof value === 'object' && !Array.isArray(value)) {\r\n Object.assign(result, flattenNestedObject(value as Record<string, unknown>, path));\r\n }\r\n }\r\n\r\n return result;\r\n}\r\n\r\n","import type { ReactNode } from 'react';\r\nimport type { Field } from '../types';\r\n\r\n// =============================================================================\r\n// FIELD PATH UTILITIES\r\n// These utilities help work with nested field definitions and form data.\r\n// =============================================================================\r\n\r\n/**\r\n * Recursively extracts all field paths from a field definition tree.\r\n * Handles nested groups, arrays, and layout fields (rows, tabs, collapsibles).\r\n * \r\n * @param fields - Array of field definitions\r\n * @param basePath - Base path prefix (e.g., \"contacts.0\" for array items)\r\n * @returns Array of all field paths\r\n * \r\n * @example\r\n * const fields = [\r\n * { type: 'text', name: 'name' },\r\n * { type: 'group', name: 'address', fields: [\r\n * { type: 'text', name: 'city' },\r\n * { type: 'text', name: 'zip' }\r\n * ]}\r\n * ];\r\n * getNestedFieldPaths(fields, 'contact')\r\n * // => ['contact.name', 'contact.address', 'contact.address.city', 'contact.address.zip']\r\n */\r\nexport function getNestedFieldPaths(fields: Field[], basePath: string): string[] {\r\n const paths: string[] = [];\r\n\r\n for (const field of fields) {\r\n // Data fields with names\r\n if ('name' in field && field.name) {\r\n const fieldPath = basePath ? `${basePath}.${field.name}` : field.name;\r\n paths.push(fieldPath);\r\n\r\n // Recurse into group/array fields\r\n if (field.type === 'group' && 'fields' in field) {\r\n paths.push(...getNestedFieldPaths(field.fields, fieldPath));\r\n }\r\n if (field.type === 'array' && 'fields' in field) {\r\n paths.push(...getNestedFieldPaths(field.fields, fieldPath));\r\n }\r\n }\r\n\r\n // Layout fields (row, tabs, collapsible) - pass through without adding to path\r\n if ('fields' in field && field.type !== 'group' && field.type !== 'array') {\r\n const layoutField = field as Field & { fields: Field[] };\r\n paths.push(...getNestedFieldPaths(layoutField.fields, basePath));\r\n }\r\n\r\n // Tabs field - iterate through tabs\r\n if (field.type === 'tabs' && 'tabs' in field) {\r\n for (const tab of field.tabs) {\r\n const tabPath = tab.name ? (basePath ? `${basePath}.${tab.name}` : tab.name) : basePath;\r\n paths.push(...getNestedFieldPaths(tab.fields, tabPath));\r\n }\r\n }\r\n }\r\n\r\n return paths;\r\n}\r\n\r\n/**\r\n * Count validation errors in nested fields.\r\n * Useful for showing error badges on collapsible sections, array rows, tabs, etc.\r\n * \r\n * @param errors - Form errors object from FormAdapter.formState.errors\r\n * @param fields - Field definitions to check\r\n * @param basePath - Base path for the fields\r\n * @returns Number of fields with errors\r\n * \r\n * @example\r\n * const errorCount = countNestedErrors(form.formState.errors, arrayField.fields, `items.0`);\r\n */\r\nexport function countNestedErrors(\r\n errors: Record<string, unknown>,\r\n fields: Field[],\r\n basePath: string\r\n): number {\r\n const paths = getNestedFieldPaths(fields, basePath);\r\n return paths.filter((path) => errors[path]).length;\r\n}\r\n\r\n/**\r\n * Resolve a potentially dynamic field property (disabled, readOnly, hidden).\r\n * These properties can be boolean or a function that receives form data.\r\n * \r\n * @param value - The property value (boolean or function)\r\n * @param formData - Current form data\r\n * @param siblingData - Data at the same level (for arrays, this is the row data)\r\n * @returns Resolved boolean value\r\n * \r\n * @example\r\n * const isDisabled = resolveFieldState(field.disabled, formData, siblingData);\r\n */\r\nexport function resolveFieldState<TData = Record<string, unknown>>(\r\n value: boolean | ((data: TData, siblingData: Record<string, unknown>) => boolean) | undefined,\r\n formData: TData,\r\n siblingData: Record<string, unknown> = formData as Record<string, unknown>\r\n): boolean {\r\n if (typeof value === 'function') {\r\n return value(formData, siblingData);\r\n }\r\n return Boolean(value);\r\n}\r\n\r\n/**\r\n * Get the label value for an array row based on field configuration.\r\n * First checks for a specific rowLabelField in ui options, then falls back\r\n * to the first named field's value.\r\n * \r\n * @param rowData - Data for the row\r\n * @param fields - Field definitions for the array\r\n * @param uiOptions - UI options that may contain rowLabelField\r\n * @param fallbackLabel - Default label if no value found\r\n * @returns Label string for the row\r\n * \r\n * @example\r\n * const label = getArrayRowLabel(rowData, field.fields, field.ui, `Item ${index + 1}`);\r\n */\r\nexport function getArrayRowLabel(\r\n rowData: Record<string, unknown> | undefined,\r\n fields: Field[],\r\n uiOptions: { rowLabelField?: string } | undefined,\r\n fallbackLabel: string\r\n): string {\r\n // First try explicit rowLabelField\r\n if (uiOptions?.rowLabelField && rowData?.[uiOptions.rowLabelField]) {\r\n return String(rowData[uiOptions.rowLabelField]);\r\n }\r\n\r\n // Fall back to first named field\r\n const firstNamedField = fields.find((f) => 'name' in f && f.name);\r\n if (firstNamedField && 'name' in firstNamedField) {\r\n const value = rowData?.[firstNamedField.name];\r\n if (value) {\r\n return String(value);\r\n }\r\n }\r\n\r\n return fallbackLabel;\r\n}\r\n\r\n// =============================================================================\r\n// FIELD STYLE UTILITIES\r\n// Helpers for computing field styling props.\r\n// =============================================================================\r\n\r\n/**\r\n * Compute the inline style object for a field's width.\r\n * Handles both numeric (px) and string (CSS) width values.\r\n * \r\n * @param style - Field style configuration\r\n * @returns CSS properties object or undefined if no width specified\r\n * \r\n * @example\r\n * <Field style={getFieldWidthStyle(field.style)}>\r\n * ...\r\n * </Field>\r\n */\r\nexport function getFieldWidthStyle(\r\n style: { width?: number | string } | undefined\r\n): { width: string } | undefined {\r\n if (!style?.width) return undefined;\r\n return {\r\n width: typeof style.width === 'number'\r\n ? `${style.width}px`\r\n : style.width,\r\n };\r\n}\r\n\r\n// =============================================================================\r\n// SELECT OPTION UTILITIES\r\n// Helpers for normalizing and extracting data from SelectOption | string.\r\n// =============================================================================\r\n\r\ntype SelectOptionLike = { value: string | number | boolean; label?: ReactNode; description?: ReactNode; icon?: ReactNode; disabled?: boolean } | string;\r\n\r\n/**\r\n * Normalize a select option to always be an object.\r\n * Converts string options to { value, label } objects.\r\n * \r\n * @param option - String or SelectOption object\r\n * @returns Normalized SelectOption object\r\n * \r\n * @example\r\n * normalizeSelectOption('foo') // => { value: 'foo', label: 'foo' }\r\n * normalizeSelectOption({ value: 'bar', label: 'Bar' }) // => { value: 'bar', label: 'Bar' }\r\n */\r\nexport function normalizeSelectOption(option: SelectOptionLike): {\r\n value: string | number | boolean;\r\n label: ReactNode;\r\n description?: ReactNode;\r\n icon?: ReactNode;\r\n disabled?: boolean;\r\n} {\r\n if (typeof option === 'string') {\r\n return { value: option, label: option };\r\n }\r\n return {\r\n value: option.value,\r\n label: option.label ?? String(option.value),\r\n description: option.description,\r\n icon: option.icon,\r\n disabled: option.disabled,\r\n };\r\n}\r\n\r\n/**\r\n * Get the value from a select option (handles string or object).\r\n * \r\n * @param option - String or SelectOption object\r\n * @returns The option's value as a string\r\n * \r\n * @example\r\n * getSelectOptionValue('foo') // => 'foo'\r\n * getSelectOptionValue({ value: 123, label: 'One Two Three' }) // => '123'\r\n */\r\nexport function getSelectOptionValue(option: SelectOptionLike): string {\r\n if (typeof option === 'string') return option;\r\n const val = option.value;\r\n if (typeof val === 'boolean') return val ? 'true' : 'false';\r\n return String(val);\r\n}\r\n\r\n/**\r\n * Get the label from a select option (handles string or object).\r\n * Returns ReactNode to support JSX labels.\r\n * \r\n * @param option - String or SelectOption object\r\n * @returns The option's label for display\r\n * \r\n * @example\r\n * getSelectOptionLabel('foo') // => 'foo'\r\n * getSelectOptionLabel({ value: 'bar', label: <strong>Bar</strong> }) // => <strong>Bar</strong>\r\n */\r\nexport function getSelectOptionLabel(option: SelectOptionLike): ReactNode {\r\n if (typeof option === 'string') return option;\r\n return option.label ?? String(option.value);\r\n}\r\n\r\n/**\r\n * Get the string label from a select option (for filtering/comparison).\r\n * Always returns a string, not ReactNode.\r\n * \r\n * @param option - String or SelectOption object\r\n * @returns The option's label as a string\r\n */\r\nexport function getSelectOptionLabelString(option: SelectOptionLike): string {\r\n if (typeof option === 'string') return option;\r\n if (typeof option.label === 'string') return option.label;\r\n return String(option.value);\r\n}\r\n\r\n/**\r\n * Check if a select option is disabled.\r\n * \r\n * @param option - String or SelectOption object\r\n * @returns true if option is disabled\r\n */\r\nexport function isSelectOptionDisabled(option: SelectOptionLike): boolean {\r\n if (typeof option === 'string') return false;\r\n return option.disabled === true;\r\n}\r\n\r\n// =============================================================================\r\n// NUMBER UTILITIES\r\n// Helpers for number field operations.\r\n// =============================================================================\r\n\r\n/**\r\n * Clamp a number between min and max bounds.\r\n * \r\n * @param value - The number to clamp\r\n * @param min - Minimum bound (optional)\r\n * @param max - Maximum bound (optional)\r\n * @returns Clamped number\r\n * \r\n * @example\r\n * clampNumber(5, 0, 10) // => 5\r\n * clampNumber(-5, 0, 10) // => 0\r\n * clampNumber(15, 0, 10) // => 10\r\n */\r\nexport function clampNumber(value: number, min?: number, max?: number): number {\r\n let result = value;\r\n if (min !== undefined && result < min) result = min;\r\n if (max !== undefined && result > max) result = max;\r\n return result;\r\n}\r\n\r\n/**\r\n * Apply numeric precision (decimal places) to a number.\r\n * \r\n * @param value - The number to format\r\n * @param precision - Number of decimal places\r\n * @returns Formatted number or undefined if input is undefined\r\n * \r\n * @example\r\n * applyNumericPrecision(3.14159, 2) // => 3.14\r\n * applyNumericPrecision(10, 2) // => 10\r\n */\r\nexport function applyNumericPrecision(\r\n value: number | undefined,\r\n precision?: number\r\n): number | undefined {\r\n if (value === undefined || precision === undefined) return value;\r\n return parseFloat(value.toFixed(precision));\r\n}\r\n\r\n/**\r\n * Format a number with thousand separators.\r\n * \r\n * @param value - The number to format\r\n * @param separator - Separator character (default: ',')\r\n * @returns Formatted string or empty string if value is undefined/NaN\r\n * \r\n * @example\r\n * formatNumberWithSeparator(1234567.89) // => '1,234,567.89'\r\n * formatNumberWithSeparator(1234567, ' ') // => '1 234 567'\r\n */\r\nexport function formatNumberWithSeparator(\r\n value: number | undefined,\r\n separator: string = ','\r\n): string {\r\n if (value === undefined || value === null || isNaN(value)) return '';\r\n const [intPart, decPart] = value.toString().split('.');\r\n const formattedInt = intPart.replace(/\\B(?=(\\d{3})+(?!\\d))/g, separator);\r\n return decPart !== undefined ? `${formattedInt}.${decPart}` : formattedInt;\r\n}\r\n\r\n/**\r\n * Parse a formatted number string back to a number.\r\n * \r\n * @param str - Formatted string with separators\r\n * @param separator - Separator character to remove\r\n * @returns Parsed number or undefined if invalid\r\n * \r\n * @example\r\n * parseFormattedNumber('1,234,567.89') // => 1234567.89\r\n * parseFormattedNumber('1 234 567', ' ') // => 1234567\r\n */\r\nexport function parseFormattedNumber(\r\n str: string,\r\n separator: string = ','\r\n): number | undefined {\r\n if (!str || str === '') return undefined;\r\n const cleaned = str.split(separator).join('');\r\n const num = parseFloat(cleaned);\r\n return isNaN(num) ? undefined : num;\r\n}\r\n\r\n// =============================================================================\r\n// DATE UTILITIES\r\n// Helpers for date field operations.\r\n// =============================================================================\r\n\r\n/**\r\n * Safely parse a value to a Date object.\r\n * Handles Date objects, ISO strings, and timestamps.\r\n * \r\n * @param value - Value to parse (Date, string, number, or unknown)\r\n * @returns Date object or undefined if invalid\r\n * \r\n * @example\r\n * parseToDate(new Date()) // => Date\r\n * parseToDate('2024-01-15') // => Date\r\n * parseToDate(null) // => undefined\r\n */\r\nexport function parseToDate(value: unknown): Date | undefined {\r\n if (!value) return undefined;\r\n if (value instanceof Date) {\r\n return isNaN(value.getTime()) ? undefined : value;\r\n }\r\n if (typeof value === 'number') {\r\n const date = new Date(value);\r\n return isNaN(date.getTime()) ? undefined : date;\r\n }\r\n if (typeof value === 'string') {\r\n const date = new Date(value);\r\n return isNaN(date.getTime()) ? undefined : date;\r\n }\r\n return undefined;\r\n}\r\n"],"mappings":"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","names":[]}