@classytic/formkit 1.2.2 → 1.3.1

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/CHANGELOG.md CHANGED
@@ -5,6 +5,18 @@ All notable changes to this project will be documented in this file.
5
5
  The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
6
  and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
7
 
8
+ ## [1.3.0] - 2026-02-27
9
+
10
+ ### Added
11
+
12
+ - New form primitives and schema-driven helpers for broader form composition use cases.
13
+ - Additional coverage for the latest public API surface.
14
+
15
+ ### Changed
16
+
17
+ - Updated package metadata and compatibility requirements for React Hook Form `^7.55.0`.
18
+ - Aligned publish artifacts and entrypoint packaging for the current release.
19
+
8
20
  ## [1.2.2] - 2026-02-26
9
21
 
10
22
  ### Fixed
package/README.md CHANGED
@@ -74,7 +74,9 @@ export function FormInput({
74
74
  </Label>
75
75
  )}
76
76
  <Input {...rhfField} id={fieldId} placeholder={placeholder} />
77
- {error && <p className="text-sm text-red-500">{error.message}</p>}
77
+ {error && (
78
+ <p className="text-sm text-red-500">{error.message}</p>
79
+ )}
78
80
  </div>
79
81
  )}
80
82
  />
@@ -152,39 +154,15 @@ const formSchema: FormSchema<SignupData> = {
152
154
  title: "Personal Information",
153
155
  cols: 2,
154
156
  fields: [
155
- {
156
- name: "firstName",
157
- type: "text",
158
- label: "First Name",
159
- required: true,
160
- defaultValue: "",
161
- },
162
- {
163
- name: "lastName",
164
- type: "text",
165
- label: "Last Name",
166
- required: true,
167
- defaultValue: "",
168
- },
157
+ { name: "firstName", type: "text", label: "First Name", required: true, defaultValue: "" },
158
+ { name: "lastName", type: "text", label: "Last Name", required: true, defaultValue: "" },
169
159
  ],
170
160
  },
171
161
  {
172
162
  title: "Account",
173
163
  fields: [
174
- {
175
- name: "email",
176
- type: "email",
177
- label: "Email",
178
- required: true,
179
- defaultValue: "",
180
- },
181
- {
182
- name: "password",
183
- type: "password",
184
- label: "Password",
185
- required: true,
186
- defaultValue: "",
187
- },
164
+ { name: "email", type: "email", label: "Email", required: true, defaultValue: "" },
165
+ { name: "password", type: "password", label: "Password", required: true, defaultValue: "" },
188
166
  ],
189
167
  },
190
168
  ],
@@ -222,10 +200,10 @@ const form = useFormKit({
222
200
  schema: formSchema,
223
201
  resolver: zodResolver(validationSchema), // optional
224
202
  defaultValues: { email: "pre@fill.com" }, // optional overrides
225
- disabled: false, // optional
226
- variant: "compact", // optional
227
- className: "my-form", // optional
228
- mode: "onBlur", // any useForm option
203
+ disabled: false, // optional
204
+ variant: "compact", // optional
205
+ className: "my-form", // optional
206
+ mode: "onBlur", // any useForm option
229
207
  });
230
208
 
231
209
  const { handleSubmit, generatorProps } = form;
@@ -253,12 +231,12 @@ The main component that renders forms from a schema. Supports React 19 `ref` as
253
231
 
254
232
  ```tsx
255
233
  <FormGenerator
256
- schema={formSchema} // Required: Form schema
257
- control={form.control} // Optional: React Hook Form control (or wrap in <FormProvider>)
258
- disabled={false} // Optional: Disable all fields
259
- variant="default" // Optional: Global variant
260
- className="my-form" // Optional: Root element class
261
- ref={formRef} // Optional: Ref to the root <div> (React 19 ref-as-prop)
234
+ schema={formSchema} // Required: Form schema
235
+ control={form.control} // Optional: React Hook Form control (or wrap in <FormProvider>)
236
+ disabled={false} // Optional: Disable all fields
237
+ variant="default" // Optional: Global variant
238
+ className="my-form" // Optional: Root element class
239
+ ref={formRef} // Optional: Ref to the root <div> (React 19 ref-as-prop)
262
240
  />
263
241
  ```
264
242
 
@@ -274,18 +252,18 @@ interface FormSchema<T extends FieldValues = FieldValues> {
274
252
 
275
253
  ```ts
276
254
  interface Section<T> {
277
- id?: string; // Unique identifier
278
- title?: string; // Section title
279
- description?: string; // Section description
280
- icon?: ReactNode; // Section icon
281
- fields?: BaseField<T>[]; // Fields in this section
282
- cols?: number; // Grid columns (1-6)
283
- gap?: number; // Grid gap
284
- variant?: string; // Section variant
285
- className?: string; // Custom class
286
- collapsible?: boolean; // Make section collapsible
255
+ id?: string; // Unique identifier
256
+ title?: string; // Section title
257
+ description?: string; // Section description
258
+ icon?: ReactNode; // Section icon
259
+ fields?: BaseField<T>[]; // Fields in this section
260
+ cols?: number; // Grid columns (1-6)
261
+ gap?: number; // Grid gap
262
+ variant?: string; // Section variant
263
+ className?: string; // Custom class
264
+ collapsible?: boolean; // Make section collapsible
287
265
  defaultCollapsed?: boolean;
288
- nameSpace?: string; // Prefix for nested object fields (e.g. "address")
266
+ nameSpace?: string; // Prefix for nested object fields (e.g. "address")
289
267
 
290
268
  // Conditional rendering (function, DSL rule, or ConditionConfig)
291
269
  condition?: Condition<T>;
@@ -299,27 +277,25 @@ interface Section<T> {
299
277
 
300
278
  ```ts
301
279
  interface BaseField<T> {
302
- name: string; // Field name (required)
303
- type: FieldType; // Field type (required)
304
- label?: string; // Field label
305
- placeholder?: string; // Placeholder text
306
- helperText?: string; // Helper text below field
307
- disabled?: boolean; // Disable field
308
- required?: boolean; // Mark as required
309
- readOnly?: boolean; // Read-only field
310
- variant?: string; // Field variant
311
- fullWidth?: boolean; // Span full grid width
312
- className?: string; // Custom class
313
- defaultValue?: unknown; // Default value
280
+ name: string; // Field name (required)
281
+ type: FieldType; // Field type (required)
282
+ label?: string; // Field label
283
+ placeholder?: string; // Placeholder text
284
+ helperText?: string; // Helper text below field
285
+ disabled?: boolean; // Disable field
286
+ required?: boolean; // Mark as required
287
+ readOnly?: boolean; // Read-only field
288
+ variant?: string; // Field variant
289
+ fullWidth?: boolean; // Span full grid width
290
+ className?: string; // Custom class
291
+ defaultValue?: unknown; // Default value
314
292
 
315
293
  // Conditional rendering
316
294
  condition?: Condition<T>;
317
- watchNames?: string | string[]; // Optimize useWatch performance
295
+ watchNames?: string | string[]; // Optimize useWatch performance
318
296
 
319
297
  // Dynamic options loading
320
- loadOptions?: (
321
- formValues: Partial<T>,
322
- ) => Promise<FieldOption[]> | FieldOption[];
298
+ loadOptions?: (formValues: Partial<T>) => Promise<FieldOption[]> | FieldOption[];
323
299
  debounceMs?: number;
324
300
 
325
301
  // For array/grouped types
@@ -354,23 +330,21 @@ interface BaseField<T> {
354
330
  Props passed to your field components:
355
331
 
356
332
  ```ts
357
- interface FieldComponentProps<
358
- T extends FieldValues = FieldValues,
359
- > extends BaseField<T> {
360
- field: BaseField<T>; // Full field config
361
- control: Control<T>; // React Hook Form control
362
- disabled?: boolean; // Merged disabled state
363
- variant?: string; // Active variant
364
- error?: FieldError; // Field error from react-hook-form
365
- fieldState?: {
366
- // Field state metadata
333
+ interface FieldComponentProps<T extends FieldValues = FieldValues>
334
+ extends BaseField<T> {
335
+ field: BaseField<T>; // Full field config
336
+ control: Control<T>; // React Hook Form control
337
+ disabled?: boolean; // Merged disabled state
338
+ variant?: string; // Active variant
339
+ error?: FieldError; // Field error from react-hook-form
340
+ fieldState?: { // Field state metadata
367
341
  invalid: boolean;
368
342
  isDirty: boolean;
369
343
  isTouched: boolean;
370
344
  isValidating: boolean;
371
345
  error?: FieldError;
372
346
  };
373
- fieldId: string; // Generated ID for label-input association (e.g. "formkit-field-email")
347
+ fieldId: string; // Generated ID for label-input association (e.g. "formkit-field-email")
374
348
  }
375
349
  ```
376
350
 
@@ -700,11 +674,7 @@ function FormTextarea({ field, customProps, ...props }: FieldComponentProps) {
700
674
  Type-safe helpers for defining schemas outside of components:
701
675
 
702
676
  ```ts
703
- import {
704
- defineSchema,
705
- defineField,
706
- defineSection,
707
- } from "@classytic/formkit/server";
677
+ import { defineSchema, defineField, defineSection } from "@classytic/formkit/server";
708
678
 
709
679
  const emailField = defineField<MyFormData>({
710
680
  name: "email",
package/dist/index.d.mts CHANGED
@@ -910,5 +910,4 @@ interface UseFormKitReturn<TFieldValues extends FieldValues = FieldValues> exten
910
910
  */
911
911
  declare function useFormKit<TFieldValues extends FieldValues = FieldValues>(options: UseFormKitOptions<TFieldValues>): UseFormKitReturn<TFieldValues>;
912
912
  //#endregion
913
- export { type BaseField, type ClassValue, type ComponentRegistry, type Condition, type ConditionConfig, type ConditionRule, type DefaultLayoutProps, type DefineField, type FieldComponent, type FieldComponentProps, type FieldOption, type FieldOptionGroup, type FieldType, FieldWrapper, type FormElement, FormGenerator, type FormGeneratorProps, type FormSchema, type FormSystemContextValue, FormSystemProvider, type FormSystemProviderProps, type GridLayoutProps, GridRenderer, type InferSchemaValues, type LayoutComponent, type LayoutComponentProps, type LayoutRegistry, type LayoutType, type SchemaFieldNames, type Section, type SectionLayoutProps, type SectionRenderProps, SectionRenderer, type UseFormKitOptions, type UseFormKitReturn, type ValidationRules, type Variant, buildValidationRules, cn, defineField, defineSchema, defineSection, evaluateCondition, extractDefaultValues, extractWatchNames, field, section, sectionUntitled, shallowEqual, useFieldComponent, useFormKit, useFormSystem, useLayoutComponent };
914
- //# sourceMappingURL=index.d.mts.map
913
+ export { type BaseField, type ClassValue, type ComponentRegistry, type Condition, type ConditionConfig, type ConditionRule, type DefaultLayoutProps, type DefineField, type FieldComponent, type FieldComponentProps, type FieldOption, type FieldOptionGroup, type FieldType, FieldWrapper, type FieldWrapperProps, type FormElement, FormGenerator, type FormGeneratorProps, type FormSchema, type FormSystemContextValue, FormSystemProvider, type FormSystemProviderProps, type GridLayoutProps, GridRenderer, type GridRendererProps, type InferSchemaValues, type LayoutComponent, type LayoutComponentProps, type LayoutRegistry, type LayoutType, type SchemaFieldNames, type Section, type SectionLayoutProps, type SectionRenderProps, SectionRenderer, type SectionRendererProps, type UseFormKitOptions, type UseFormKitReturn, type ValidationRules, type Variant, buildValidationRules, cn, defineField, defineSchema, defineSection, evaluateCondition, extractDefaultValues, extractWatchNames, field, section, sectionUntitled, shallowEqual, useFieldComponent, useFormKit, useFormSystem, useLayoutComponent };
package/dist/index.mjs CHANGED
@@ -279,7 +279,12 @@ function toRules(condition) {
279
279
  */
280
280
  function evaluateCondition(condition, formValues) {
281
281
  if (!condition) return true;
282
- if (typeof condition === "function") return condition(formValues);
282
+ if (typeof condition === "function") try {
283
+ return condition(formValues);
284
+ } catch (err) {
285
+ console.warn("[FormKit] Condition function threw:", err);
286
+ return false;
287
+ }
283
288
  const { rules, logic } = toRules(condition);
284
289
  const evalFn = (rule) => evaluateRule(rule, formValues);
285
290
  return logic === "or" ? rules.some(evalFn) : rules.every(evalFn);
@@ -369,10 +374,14 @@ function buildValidationRules(field) {
369
374
  value: field.max,
370
375
  message: `Must be at most ${field.max}`
371
376
  };
372
- if (field.pattern) rules.pattern = {
373
- value: new RegExp(field.pattern),
374
- message: "Invalid format"
375
- };
377
+ if (field.pattern) try {
378
+ rules.pattern = {
379
+ value: new RegExp(field.pattern),
380
+ message: "Invalid format"
381
+ };
382
+ } catch {
383
+ console.warn(`[FormKit] Invalid regex pattern "${field.pattern}" in field "${field.name}", skipping.`);
384
+ }
376
385
  if (field.validate) rules.validate = field.validate;
377
386
  return rules;
378
387
  }
@@ -548,8 +557,50 @@ function GridRenderer({ fields, cols = 1, gap, control, disabled, variant }) {
548
557
  */
549
558
  function FieldWrapper(props) {
550
559
  if (props.field.condition || props.field.loadOptions) return /* @__PURE__ */ jsx(DynamicFieldWrapper, { ...props });
560
+ if (props.field.render) return /* @__PURE__ */ jsx(RenderedFieldWrapper, { ...props });
551
561
  return /* @__PURE__ */ jsx(StaticFieldWrapper, { ...props });
552
562
  }
563
+ function RenderedFieldWrapper({ field, control, disabled, variant }) {
564
+ const fieldName = field.name;
565
+ const fieldId = toFieldId(fieldName);
566
+ const activeVariant = field.variant ?? variant;
567
+ const isDisabled = disabled || field.disabled;
568
+ const { errors, dirtyFields, touchedFields } = useFormState({
569
+ control,
570
+ name: fieldName
571
+ });
572
+ const fieldError = getNestedError(errors, fieldName);
573
+ const isDirty = Boolean(getNestedValue(dirtyFields, fieldName));
574
+ const isTouched = Boolean(getNestedValue(touchedFields, fieldName));
575
+ const fieldState = useMemo(() => ({
576
+ invalid: !!fieldError,
577
+ isDirty,
578
+ isTouched,
579
+ isValidating: false,
580
+ error: fieldError
581
+ }), [
582
+ fieldError,
583
+ isDirty,
584
+ isTouched
585
+ ]);
586
+ return /* @__PURE__ */ jsx("div", {
587
+ className: cn("formkit-field", field.fullWidth && "col-span-full", field.className),
588
+ id: fieldId,
589
+ "data-formkit-field": fieldName,
590
+ "data-field-type": field.type,
591
+ children: field.render?.({
592
+ ...field,
593
+ field,
594
+ control,
595
+ disabled: isDisabled,
596
+ variant: activeVariant,
597
+ error: fieldError,
598
+ fieldState,
599
+ fieldId,
600
+ isLoading: void 0
601
+ })
602
+ });
603
+ }
553
604
  /**
554
605
  * Dynamic Field Wrapper
555
606
  * Conditionally calls `useWatch` to trigger re-renders only when form values change.
@@ -615,7 +666,10 @@ function DynamicFieldWrapper({ field, control, disabled, variant }) {
615
666
  } else executeLoad();
616
667
  return () => {
617
668
  isActive = false;
618
- if (timeoutRef.current) clearTimeout(timeoutRef.current);
669
+ if (timeoutRef.current) {
670
+ clearTimeout(timeoutRef.current);
671
+ timeoutRef.current = null;
672
+ }
619
673
  };
620
674
  }, [
621
675
  watchedValues,
@@ -671,23 +725,6 @@ function StaticFieldWrapper({ field, control, disabled, variant, isLoading }) {
671
725
  isTouched
672
726
  ]);
673
727
  const activeVariant = field.variant ?? variant;
674
- if (field.render) return /* @__PURE__ */ jsx("div", {
675
- className: cn("formkit-field", field.fullWidth && "col-span-full", field.className),
676
- id: fieldId,
677
- "data-formkit-field": fieldName,
678
- "data-field-type": field.type,
679
- children: field.render({
680
- ...field,
681
- field,
682
- control,
683
- disabled: isDisabled,
684
- variant: activeVariant,
685
- error: fieldError,
686
- fieldState,
687
- fieldId,
688
- isLoading
689
- })
690
- });
691
728
  if (!Boolean(components[field.type] || activeVariant && components[activeVariant] && typeof components[activeVariant] === "object" && components[activeVariant][field.type]) && field.itemFields && field.itemFields.length > 0) {
692
729
  if (field.type === "array") return /* @__PURE__ */ jsx(ArrayFieldFallback, {
693
730
  field,
@@ -708,23 +745,24 @@ function StaticFieldWrapper({ field, control, disabled, variant, isLoading }) {
708
745
  });
709
746
  }
710
747
  const FieldComponent = useFieldComponent(field.type, activeVariant);
711
- if (!FieldComponent) return null;
748
+ if (!FieldComponent && !field.render) return null;
749
+ const fieldProps = {
750
+ ...field,
751
+ field,
752
+ control,
753
+ disabled: isDisabled,
754
+ variant: activeVariant,
755
+ error: fieldError,
756
+ fieldState,
757
+ fieldId,
758
+ isLoading
759
+ };
712
760
  return /* @__PURE__ */ jsx("div", {
713
761
  className: cn("formkit-field", field.fullWidth && "col-span-full", field.className),
714
762
  id: fieldId,
715
763
  "data-formkit-field": fieldName,
716
764
  "data-field-type": field.type,
717
- children: /* @__PURE__ */ jsx(FieldComponent, {
718
- ...field,
719
- field,
720
- control,
721
- disabled: isDisabled,
722
- variant: activeVariant,
723
- error: fieldError,
724
- fieldState,
725
- fieldId,
726
- isLoading
727
- })
765
+ children: field.render ? field.render(fieldProps) : /* @__PURE__ */ jsx(FieldComponent, { ...fieldProps })
728
766
  });
729
767
  }
730
768
  function ArrayFieldFallback({ field, control, disabled, variant }) {
@@ -763,7 +801,13 @@ function ArrayFieldFallback({ field, control, disabled, variant }) {
763
801
  }, item.id)),
764
802
  /* @__PURE__ */ jsx("button", {
765
803
  type: "button",
766
- onClick: () => append({}),
804
+ onClick: () => {
805
+ const defaults = {};
806
+ if (field.itemFields) {
807
+ for (const f of field.itemFields) if (f.defaultValue !== void 0) defaults[f.name] = f.defaultValue;
808
+ }
809
+ append(defaults);
810
+ },
767
811
  disabled,
768
812
  className: "self-start mt-2 px-4 py-2 bg-blue-50 text-blue-600 rounded-md text-sm font-medium hover:bg-blue-100 disabled:opacity-50",
769
813
  children: "+ Add Item"
@@ -1015,10 +1059,11 @@ function sectionUntitled(fields, props = {}) {
1015
1059
  */
1016
1060
  function useFormKit(options) {
1017
1061
  const { schema, disabled, variant, className, defaultValues, ...formOptions } = options;
1018
- const mergedDefaults = {
1019
- ...extractDefaultValues(schema),
1062
+ const schemaDefaults = useMemo(() => extractDefaultValues(schema), [schema]);
1063
+ const mergedDefaults = useMemo(() => ({
1064
+ ...schemaDefaults,
1020
1065
  ...typeof defaultValues === "object" && defaultValues !== null ? defaultValues : {}
1021
- };
1066
+ }), [schemaDefaults, defaultValues]);
1022
1067
  const form = useForm({
1023
1068
  ...formOptions,
1024
1069
  defaultValues: mergedDefaults
@@ -1040,5 +1085,4 @@ function useFormKit(options) {
1040
1085
  }
1041
1086
 
1042
1087
  //#endregion
1043
- export { FieldWrapper, FormGenerator, FormSystemProvider, GridRenderer, SectionRenderer, buildValidationRules, cn, defineField, defineSchema, defineSection, evaluateCondition, extractDefaultValues, extractWatchNames, field, section, sectionUntitled, shallowEqual, useFieldComponent, useFormKit, useFormSystem, useLayoutComponent };
1044
- //# sourceMappingURL=index.mjs.map
1088
+ export { FieldWrapper, FormGenerator, FormSystemProvider, GridRenderer, SectionRenderer, buildValidationRules, cn, defineField, defineSchema, defineSection, evaluateCondition, extractDefaultValues, extractWatchNames, field, section, sectionUntitled, shallowEqual, useFieldComponent, useFormKit, useFormSystem, useLayoutComponent };
package/dist/server.d.mts CHANGED
@@ -621,5 +621,4 @@ declare function section<TFieldValues extends FieldValues = FieldValues>(id: str
621
621
  */
622
622
  declare function sectionUntitled<TFieldValues extends FieldValues = FieldValues>(fields: BaseField<TFieldValues>[], props?: Omit<SectionProps<TFieldValues>, "variant">): Section<TFieldValues>;
623
623
  //#endregion
624
- export { type BaseField, type ClassValue, type Condition, type ConditionConfig, type ConditionRule, type DefaultLayoutProps, type DefineField, type FieldOption, type FieldOptionGroup, type FieldType, type FormSchema, type GridLayoutProps, type InferSchemaValues, type LayoutComponentProps, type LayoutType, type SchemaFieldNames, type Section, type SectionLayoutProps, type SectionRenderProps, type Variant, buildValidationRules, cn, defineField, defineSchema, defineSection, evaluateCondition, extractDefaultValues, extractWatchNames, field, section, sectionUntitled };
625
- //# sourceMappingURL=server.d.mts.map
624
+ export { type BaseField, type ClassValue, type Condition, type ConditionConfig, type ConditionRule, type DefaultLayoutProps, type DefineField, type FieldOption, type FieldOptionGroup, type FieldType, type FormSchema, type GridLayoutProps, type InferSchemaValues, type LayoutComponentProps, type LayoutType, type SchemaFieldNames, type Section, type SectionLayoutProps, type SectionRenderProps, type Variant, buildValidationRules, cn, defineField, defineSchema, defineSection, evaluateCondition, extractDefaultValues, extractWatchNames, field, section, sectionUntitled };
package/dist/server.mjs CHANGED
@@ -95,7 +95,12 @@ function toRules(condition) {
95
95
  */
96
96
  function evaluateCondition(condition, formValues) {
97
97
  if (!condition) return true;
98
- if (typeof condition === "function") return condition(formValues);
98
+ if (typeof condition === "function") try {
99
+ return condition(formValues);
100
+ } catch (err) {
101
+ console.warn("[FormKit] Condition function threw:", err);
102
+ return false;
103
+ }
99
104
  const { rules, logic } = toRules(condition);
100
105
  const evalFn = (rule) => evaluateRule(rule, formValues);
101
106
  return logic === "or" ? rules.some(evalFn) : rules.every(evalFn);
@@ -185,10 +190,14 @@ function buildValidationRules(field) {
185
190
  value: field.max,
186
191
  message: `Must be at most ${field.max}`
187
192
  };
188
- if (field.pattern) rules.pattern = {
189
- value: new RegExp(field.pattern),
190
- message: "Invalid format"
191
- };
193
+ if (field.pattern) try {
194
+ rules.pattern = {
195
+ value: new RegExp(field.pattern),
196
+ message: "Invalid format"
197
+ };
198
+ } catch {
199
+ console.warn(`[FormKit] Invalid regex pattern "${field.pattern}" in field "${field.name}", skipping.`);
200
+ }
192
201
  if (field.validate) rules.validate = field.validate;
193
202
  return rules;
194
203
  }
@@ -414,5 +423,4 @@ function sectionUntitled(fields, props = {}) {
414
423
  }
415
424
 
416
425
  //#endregion
417
- export { buildValidationRules, cn, defineField, defineSchema, defineSection, evaluateCondition, extractDefaultValues, extractWatchNames, field, section, sectionUntitled };
418
- //# sourceMappingURL=server.mjs.map
426
+ export { buildValidationRules, cn, defineField, defineSchema, defineSection, evaluateCondition, extractDefaultValues, extractWatchNames, field, section, sectionUntitled };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@classytic/formkit",
3
- "version": "1.2.2",
3
+ "version": "1.3.1",
4
4
  "description": "Headless, type-safe form generation engine for React 19. Schema-driven with full TypeScript support.",
5
5
  "author": "Classytic",
6
6
  "license": "MIT",
@@ -95,13 +95,13 @@
95
95
  "@typescript-eslint/parser": "^8.0.0",
96
96
  "@vitejs/plugin-react": "^4.3.0",
97
97
  "eslint": "^9.0.0",
98
- "happy-dom": "^15.0.0",
98
+ "happy-dom": "^20.8.3",
99
99
  "react": "^19.0.0",
100
100
  "react-dom": "^19.0.0",
101
101
  "react-hook-form": "^7.55.0",
102
102
  "tsdown": "^0.20.3",
103
103
  "typescript": "^5.6.3",
104
- "vitest": "^2.0.0"
104
+ "vitest": "^4.0.18"
105
105
  },
106
106
  "engines": {
107
107
  "node": ">=18.0.0"
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.d.mts","names":[],"sources":["../src/types.ts","../src/FormGenerator.tsx","../src/FormSystemContext.tsx","../src/utils.ts","../src/schema.ts","../src/builders.ts","../src/useFormKit.ts"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"index.mjs","names":["getNestedValue"],"sources":["../src/FormSystemContext.tsx","../src/utils.ts","../src/schema.ts","../src/FormGenerator.tsx","../src/builders.ts","../src/useFormKit.ts"],"sourcesContent":["\"use client\";\r\n\r\nimport { createContext, useContext, useMemo } from \"react\";\r\nimport type {\r\n FormSystemContextValue,\r\n FormSystemProviderProps,\r\n FieldComponent,\r\n LayoutComponent,\r\n FieldType,\r\n LayoutType,\r\n Variant,\r\n SectionLayoutProps,\r\n GridLayoutProps,\r\n DefaultLayoutProps,\r\n FormElement,\r\n} from \"./types\";\r\n\r\n// ============================================================================\r\n// Context\r\n// ============================================================================\r\n\r\nconst FormSystemContext = createContext<FormSystemContextValue | null>(null);\r\n\r\n// Display name for React DevTools\r\nFormSystemContext.displayName = \"FormSystemContext\";\r\n\r\n// ============================================================================\r\n// Provider\r\n// ============================================================================\r\n\r\n/**\r\n * FormSystemProvider\r\n *\r\n * Root provider that enables the form system. Provides component and layout\r\n * registries to FormGenerator and its descendants.\r\n *\r\n * @example\r\n * ```tsx\r\n * import { FormSystemProvider } from '@classytic/formkit';\r\n *\r\n * const components = {\r\n * text: TextInput,\r\n * select: SelectInput,\r\n * // Variant-specific components\r\n * compact: {\r\n * text: CompactTextInput,\r\n * },\r\n * };\r\n *\r\n * const layouts = {\r\n * section: SectionLayout,\r\n * grid: GridLayout,\r\n * };\r\n *\r\n * function App() {\r\n * return (\r\n * <FormSystemProvider components={components} layouts={layouts}>\r\n * <YourFormComponent />\r\n * </FormSystemProvider>\r\n * );\r\n * }\r\n * ```\r\n */\r\nexport function FormSystemProvider({\r\n components,\r\n layouts,\r\n children,\r\n}: FormSystemProviderProps): FormElement {\r\n const value = useMemo<FormSystemContextValue>(\r\n () => ({\r\n components: components ?? {},\r\n layouts: layouts ?? {},\r\n }),\r\n [components, layouts]\r\n );\r\n\r\n return <FormSystemContext value={value}>{children}</FormSystemContext>;\r\n}\r\n\r\n// ============================================================================\r\n// Hooks\r\n// ============================================================================\r\n\r\n/**\r\n * Hook to access the form system context.\r\n *\r\n * @throws {Error} If used outside FormSystemProvider\r\n * @returns Form system context value\r\n *\r\n * @example\r\n * ```tsx\r\n * const { components, layouts } = useFormSystem();\r\n * ```\r\n */\r\nexport function useFormSystem(): FormSystemContextValue {\r\n const context = useContext(FormSystemContext);\r\n if (!context) {\r\n throw new Error(\r\n \"[FormKit] useFormSystem must be used within a FormSystemProvider. \" +\r\n \"Make sure to wrap your form components with <FormSystemProvider>.\"\r\n );\r\n }\r\n return context;\r\n}\r\n\r\n/**\r\n * Hook to get a field component by type and optional variant.\r\n *\r\n * Resolution order:\r\n * 1. Variant-specific component: `components[variant][type]`\r\n * 2. Type-specific component: `components[type]`\r\n * 3. Default component: `components[\"default\"]`\r\n * 4. Text fallback: `components[\"text\"]`\r\n *\r\n * @param type - Field type identifier\r\n * @param variant - Optional variant name\r\n * @returns Field component or fallback\r\n *\r\n * @internal\r\n */\r\nexport function useFieldComponent(type: FieldType, variant?: Variant): FieldComponent {\r\n const { components } = useFormSystem();\r\n\r\n // 1. Try variant-specific component\r\n if (variant && typeof components[variant] === \"object\" && components[variant] !== null) {\r\n const variantComponents = components[variant] as Record<string, FieldComponent>;\r\n const variantComponent = variantComponents[type];\r\n if (variantComponent) {\r\n return variantComponent;\r\n }\r\n }\r\n\r\n // 2. Try type-specific component\r\n const typeComponent = components[type] as FieldComponent | undefined;\r\n if (typeComponent && typeof typeComponent === \"function\") {\r\n return typeComponent;\r\n }\r\n\r\n // 3. Try default component\r\n const defaultComponent = components[\"default\"] as FieldComponent | undefined;\r\n if (defaultComponent && typeof defaultComponent === \"function\") {\r\n return defaultComponent;\r\n }\r\n\r\n // 4. Try text fallback\r\n const textComponent = components[\"text\"] as FieldComponent | undefined;\r\n if (textComponent && typeof textComponent === \"function\") {\r\n return textComponent;\r\n }\r\n\r\n // 5. Development warning and placeholder\r\n if (process.env.NODE_ENV !== \"production\") {\r\n console.warn(\r\n `[FormKit] No component found for type \"${type}\"${variant ? ` (variant: \"${variant}\")` : \"\"}. ` +\r\n \"Register a component for this type in your FormSystemProvider.\"\r\n );\r\n return MissingFieldComponent;\r\n }\r\n\r\n // Production: silent fallback\r\n return NullComponent;\r\n}\r\n\r\n/**\r\n * Hook to get a layout component by type and optional variant.\r\n *\r\n * Resolution order:\r\n * 1. Variant-specific layout: `layouts[variant][type]`\r\n * 2. Type-specific layout: `layouts[type]`\r\n * 3. Default layout: `layouts[\"default\"]`\r\n * 4. Built-in default layout\r\n *\r\n * @param type - Layout type identifier\r\n * @param variant - Optional variant name\r\n * @returns Layout component or fallback\r\n *\r\n * @internal\r\n */\r\nexport function useLayoutComponent(\r\n type: LayoutType,\r\n variant?: Variant\r\n): LayoutComponent<SectionLayoutProps | GridLayoutProps | DefaultLayoutProps> {\r\n const { layouts } = useFormSystem();\r\n\r\n // 1. Try variant-specific layout\r\n if (variant && typeof layouts[variant] === \"object\" && layouts[variant] !== null) {\r\n const variantLayouts = layouts[variant] as Record<\r\n string,\r\n LayoutComponent<SectionLayoutProps | GridLayoutProps | DefaultLayoutProps>\r\n >;\r\n const variantLayout = variantLayouts[type];\r\n if (variantLayout) {\r\n return variantLayout;\r\n }\r\n }\r\n\r\n // 2. Try type-specific layout\r\n const typeLayout = layouts[type] as\r\n | LayoutComponent<SectionLayoutProps | GridLayoutProps | DefaultLayoutProps>\r\n | undefined;\r\n if (typeLayout && typeof typeLayout === \"function\") {\r\n return typeLayout;\r\n }\r\n\r\n // 3. Try default layout\r\n const defaultLayout = layouts[\"default\"] as\r\n | LayoutComponent<SectionLayoutProps | GridLayoutProps | DefaultLayoutProps>\r\n | undefined;\r\n if (defaultLayout && typeof defaultLayout === \"function\") {\r\n return defaultLayout;\r\n }\r\n\r\n // 4. Built-in default layout\r\n return DefaultLayout;\r\n}\r\n\r\n// ============================================================================\r\n// Fallback Components\r\n// ============================================================================\r\n\r\n/**\r\n * Default layout component - simple div wrapper.\r\n * Used when no layout is registered.\r\n */\r\nfunction DefaultLayout({ children, className }: DefaultLayoutProps): FormElement {\r\n return <div className={className}>{children}</div>;\r\n}\r\n\r\n/**\r\n * Null component for production fallback.\r\n */\r\nfunction NullComponent(): FormElement {\r\n return null;\r\n}\r\n\r\n/**\r\n * Development placeholder for missing field components.\r\n */\r\nfunction MissingFieldComponent({ field }: { field: { type: string; name: string } }): FormElement {\r\n return (\r\n <div\r\n style={{\r\n color: \"#dc2626\",\r\n padding: \"8px 12px\",\r\n border: \"1px dashed #dc2626\",\r\n borderRadius: \"4px\",\r\n fontSize: \"12px\",\r\n fontFamily: \"monospace\",\r\n backgroundColor: \"#fef2f2\",\r\n }}\r\n >\r\n Missing component: <strong>{field.type}</strong> (field: {field.name})\r\n </div>\r\n );\r\n}\r\n","import { clsx } from \"clsx\";\r\nimport { twMerge } from \"tailwind-merge\";\r\nimport type { ClassValue } from \"clsx\";\r\n\r\n/**\r\n * Utility function to merge CSS classes with Tailwind CSS conflict resolution.\r\n *\r\n * Combines `clsx` for conditional class handling with `tailwind-merge`\r\n * for proper Tailwind CSS class conflict resolution.\r\n *\r\n * @param inputs - Class values to merge (strings, arrays, objects, or conditionals)\r\n * @returns Merged and deduplicated class string\r\n *\r\n * @example\r\n * ```tsx\r\n * // Basic usage\r\n * cn(\"px-2 py-1\", \"px-4\") // \"py-1 px-4\"\r\n *\r\n * // Conditional classes\r\n * cn(\"base\", isActive && \"active\", { \"disabled\": isDisabled })\r\n *\r\n * // Arrays\r\n * cn([\"flex\", \"items-center\"], \"gap-2\")\r\n * ```\r\n */\r\nexport function cn(...inputs: ClassValue[]): string {\r\n return twMerge(clsx(inputs));\r\n}\r\n\r\n/**\r\n * Shallow equality check for arrays and primitives.\r\n * Used to stabilize useWatch output without JSON.stringify overhead.\r\n */\r\nexport function shallowEqual(a: unknown, b: unknown): boolean {\r\n if (Object.is(a, b)) return true;\r\n if (\r\n typeof a !== \"object\" ||\r\n typeof b !== \"object\" ||\r\n a === null ||\r\n b === null\r\n ) {\r\n return false;\r\n }\r\n\r\n if (Array.isArray(a) && Array.isArray(b)) {\r\n if (a.length !== b.length) return false;\r\n for (let i = 0; i < a.length; i++) {\r\n if (!Object.is(a[i], b[i])) return false;\r\n }\r\n return true;\r\n }\r\n\r\n const keysA = Object.keys(a);\r\n const keysB = Object.keys(b);\r\n if (keysA.length !== keysB.length) return false;\r\n\r\n for (const key of keysA) {\r\n if (\r\n !Object.prototype.hasOwnProperty.call(b, key) ||\r\n !Object.is(\r\n (a as Record<string, unknown>)[key],\r\n (b as Record<string, unknown>)[key],\r\n )\r\n ) {\r\n return false;\r\n }\r\n }\r\n return true;\r\n}\r\n\r\n/**\r\n * Re-export ClassValue type for consumers who need it.\r\n */\r\nexport type { ClassValue };\r\n","import type { FieldValues } from \"react-hook-form\";\r\nimport type {\r\n FormSchema,\r\n Section,\r\n BaseField,\r\n ConditionRule,\r\n ConditionConfig,\r\n ValidationRules,\r\n} from \"./types\";\r\n\r\n// ============================================================================\r\n// Condition Types (union used by both evaluateCondition and extractWatchNames)\r\n// ============================================================================\r\n\r\n/**\r\n * All supported condition shapes.\r\n */\r\nexport type Condition<TFieldValues extends FieldValues = FieldValues> =\r\n | ((formValues: Partial<TFieldValues>) => boolean)\r\n | ConditionRule<TFieldValues>\r\n | ConditionRule<TFieldValues>[]\r\n | ConditionConfig<TFieldValues>\r\n | undefined;\r\n\r\n// ============================================================================\r\n// Internal Helpers\r\n// ============================================================================\r\n\r\n/**\r\n * Resolves a dot-notation path against an object.\r\n * Handles array indices: \"items.0.name\" resolves through arrays correctly.\r\n */\r\nfunction getNestedValue(obj: Record<string, unknown>, path: string): unknown {\r\n const parts = path.split(\".\");\r\n let current: unknown = obj;\r\n for (const part of parts) {\r\n if (current == null || typeof current !== \"object\") return undefined;\r\n if (Array.isArray(current)) {\r\n const index = Number(part);\r\n if (Number.isNaN(index)) return undefined;\r\n current = current[index];\r\n } else {\r\n current = (current as Record<string, unknown>)[part];\r\n }\r\n }\r\n return current;\r\n}\r\n\r\n/**\r\n * Evaluates a single condition rule against form values.\r\n * Supports both flat dotted keys (\"address.city\" as literal key) and\r\n * nested object resolution (values.address.city). Flat key takes priority\r\n * because DynamicFieldWrapper reconstructs watched values as flat keys.\r\n */\r\nfunction evaluateRule<TFieldValues extends FieldValues>(\r\n rule: ConditionRule<TFieldValues>,\r\n formValues: Partial<TFieldValues>,\r\n): boolean {\r\n const watchPath = rule.watch as string;\r\n const obj = formValues as Record<string, unknown>;\r\n // Flat key first (handles DynamicFieldWrapper's { \"address.city\": val }),\r\n // then nested resolution (handles full form values { address: { city: val } })\r\n const value = watchPath in obj\r\n ? obj[watchPath]\r\n : getNestedValue(obj, watchPath);\r\n\r\n switch (rule.operator) {\r\n case \"===\":\r\n return value === rule.value;\r\n case \"!==\":\r\n return value !== rule.value;\r\n case \"in\":\r\n return Array.isArray(rule.value) && rule.value.includes(value);\r\n case \"not-in\":\r\n return Array.isArray(rule.value) && !rule.value.includes(value);\r\n case \"truthy\":\r\n return Boolean(value);\r\n case \"falsy\":\r\n return !value;\r\n default:\r\n return false;\r\n }\r\n}\r\n\r\n/**\r\n * Type guard: checks if a condition is a ConditionConfig (has `rules` array).\r\n */\r\nfunction isConditionConfig<TFieldValues extends FieldValues>(\r\n condition: NonNullable<Condition<TFieldValues>>,\r\n): condition is ConditionConfig<TFieldValues> {\r\n return (\r\n typeof condition === \"object\" &&\r\n !Array.isArray(condition) &&\r\n \"rules\" in condition\r\n );\r\n}\r\n\r\n/**\r\n * Extracts the rules array from any non-function condition shape.\r\n */\r\nfunction toRules<TFieldValues extends FieldValues>(\r\n condition: Exclude<NonNullable<Condition<TFieldValues>>, Function>,\r\n): { rules: ConditionRule<TFieldValues>[]; logic: \"and\" | \"or\" } {\r\n if (isConditionConfig(condition)) {\r\n return { rules: condition.rules, logic: condition.logic ?? \"and\" };\r\n }\r\n const rules = Array.isArray(condition) ? condition : [condition];\r\n return { rules, logic: \"and\" };\r\n}\r\n\r\n// ============================================================================\r\n// Public API\r\n// ============================================================================\r\n\r\n/**\r\n * Evaluates a conditional rule, array of rules, or a ConditionConfig against form values.\r\n * Supports AND (default) and OR logic via ConditionConfig.\r\n *\r\n * @param condition - The condition function, rule(s), or config\r\n * @param formValues - The form values to evaluate against\r\n * @returns boolean indicating if condition matches\r\n */\r\nexport function evaluateCondition<\r\n TFieldValues extends FieldValues = FieldValues,\r\n>(\r\n condition: Condition<TFieldValues>,\r\n formValues: Partial<TFieldValues>,\r\n): boolean {\r\n if (!condition) return true;\r\n\r\n if (typeof condition === \"function\") {\r\n return condition(formValues);\r\n }\r\n\r\n const { rules, logic } = toRules(condition);\r\n const evalFn = (rule: ConditionRule<TFieldValues>) =>\r\n evaluateRule(rule, formValues);\r\n\r\n return logic === \"or\" ? rules.some(evalFn) : rules.every(evalFn);\r\n}\r\n\r\n/**\r\n * Extracts all watch names from a condition to optimize `useWatch`.\r\n * Handles single rules, arrays, and ConditionConfig objects.\r\n */\r\nexport function extractWatchNames<\r\n TFieldValues extends FieldValues = FieldValues,\r\n>(condition: Condition<TFieldValues>): string[] {\r\n if (!condition || typeof condition === \"function\") return [];\r\n\r\n const { rules } = toRules(condition);\r\n return rules.map((r) => r.watch as string);\r\n}\r\n\r\n/**\r\n * Strictly types a comprehensive form schema, granting exact intellisense bounds across conditions and nested watches.\r\n */\r\nexport function defineSchema<TFieldValues extends FieldValues = FieldValues>(\r\n schema: FormSchema<TFieldValues>,\r\n): FormSchema<TFieldValues> {\r\n return schema;\r\n}\r\n\r\n/**\r\n * Standard utility to strictly type a standalone field out-of-bounds, useful for externalizing massive schema structures.\r\n */\r\nexport function defineField<TFieldValues extends FieldValues = FieldValues>(\r\n field: BaseField<TFieldValues>,\r\n): BaseField<TFieldValues> {\r\n return field;\r\n}\r\n\r\n/**\r\n * Standard utility to strictly type a standalone logic section layout block.\r\n */\r\nexport function defineSection<TFieldValues extends FieldValues = FieldValues>(\r\n section: Section<TFieldValues>,\r\n): Section<TFieldValues> {\r\n return section;\r\n}\r\n\r\n/**\r\n * Extracts default values from a form schema.\r\n * Walks all sections and fields, respecting nameSpace prefixes and group nesting.\r\n *\r\n * @example\r\n * ```ts\r\n * const defaults = extractDefaultValues(schema);\r\n * const form = useForm({ defaultValues: defaults });\r\n * ```\r\n */\r\nexport function extractDefaultValues<\r\n TFieldValues extends FieldValues = FieldValues,\r\n>(schema: FormSchema<TFieldValues>): Partial<TFieldValues> {\r\n const defaults: Record<string, unknown> = {};\r\n\r\n for (const section of schema.sections) {\r\n const prefix = section.nameSpace ? `${section.nameSpace}.` : \"\";\r\n if (!section.fields) continue;\r\n\r\n for (const field of section.fields) {\r\n if (field.defaultValue !== undefined) {\r\n defaults[`${prefix}${field.name as string}`] = field.defaultValue;\r\n }\r\n // Handle group itemFields defaults (skip array types — items are dynamic)\r\n if (field.itemFields && field.type !== \"array\") {\r\n for (const sub of field.itemFields) {\r\n if (sub.defaultValue !== undefined) {\r\n defaults[\r\n `${prefix}${field.name as string}.${sub.name as string}`\r\n ] = sub.defaultValue;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n return defaults as Partial<TFieldValues>;\r\n}\r\n\r\n/**\r\n * Generates react-hook-form `RegisterOptions`-compatible validation rules\r\n * from a field's schema props. Maps `required`, `min`, `max`, `minLength`,\r\n * `maxLength`, `pattern`, and `validate` to RHF rules.\r\n *\r\n * @example\r\n * ```tsx\r\n * import { buildValidationRules } from '@classytic/formkit';\r\n *\r\n * function FormInput({ field, control }: FieldComponentProps) {\r\n * const rules = buildValidationRules(field);\r\n * return <Controller name={field.name} control={control} rules={rules} render={...} />;\r\n * }\r\n * ```\r\n */\r\nexport function buildValidationRules<\r\n TFieldValues extends FieldValues = FieldValues,\r\n>(field: BaseField<TFieldValues>): ValidationRules {\r\n const rules: ValidationRules = {};\r\n\r\n if (field.required) {\r\n rules.required = `${field.label || (field.name as string)} is required`;\r\n }\r\n if (field.minLength !== undefined) {\r\n rules.minLength = {\r\n value: field.minLength,\r\n message: `At least ${field.minLength} characters`,\r\n };\r\n }\r\n if (field.maxLength !== undefined) {\r\n rules.maxLength = {\r\n value: field.maxLength,\r\n message: `At most ${field.maxLength} characters`,\r\n };\r\n }\r\n if (field.min !== undefined) {\r\n rules.min = {\r\n value: field.min,\r\n message: `Must be at least ${field.min}`,\r\n };\r\n }\r\n if (field.max !== undefined) {\r\n rules.max = {\r\n value: field.max,\r\n message: `Must be at most ${field.max}`,\r\n };\r\n }\r\n if (field.pattern) {\r\n rules.pattern = {\r\n value: new RegExp(field.pattern),\r\n message: \"Invalid format\",\r\n };\r\n }\r\n if (field.validate) {\r\n rules.validate = field.validate as ValidationRules[\"validate\"];\r\n }\r\n\r\n return rules;\r\n}\r\n","\"use client\";\r\n\r\nimport { useEffect, useState, useMemo, useRef } from \"react\";\r\nimport {\r\n useFormContext,\r\n useFormState,\r\n useWatch,\r\n useFieldArray,\r\n} from \"react-hook-form\";\r\nimport type {\r\n Control,\r\n FieldValues,\r\n FieldArrayPath,\r\n FieldError,\r\n Path,\r\n} from \"react-hook-form\";\r\nimport {\r\n useFieldComponent,\r\n useLayoutComponent,\r\n useFormSystem,\r\n} from \"./FormSystemContext\";\r\nimport { cn, shallowEqual } from \"./utils\";\r\nimport { evaluateCondition, extractWatchNames } from \"./schema\";\r\nimport type {\r\n FormGeneratorProps,\r\n Section,\r\n BaseField,\r\n FieldComponentProps,\r\n Variant,\r\n FormElement,\r\n} from \"./types\";\r\n\r\n// ============================================================================\r\n// Helpers\r\n// ============================================================================\r\n\r\n/** Generate a deterministic field ID for accessibility label-input association. */\r\nfunction toFieldId(name: string): string {\r\n return `formkit-field-${name.replace(/[.[\\]]/g, \"-\")}`;\r\n}\r\n\r\n/**\r\n * Get nested value from an object using dot-notation path.\r\n * Handles array indices: \"items.0.name\" resolves through arrays correctly.\r\n */\r\nfunction getNestedValue(\r\n obj: Record<string, unknown>,\r\n path: string,\r\n): unknown {\r\n const parts = path.split(\".\");\r\n let current: unknown = obj;\r\n for (const part of parts) {\r\n if (current == null || typeof current !== \"object\") return undefined;\r\n if (Array.isArray(current)) {\r\n const index = Number(part);\r\n if (Number.isNaN(index)) return undefined;\r\n current = current[index];\r\n } else {\r\n current = (current as Record<string, unknown>)[part];\r\n }\r\n }\r\n return current;\r\n}\r\n\r\n/**\r\n * Get nested error from react-hook-form errors object.\r\n * Supports dot-notation paths like \"address.street\" and array paths like \"items.0.name\".\r\n */\r\nfunction getNestedError(\r\n errors: Record<string, unknown>,\r\n path: string,\r\n): FieldError | undefined {\r\n const result = getNestedValue(errors, path);\r\n // FieldError has a `message` property\r\n if (result && typeof result === \"object\" && \"message\" in result) {\r\n return result as FieldError;\r\n }\r\n return undefined;\r\n}\r\n\r\n/**\r\n * Prefix field names with a namespace.\r\n * Memoization-friendly: returns the same shape for stable inputs.\r\n */\r\nfunction prefixFields<TFieldValues extends FieldValues>(\r\n fields: BaseField<TFieldValues>[],\r\n nameSpace: string,\r\n): BaseField<TFieldValues>[] {\r\n return fields.map((f) => ({\r\n ...f,\r\n name: `${nameSpace}.${f.name as string}`,\r\n itemFields: f.itemFields?.map((i) => ({\r\n ...i,\r\n name: `${nameSpace}.${f.name as string}.${i.name as string}`,\r\n })),\r\n })) as BaseField<TFieldValues>[];\r\n}\r\n\r\n// ============================================================================\r\n// FormGenerator Component\r\n// ============================================================================\r\n\r\n/**\r\n * FormGenerator - Headless Form Generator Component\r\n *\r\n * Renders a form based on a schema definition, using components registered\r\n * via FormSystemProvider. Supports conditional fields, dynamic layouts,\r\n * and component variants.\r\n *\r\n * @template TFieldValues - Form field values type for type safety\r\n *\r\n * @example\r\n * ```tsx\r\n * import { useFormKit, FormGenerator } from '@classytic/formkit';\r\n *\r\n * const { handleSubmit, generatorProps } = useFormKit({\r\n * schema: formSchema,\r\n * resolver: zodResolver(validationSchema),\r\n * });\r\n *\r\n * return (\r\n * <form onSubmit={handleSubmit(onSubmit)}>\r\n * <FormGenerator {...generatorProps} />\r\n * </form>\r\n * );\r\n * ```\r\n */\r\nexport function FormGenerator<TFieldValues extends FieldValues = FieldValues>({\r\n schema,\r\n control,\r\n disabled = false,\r\n variant,\r\n className,\r\n ref,\r\n}: FormGeneratorProps<TFieldValues>): FormElement {\r\n // Use provided control or fall back to FormProvider context\r\n const formContext = useFormContext<TFieldValues>();\r\n const activeControl = control ?? formContext?.control;\r\n\r\n if (!activeControl) {\r\n console.warn(\r\n \"[FormKit] FormGenerator requires a `control` prop or to be wrapped in a <FormProvider>.\",\r\n );\r\n return null;\r\n }\r\n\r\n // Early return if no schema\r\n if (!schema?.sections || schema.sections.length === 0) {\r\n return null;\r\n }\r\n\r\n return (\r\n <div\r\n ref={ref}\r\n className={cn(\r\n \"formkit-root\",\r\n variant && `formkit-variant-${variant}`,\r\n className,\r\n )}\r\n data-formkit-root=\"\"\r\n >\r\n {schema.sections.map((section, index) => (\r\n <SectionRenderer\r\n key={section.id ?? `section-${index}`}\r\n section={section}\r\n control={activeControl}\r\n disabled={disabled}\r\n variant={variant}\r\n />\r\n ))}\r\n </div>\r\n );\r\n}\r\n\r\n// ============================================================================\r\n// Section Renderer\r\n// ============================================================================\r\n\r\ninterface SectionRendererProps<TFieldValues extends FieldValues = FieldValues> {\r\n section: Section<TFieldValues>;\r\n control?: Control<TFieldValues>;\r\n disabled?: boolean;\r\n variant?: Variant;\r\n}\r\n\r\n/**\r\n * Renders a single section with its fields.\r\n */\r\nfunction SectionRenderer<TFieldValues extends FieldValues = FieldValues>(\r\n props: SectionRendererProps<TFieldValues>,\r\n): FormElement {\r\n if (props.section.condition) {\r\n return <DynamicSectionRenderer {...props} />;\r\n }\r\n return <StaticSectionRenderer {...props} />;\r\n}\r\n\r\n/**\r\n * Section renderer that evaluates conditions reactively.\r\n * Scopes useWatch to only the fields referenced in the condition\r\n * to avoid re-rendering on every form change.\r\n */\r\nfunction DynamicSectionRenderer<\r\n TFieldValues extends FieldValues = FieldValues,\r\n>(props: SectionRendererProps<TFieldValues>): FormElement {\r\n const conditionWatchNames = useMemo(\r\n () => extractWatchNames(props.section.condition),\r\n [props.section.condition],\r\n );\r\n\r\n // Scope watch to condition dependencies when possible\r\n const watchedRaw = conditionWatchNames.length > 0\r\n ? useWatch({ control: props.control, name: conditionWatchNames as unknown as readonly Path<TFieldValues>[] })\r\n : useWatch({ control: props.control });\r\n\r\n // Reconstruct named values if we watched specific names\r\n const sectionValues = useMemo(() => {\r\n if (conditionWatchNames.length > 0 && Array.isArray(watchedRaw)) {\r\n return conditionWatchNames.reduce<Record<string, unknown>>(\r\n (acc, name, i) => ({ ...acc, [name]: watchedRaw[i] }),\r\n {},\r\n );\r\n }\r\n return watchedRaw;\r\n }, [conditionWatchNames, watchedRaw]);\r\n\r\n if (\r\n !evaluateCondition(\r\n props.section.condition,\r\n sectionValues as Partial<TFieldValues>,\r\n )\r\n ) {\r\n return null;\r\n }\r\n return <StaticSectionRenderer {...props} />;\r\n}\r\n\r\nfunction StaticSectionRenderer<\r\n TFieldValues extends FieldValues = FieldValues,\r\n>({\r\n section,\r\n control,\r\n disabled,\r\n variant,\r\n}: SectionRendererProps<TFieldValues>): FormElement {\r\n // Section can override variant\r\n const activeVariant = section.variant ?? variant;\r\n const SectionLayout = useLayoutComponent(\"section\", activeVariant);\r\n\r\n // Memoize namespace-prefixed fields to avoid creating new arrays every render\r\n const resolvedFields = useMemo(() => {\r\n if (section.nameSpace && section.fields) {\r\n return prefixFields(section.fields, section.nameSpace);\r\n }\r\n return section.fields;\r\n }, [section.nameSpace, section.fields]);\r\n\r\n return (\r\n <SectionLayout\r\n title={section.title}\r\n description={section.description}\r\n icon={section.icon}\r\n variant={activeVariant}\r\n className={section.className}\r\n collapsible={section.collapsible}\r\n defaultCollapsed={section.defaultCollapsed}\r\n >\r\n {section.render ? (\r\n // Custom render function\r\n section.render({ control, disabled, section })\r\n ) : (\r\n // Standard grid rendering\r\n <GridRenderer\r\n fields={resolvedFields}\r\n cols={section.cols}\r\n gap={section.gap}\r\n control={control}\r\n disabled={disabled}\r\n variant={activeVariant}\r\n />\r\n )}\r\n </SectionLayout>\r\n );\r\n}\r\n\r\n// ============================================================================\r\n// Grid Renderer\r\n// ============================================================================\r\n\r\ninterface GridRendererProps<TFieldValues extends FieldValues = FieldValues> {\r\n fields?: BaseField<TFieldValues>[];\r\n cols?: number;\r\n gap?: number;\r\n control?: Control<TFieldValues>;\r\n disabled?: boolean;\r\n variant?: Variant;\r\n}\r\n\r\n/**\r\n * Renders a grid of fields with specified column layout.\r\n */\r\nfunction GridRenderer<TFieldValues extends FieldValues = FieldValues>({\r\n fields,\r\n cols = 1,\r\n gap,\r\n control,\r\n disabled,\r\n variant,\r\n}: GridRendererProps<TFieldValues>): FormElement {\r\n const GridLayout = useLayoutComponent(\"grid\", variant);\r\n\r\n if (!fields || fields.length === 0) {\r\n return null;\r\n }\r\n\r\n return (\r\n <GridLayout cols={cols} gap={gap}>\r\n {fields.map((field, index) => (\r\n <FieldWrapper\r\n key={field.name || `field-${index}`}\r\n field={field}\r\n control={control}\r\n disabled={disabled}\r\n variant={variant}\r\n />\r\n ))}\r\n </GridLayout>\r\n );\r\n}\r\n\r\n// ============================================================================\r\n// Field Wrapper\r\n// ============================================================================\r\n\r\ninterface FieldWrapperProps<TFieldValues extends FieldValues = FieldValues> {\r\n field: BaseField<TFieldValues>;\r\n control?: Control<TFieldValues>;\r\n disabled?: boolean;\r\n variant?: Variant;\r\n}\r\n\r\n/**\r\n * Wraps individual fields.\r\n * If the field requires conditional logic or dynamic options, it uses the Dynamic wrapper.\r\n * Otherwise, it uses the Static wrapper, vastly improving performance by skipping `useWatch`.\r\n */\r\nfunction FieldWrapper<TFieldValues extends FieldValues = FieldValues>(\r\n props: FieldWrapperProps<TFieldValues>,\r\n): FormElement {\r\n if (props.field.condition || props.field.loadOptions) {\r\n return <DynamicFieldWrapper {...props} />;\r\n }\r\n return <StaticFieldWrapper {...props} />;\r\n}\r\n\r\n/**\r\n * Dynamic Field Wrapper\r\n * Conditionally calls `useWatch` to trigger re-renders only when form values change.\r\n * Can be optimized further by providing `watchNames` on the field.\r\n */\r\nfunction DynamicFieldWrapper<TFieldValues extends FieldValues = FieldValues>({\r\n field,\r\n control,\r\n disabled,\r\n variant,\r\n}: FieldWrapperProps<TFieldValues>): FormElement {\r\n // Combine explicit watchNames with names extracted from DSL condition rules\r\n const ruleWatchNames = useMemo(\r\n () => extractWatchNames(field.condition),\r\n [field.condition],\r\n );\r\n const explicitWatchNames = useMemo(() => {\r\n if (Array.isArray(field.watchNames)) return field.watchNames as string[];\r\n if (field.watchNames) return [field.watchNames as string];\r\n return [];\r\n }, [field.watchNames]);\r\n\r\n // Stabilize the watch names list across renders using ref comparison\r\n const allWatchNamesRef = useRef<string[]>([]);\r\n const allWatchNames = useMemo(() => {\r\n const next = Array.from(\r\n new Set([...explicitWatchNames, ...ruleWatchNames]),\r\n );\r\n // Only return new array if contents actually changed\r\n if (\r\n next.length === allWatchNamesRef.current.length &&\r\n next.every((n, i) => n === allWatchNamesRef.current[i])\r\n ) {\r\n return allWatchNamesRef.current;\r\n }\r\n allWatchNamesRef.current = next;\r\n return next;\r\n }, [explicitWatchNames, ruleWatchNames]);\r\n\r\n // Watch form values for conditional rendering.\r\n // When specific watch names are available we pass them to limit re-renders;\r\n // otherwise we watch the entire form.\r\n const watchedRaw = allWatchNames.length > 0\r\n ? useWatch({ control, name: allWatchNames as unknown as readonly Path<TFieldValues>[] })\r\n : useWatch({ control });\r\n\r\n // Use shallow comparison to stabilize watched values without JSON.stringify cost\r\n const prevWatchedRef = useRef(watchedRaw);\r\n const stableWatched = useMemo(() => {\r\n if (shallowEqual(prevWatchedRef.current, watchedRaw)) {\r\n return prevWatchedRef.current;\r\n }\r\n prevWatchedRef.current = watchedRaw;\r\n return watchedRaw;\r\n }, [watchedRaw]);\r\n\r\n // Reconstruct correctly typed partial payload for conditions if watchNames arrays were mapped\r\n const watchedValues = useMemo(() => {\r\n if (allWatchNames.length > 0 && Array.isArray(stableWatched)) {\r\n return allWatchNames.reduce<Record<string, unknown>>(\r\n (acc, name, i) => ({ ...acc, [name]: stableWatched[i] }),\r\n {},\r\n );\r\n }\r\n return stableWatched;\r\n }, [allWatchNames, stableWatched]);\r\n\r\n const [options, setOptions] = useState(field.options || []);\r\n const [isLoading, setIsLoading] = useState(false);\r\n // Store loading timeout to cleanly clear debounce sweeps\r\n const timeoutRef = useRef<ReturnType<typeof setTimeout> | null>(null);\r\n\r\n useEffect(() => {\r\n if (!field.loadOptions) return;\r\n\r\n let isActive = true;\r\n\r\n const executeLoad = () => {\r\n const res = field.loadOptions!(\r\n watchedValues as Partial<TFieldValues>,\r\n );\r\n if (res instanceof Promise) {\r\n setIsLoading(true);\r\n res\r\n .then((newOptions) => {\r\n if (isActive) setOptions(newOptions);\r\n })\r\n .catch((err: unknown) => {\r\n if (isActive) {\r\n if (field.onLoadError) {\r\n field.onLoadError(err);\r\n } else {\r\n console.error(\"[FormKit] loadOptions error:\", err);\r\n }\r\n }\r\n })\r\n .finally(() => {\r\n if (isActive) setIsLoading(false);\r\n });\r\n } else {\r\n setOptions(res);\r\n setIsLoading(false);\r\n }\r\n };\r\n\r\n if (field.debounceMs && field.debounceMs > 0) {\r\n if (timeoutRef.current) clearTimeout(timeoutRef.current);\r\n timeoutRef.current = setTimeout(executeLoad, field.debounceMs);\r\n } else {\r\n executeLoad();\r\n }\r\n\r\n return () => {\r\n isActive = false;\r\n if (timeoutRef.current) clearTimeout(timeoutRef.current);\r\n };\r\n }, [watchedValues, field.loadOptions, field.debounceMs, field.onLoadError]);\r\n\r\n // Memoize the augmented field to avoid creating new objects every render\r\n // Must be before the conditional return to satisfy rules of hooks\r\n const loadingState = field.loadOptions ? isLoading : undefined;\r\n const dynamicField = useMemo<BaseField<TFieldValues>>(() => ({\r\n ...field,\r\n options: field.loadOptions ? options : field.options,\r\n isLoading: loadingState,\r\n } as BaseField<TFieldValues>), [field, options, loadingState]);\r\n\r\n // Check field condition\r\n if (\r\n !evaluateCondition(\r\n field.condition,\r\n watchedValues as Partial<TFieldValues>,\r\n )\r\n ) {\r\n return null;\r\n }\r\n\r\n return (\r\n <StaticFieldWrapper\r\n field={dynamicField}\r\n control={control}\r\n disabled={disabled}\r\n variant={variant}\r\n isLoading={loadingState}\r\n />\r\n );\r\n}\r\n\r\n// ============================================================================\r\n// Static Field Wrapper\r\n// ============================================================================\r\n\r\ninterface StaticFieldWrapperProps<TFieldValues extends FieldValues = FieldValues>\r\n extends FieldWrapperProps<TFieldValues> {\r\n isLoading?: boolean;\r\n}\r\n\r\n/**\r\n * Static Field Wrapper\r\n * Handles rendering the actual component via the registry, or via a custom static `render`.\r\n * Does not use `useWatch` internally.\r\n */\r\nfunction StaticFieldWrapper<TFieldValues extends FieldValues = FieldValues>({\r\n field,\r\n control,\r\n disabled,\r\n variant,\r\n isLoading,\r\n}: StaticFieldWrapperProps<TFieldValues>): FormElement {\r\n // All hooks must be called unconditionally at the top\r\n const { components } = useFormSystem();\r\n const fieldName = field.name as string;\r\n const { errors, dirtyFields, touchedFields } = useFormState({\r\n control,\r\n name: fieldName as Path<TFieldValues>,\r\n });\r\n\r\n // Merge disabled states\r\n const isDisabled = disabled || field.disabled;\r\n const fieldId = toFieldId(fieldName);\r\n const fieldError = getNestedError(\r\n errors as Record<string, unknown>,\r\n fieldName,\r\n );\r\n const isDirty = Boolean(\r\n getNestedValue(dirtyFields as Record<string, unknown>, fieldName),\r\n );\r\n const isTouched = Boolean(\r\n getNestedValue(touchedFields as Record<string, unknown>, fieldName),\r\n );\r\n const fieldState = useMemo(\r\n () => ({\r\n invalid: !!fieldError,\r\n isDirty,\r\n isTouched,\r\n isValidating: false,\r\n error: fieldError,\r\n }),\r\n [fieldError, isDirty, isTouched],\r\n );\r\n const activeVariant = field.variant ?? variant;\r\n\r\n // Render override bypassing the registry completely\r\n if (field.render) {\r\n return (\r\n <div\r\n className={cn(\r\n \"formkit-field\",\r\n field.fullWidth && \"col-span-full\",\r\n field.className,\r\n )}\r\n id={fieldId}\r\n data-formkit-field={fieldName}\r\n data-field-type={field.type}\r\n >\r\n {field.render({\r\n ...field,\r\n field,\r\n control: control as Control<TFieldValues>,\r\n disabled: isDisabled,\r\n variant: activeVariant,\r\n error: fieldError,\r\n fieldState,\r\n fieldId,\r\n isLoading,\r\n } as FieldComponentProps<TFieldValues>)}\r\n </div>\r\n );\r\n }\r\n\r\n // Verify if a component explicitly exists for this type, preventing default \"text\" fallback\r\n // from devouring nested group types entirely.\r\n const hasExplicitComponent = Boolean(\r\n components[field.type] ||\r\n (activeVariant &&\r\n components[activeVariant] &&\r\n typeof components[activeVariant] === \"object\" &&\r\n (components[activeVariant] as Record<string, unknown>)[field.type]),\r\n );\r\n\r\n if (\r\n !hasExplicitComponent &&\r\n field.itemFields &&\r\n field.itemFields.length > 0\r\n ) {\r\n if (field.type === \"array\") {\r\n return (\r\n <ArrayFieldFallback\r\n field={field}\r\n control={control}\r\n disabled={isDisabled}\r\n variant={activeVariant}\r\n />\r\n );\r\n }\r\n\r\n // Default Group mapping fallback\r\n return (\r\n <div\r\n className={cn(\r\n \"formkit-field-group\",\r\n field.fullWidth && \"col-span-full\",\r\n field.className,\r\n )}\r\n data-formkit-field={fieldName}\r\n data-field-type={field.type}\r\n >\r\n <GridRenderer\r\n fields={field.itemFields}\r\n control={control}\r\n disabled={isDisabled}\r\n variant={activeVariant}\r\n />\r\n </div>\r\n );\r\n }\r\n\r\n const FieldComponent = useFieldComponent(field.type, activeVariant);\r\n\r\n if (!FieldComponent) {\r\n return null;\r\n }\r\n\r\n return (\r\n <div\r\n className={cn(\r\n \"formkit-field\",\r\n field.fullWidth && \"col-span-full\",\r\n field.className,\r\n )}\r\n id={fieldId}\r\n data-formkit-field={fieldName}\r\n data-field-type={field.type}\r\n >\r\n <FieldComponent\r\n {...(field as BaseField<FieldValues>)}\r\n field={field as BaseField<FieldValues>}\r\n control={control as Control<FieldValues>}\r\n disabled={isDisabled}\r\n variant={activeVariant}\r\n error={fieldError}\r\n fieldState={fieldState}\r\n fieldId={fieldId}\r\n isLoading={isLoading}\r\n />\r\n </div>\r\n );\r\n}\r\n\r\n// ============================================================================\r\n// Array Native Fallback Wrapper\r\n// ============================================================================\r\n\r\nfunction ArrayFieldFallback<TFieldValues extends FieldValues = FieldValues>({\r\n field,\r\n control,\r\n disabled,\r\n variant,\r\n}: FieldWrapperProps<TFieldValues>): FormElement {\r\n const { fields, append, remove } = useFieldArray({\r\n control,\r\n name: field.name as FieldArrayPath<TFieldValues>,\r\n });\r\n\r\n return (\r\n <div\r\n className={cn(\r\n \"formkit-field-array flex flex-col gap-4\",\r\n field.fullWidth && \"col-span-full\",\r\n field.className,\r\n )}\r\n data-formkit-field={field.name}\r\n data-field-type=\"array\"\r\n >\r\n <div className=\"flex items-center justify-between\">\r\n {field.label && (\r\n <label className=\"font-semibold\">{field.label}</label>\r\n )}\r\n </div>\r\n\r\n {fields.map((item, index) => (\r\n <div\r\n key={item.id}\r\n className=\"relative formkit-array-item border p-4 rounded-md\"\r\n >\r\n <GridRenderer\r\n fields={\r\n field.itemFields?.map((f) => ({\r\n ...f,\r\n name: `${field.name as string}.${index}.${f.name as string}`,\r\n })) as BaseField<TFieldValues>[] | undefined\r\n }\r\n control={control}\r\n disabled={disabled}\r\n variant={variant}\r\n />\r\n <button\r\n type=\"button\"\r\n onClick={() => remove(index)}\r\n className=\"absolute top-2 right-2 text-red-500 hover:text-red-700 text-sm font-medium\"\r\n >\r\n Remove\r\n </button>\r\n </div>\r\n ))}\r\n <button\r\n type=\"button\"\r\n onClick={() => append({} as Record<string, unknown> as TFieldValues[string & keyof TFieldValues])}\r\n disabled={disabled}\r\n className=\"self-start mt-2 px-4 py-2 bg-blue-50 text-blue-600 rounded-md text-sm font-medium hover:bg-blue-100 disabled:opacity-50\"\r\n >\r\n + Add Item\r\n </button>\r\n </div>\r\n );\r\n}\r\n\r\n// ============================================================================\r\n// Named Exports for Subcomponents (for advanced use cases)\r\n// ============================================================================\r\n\r\nexport { SectionRenderer, GridRenderer, FieldWrapper };\r\n","import type { ReactNode } from \"react\";\r\nimport type { FieldValues, Control, FieldError } from \"react-hook-form\";\r\nimport type {\r\n BaseField,\r\n FieldOption,\r\n FieldOptionGroup,\r\n Section,\r\n} from \"./types\";\r\n\r\n// ============================================================================\r\n// Types\r\n// ============================================================================\r\n\r\n/**\r\n * Additional field props for builder helpers.\r\n * Accepts all BaseField properties except `name`, `type`, and `label`\r\n * which are set by the builder method.\r\n */\r\ntype FieldProps<TFieldValues extends FieldValues = FieldValues> = Omit<\r\n BaseField<TFieldValues>,\r\n \"name\" | \"type\" | \"label\"\r\n> & {\r\n /** Grid column class (e.g., \"col-span-2\") */\r\n gridColumn?: string;\r\n /** Icon for the left side of input */\r\n iconLeft?: ReactNode;\r\n /** Icon for the right side of input */\r\n iconRight?: ReactNode;\r\n /** Additional custom props */\r\n [key: string]: unknown;\r\n};\r\n\r\n/**\r\n * Section configuration props.\r\n */\r\ninterface SectionProps<TFieldValues extends FieldValues = FieldValues>\r\n extends Omit<Section<TFieldValues>, \"id\" | \"title\" | \"fields\" | \"cols\"> {\r\n cols?: number;\r\n}\r\n\r\n/**\r\n * Render function for custom field types.\r\n */\r\ntype CustomRenderFn = (props: {\r\n control: Control<FieldValues>;\r\n disabled?: boolean;\r\n error?: FieldError;\r\n}) => ReactNode;\r\n\r\n// ============================================================================\r\n// Field Builder\r\n// ============================================================================\r\n\r\n/**\r\n * Type-safe field builder helpers for schema-driven forms.\r\n *\r\n * Provides shorthand methods for common field types with sensible defaults,\r\n * reducing boilerplate while maintaining full type safety.\r\n *\r\n * @example\r\n * ```ts\r\n * import { field, section } from '@classytic/formkit';\r\n *\r\n * const schema = {\r\n * sections: [\r\n * section(\"personal\", \"Personal Info\", [\r\n * field.text(\"firstName\", \"First Name\", { required: true }),\r\n * field.email(\"email\", \"Email\"),\r\n * field.select(\"role\", \"Role\", [\r\n * { label: \"Admin\", value: \"admin\" },\r\n * { label: \"User\", value: \"user\" },\r\n * ]),\r\n * ], { cols: 2 }),\r\n * ],\r\n * };\r\n * ```\r\n */\r\nexport const field = {\r\n /**\r\n * Text input field.\r\n */\r\n text: (\r\n name: string,\r\n label: string,\r\n props: FieldProps = {},\r\n ): BaseField => ({\r\n type: \"text\",\r\n name,\r\n label,\r\n ...props,\r\n }),\r\n\r\n /**\r\n * Email input field with default placeholder.\r\n */\r\n email: (\r\n name: string,\r\n label: string,\r\n props: FieldProps = {},\r\n ): BaseField => ({\r\n type: \"email\",\r\n name,\r\n label,\r\n placeholder: \"example@email.com\",\r\n ...props,\r\n }),\r\n\r\n /**\r\n * URL input field with default placeholder.\r\n */\r\n url: (\r\n name: string,\r\n label: string,\r\n props: FieldProps = {},\r\n ): BaseField => ({\r\n type: \"url\",\r\n name,\r\n label,\r\n placeholder: \"https://example.com\",\r\n ...props,\r\n }),\r\n\r\n /**\r\n * Phone/tel input field with default placeholder.\r\n */\r\n tel: (\r\n name: string,\r\n label: string,\r\n props: FieldProps = {},\r\n ): BaseField => ({\r\n type: \"tel\",\r\n name,\r\n label,\r\n placeholder: \"+1 (555) 000-0000\",\r\n ...props,\r\n }),\r\n\r\n /**\r\n * Password input field.\r\n */\r\n password: (\r\n name: string,\r\n label: string,\r\n props: FieldProps = {},\r\n ): BaseField => ({\r\n type: \"password\",\r\n name,\r\n label,\r\n ...props,\r\n }),\r\n\r\n /**\r\n * Number input field with min: 0 default.\r\n */\r\n number: (\r\n name: string,\r\n label: string,\r\n props: FieldProps = {},\r\n ): BaseField => ({\r\n type: \"number\",\r\n name,\r\n label,\r\n min: 0,\r\n ...props,\r\n }),\r\n\r\n /**\r\n * Textarea field with default 3 rows.\r\n */\r\n textarea: (\r\n name: string,\r\n label: string,\r\n props: FieldProps = {},\r\n ): BaseField => ({\r\n type: \"textarea\",\r\n name,\r\n label,\r\n rows: 3,\r\n ...props,\r\n }),\r\n\r\n /**\r\n * Select dropdown field.\r\n */\r\n select: (\r\n name: string,\r\n label: string,\r\n options: (FieldOption | FieldOptionGroup)[],\r\n props: FieldProps = {},\r\n ): BaseField => ({\r\n type: \"select\",\r\n name,\r\n label,\r\n options,\r\n ...props,\r\n }),\r\n\r\n /**\r\n * Searchable combobox field.\r\n */\r\n combobox: (\r\n name: string,\r\n label: string,\r\n options: (FieldOption | FieldOptionGroup)[],\r\n props: FieldProps = {},\r\n ): BaseField => ({\r\n type: \"combobox\",\r\n name,\r\n label,\r\n options,\r\n ...props,\r\n }),\r\n\r\n /**\r\n * Multi-select field (tag choice).\r\n */\r\n multiselect: (\r\n name: string,\r\n label: string,\r\n options: (FieldOption | FieldOptionGroup)[],\r\n props: FieldProps = {},\r\n ): BaseField => ({\r\n type: \"multiselect\",\r\n name,\r\n label,\r\n options,\r\n placeholder: \"Select options...\",\r\n ...props,\r\n }),\r\n\r\n /**\r\n * Dependent select field that reacts to parent field changes.\r\n */\r\n dependentSelect: (\r\n name: string,\r\n label: string,\r\n props: FieldProps = {},\r\n ): BaseField => ({\r\n type: \"dependentSelect\",\r\n name,\r\n label,\r\n ...props,\r\n }),\r\n\r\n /**\r\n * Switch/toggle field.\r\n */\r\n switch: (\r\n name: string,\r\n label: string,\r\n props: FieldProps = {},\r\n ): BaseField => ({\r\n type: \"switch\",\r\n name,\r\n label,\r\n ...props,\r\n }),\r\n\r\n /**\r\n * Boolean field (alias for switch).\r\n */\r\n boolean: (\r\n name: string,\r\n label: string,\r\n props: FieldProps = {},\r\n ): BaseField => ({\r\n type: \"switch\",\r\n name,\r\n label,\r\n ...props,\r\n }),\r\n\r\n /**\r\n * Checkbox field.\r\n */\r\n checkbox: (\r\n name: string,\r\n label: string,\r\n props: FieldProps = {},\r\n ): BaseField => ({\r\n type: \"checkbox\",\r\n name,\r\n label,\r\n ...props,\r\n }),\r\n\r\n /**\r\n * Radio button group field.\r\n */\r\n radio: (\r\n name: string,\r\n label: string,\r\n options: FieldOption[],\r\n props: FieldProps = {},\r\n ): BaseField => ({\r\n type: \"radio\",\r\n name,\r\n label,\r\n options,\r\n ...props,\r\n }),\r\n\r\n /**\r\n * Date picker field.\r\n */\r\n date: (\r\n name: string,\r\n label: string,\r\n props: FieldProps = {},\r\n ): BaseField => ({\r\n type: \"date\",\r\n name,\r\n label,\r\n ...props,\r\n }),\r\n\r\n /**\r\n * Tag input field with default placeholder.\r\n */\r\n tags: (\r\n name: string,\r\n label: string,\r\n props: FieldProps = {},\r\n ): BaseField => ({\r\n type: \"tags\",\r\n name,\r\n label,\r\n placeholder: \"Add tags...\",\r\n ...props,\r\n }),\r\n\r\n /**\r\n * Slug field with auto-generation from source value.\r\n */\r\n slug: (\r\n name: string,\r\n label: string,\r\n props: FieldProps = {},\r\n ): BaseField => ({\r\n type: \"slug\",\r\n name,\r\n label,\r\n placeholder: \"my-page-slug\",\r\n ...props,\r\n }),\r\n\r\n /**\r\n * File upload field.\r\n */\r\n file: (\r\n name: string,\r\n label: string,\r\n props: FieldProps = {},\r\n ): BaseField => ({\r\n type: \"file\",\r\n name,\r\n label,\r\n ...props,\r\n }),\r\n\r\n /**\r\n * Hidden field (no UI).\r\n */\r\n hidden: (\r\n name: string,\r\n props: FieldProps = {},\r\n ): BaseField => ({\r\n type: \"hidden\",\r\n name,\r\n ...props,\r\n }),\r\n\r\n /**\r\n * Group field for nested objects.\r\n * Renders itemFields as a sub-grid within the form.\r\n *\r\n * @example\r\n * ```ts\r\n * field.group(\"address\", \"Address\", [\r\n * field.text(\"street\", \"Street\"),\r\n * field.text(\"city\", \"City\"),\r\n * field.text(\"zip\", \"ZIP Code\"),\r\n * ], { cols: 3 })\r\n * ```\r\n */\r\n group: (\r\n name: string,\r\n label: string,\r\n itemFields: BaseField[],\r\n props: FieldProps = {},\r\n ): BaseField => ({\r\n type: \"group\",\r\n name,\r\n label,\r\n itemFields,\r\n ...props,\r\n }),\r\n\r\n /**\r\n * Array/repeatable field.\r\n * Renders a dynamic list of sub-forms using react-hook-form's useFieldArray.\r\n *\r\n * @example\r\n * ```ts\r\n * field.array(\"contacts\", \"Contacts\", [\r\n * field.text(\"name\", \"Name\"),\r\n * field.email(\"email\", \"Email\"),\r\n * ])\r\n * ```\r\n */\r\n array: (\r\n name: string,\r\n label: string,\r\n itemFields: BaseField[],\r\n props: FieldProps = {},\r\n ): BaseField => ({\r\n type: \"array\",\r\n name,\r\n label,\r\n itemFields,\r\n ...props,\r\n }),\r\n\r\n /**\r\n * Custom field with a render function.\r\n * Bypasses the component registry entirely.\r\n *\r\n * @example\r\n * ```ts\r\n * field.custom(\"skills\", \"Skills\", ({ control, disabled }) => (\r\n * <SkillSelector control={control} disabled={disabled} />\r\n * ))\r\n * ```\r\n */\r\n custom: (\r\n name: string,\r\n label: string,\r\n render: CustomRenderFn,\r\n props: FieldProps = {},\r\n ): BaseField => ({\r\n type: \"custom\",\r\n name,\r\n label,\r\n render: render as BaseField[\"render\"],\r\n ...props,\r\n }),\r\n};\r\n\r\n// ============================================================================\r\n// Section Builder\r\n// ============================================================================\r\n\r\n/**\r\n * Create a section definition with sensible defaults.\r\n *\r\n * @param id - Unique section identifier\r\n * @param title - Section title\r\n * @param fields - Array of field definitions\r\n * @param props - Additional section configuration\r\n *\r\n * @example\r\n * ```ts\r\n * section(\"personal\", \"Personal Info\", [\r\n * field.text(\"name\", \"Name\", { required: true }),\r\n * field.email(\"email\", \"Email\"),\r\n * ], { cols: 2, variant: \"card\" })\r\n * ```\r\n */\r\nexport function section<TFieldValues extends FieldValues = FieldValues>(\r\n id: string,\r\n title: string,\r\n fields: BaseField<TFieldValues>[],\r\n props: SectionProps<TFieldValues> = {},\r\n): Section<TFieldValues> {\r\n const { cols = 2, ...rest } = props;\r\n return {\r\n id,\r\n title,\r\n fields,\r\n cols,\r\n ...rest,\r\n };\r\n}\r\n\r\n/**\r\n * Create a section without a title (transparent section).\r\n * Useful for grouping fields without visual separation.\r\n */\r\nexport function sectionUntitled<TFieldValues extends FieldValues = FieldValues>(\r\n fields: BaseField<TFieldValues>[],\r\n props: Omit<SectionProps<TFieldValues>, \"variant\"> = {},\r\n): Section<TFieldValues> {\r\n const { cols = 1, ...rest } = props;\r\n return {\r\n fields,\r\n cols,\r\n variant: \"transparent\",\r\n ...rest,\r\n };\r\n}\r\n","\"use client\";\r\n\r\nimport { useMemo } from \"react\";\r\nimport { useForm } from \"react-hook-form\";\r\nimport type { UseFormProps, UseFormReturn, FieldValues } from \"react-hook-form\";\r\nimport { extractDefaultValues } from \"./schema\";\r\nimport type { FormSchema, FormGeneratorProps, Variant } from \"./types\";\r\n\r\n// ============================================================================\r\n// Types\r\n// ============================================================================\r\n\r\n/**\r\n * Options for the useFormKit hook.\r\n * Extends react-hook-form's UseFormProps with schema-driven defaults.\r\n */\r\nexport interface UseFormKitOptions<\r\n TFieldValues extends FieldValues = FieldValues,\r\n> extends Omit<UseFormProps<TFieldValues>, \"defaultValues\"> {\r\n /** Form schema defining sections and fields. Accepts any FormSchema generic. */\r\n schema: FormSchema<any>;\r\n /** Override or extend default values extracted from schema */\r\n defaultValues?: UseFormProps<TFieldValues>[\"defaultValues\"];\r\n /** Disable all fields */\r\n disabled?: boolean;\r\n /** Global variant */\r\n variant?: Variant;\r\n /** Root element className */\r\n className?: string;\r\n}\r\n\r\n/**\r\n * Return value from useFormKit.\r\n * Includes all useForm methods plus pre-built generatorProps.\r\n */\r\nexport interface UseFormKitReturn<\r\n TFieldValues extends FieldValues = FieldValues,\r\n> extends UseFormReturn<TFieldValues> {\r\n /** Props to spread onto <FormGenerator /> */\r\n generatorProps: Pick<\r\n FormGeneratorProps<TFieldValues>,\r\n \"schema\" | \"control\" | \"disabled\" | \"variant\" | \"className\"\r\n >;\r\n}\r\n\r\n// ============================================================================\r\n// Hook\r\n// ============================================================================\r\n\r\n/**\r\n * Convenience hook that combines schema default extraction with react-hook-form setup.\r\n * Returns all useForm methods plus ready-to-spread `generatorProps`.\r\n *\r\n * @example\r\n * ```tsx\r\n * const { handleSubmit, generatorProps } = useFormKit({\r\n * schema: formSchema,\r\n * resolver: zodResolver(validationSchema),\r\n * });\r\n *\r\n * return (\r\n * <form onSubmit={handleSubmit(onSubmit)}>\r\n * <FormGenerator {...generatorProps} />\r\n * <button type=\"submit\">Submit</button>\r\n * </form>\r\n * );\r\n * ```\r\n */\r\nexport function useFormKit<TFieldValues extends FieldValues = FieldValues>(\r\n options: UseFormKitOptions<TFieldValues>,\r\n): UseFormKitReturn<TFieldValues> {\r\n const { schema, disabled, variant, className, defaultValues, ...formOptions } =\r\n options;\r\n\r\n // Extract defaults from schema, merge with explicit overrides\r\n const schemaDefaults = extractDefaultValues(schema);\r\n const mergedDefaults = {\r\n ...schemaDefaults,\r\n ...(typeof defaultValues === \"object\" && defaultValues !== null\r\n ? defaultValues\r\n : {}),\r\n } as UseFormProps<TFieldValues>[\"defaultValues\"];\r\n\r\n const form = useForm<TFieldValues>({\r\n ...formOptions,\r\n defaultValues: mergedDefaults,\r\n });\r\n\r\n const generatorProps = useMemo(\r\n () => ({\r\n schema,\r\n control: form.control,\r\n disabled,\r\n variant,\r\n className,\r\n }),\r\n [schema, form.control, disabled, variant, className],\r\n );\r\n\r\n // Return the original form object with generatorProps attached.\r\n // We assign directly instead of spreading to preserve referential identity\r\n // of the useForm return value — spreading creates a new object every render,\r\n // which breaks useEffect dependency arrays that include the form.\r\n return Object.assign(form, { generatorProps });\r\n}\r\n"],"mappings":"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CX;MAEQ;MApBJ,KAAK,GAqBN,CACN;GACF,oBAAC;IACC,MAAK;IACL,eAAe,OAAO,EAAE,CAAyE;IACvF;IACV,WAAU;cACX;KAEQ;;GACL;;;;;;;;;;;;;;;;;;;;;;;;;;;;;AC3oBV,MAAa,QAAQ;CAInB,OACE,MACA,OACA,QAAoB,EAAE,MACP;EACf,MAAM;EACN;EACA;EACA,GAAG;EACJ;CAKD,QACE,MACA,OACA,QAAoB,EAAE,MACP;EACf,MAAM;EACN;EACA;EACA,aAAa;EACb,GAAG;EACJ;CAKD,MACE,MACA,OACA,QAAoB,EAAE,MACP;EACf,MAAM;EACN;EACA;EACA,aAAa;EACb,GAAG;EACJ;CAKD,MACE,MACA,OACA,QAAoB,EAAE,MACP;EACf,MAAM;EACN;EACA;EACA,aAAa;EACb,GAAG;EACJ;CAKD,WACE,MACA,OACA,QAAoB,EAAE,MACP;EACf,MAAM;EACN;EACA;EACA,GAAG;EACJ;CAKD,SACE,MACA,OACA,QAAoB,EAAE,MACP;EACf,MAAM;EACN;EACA;EACA,KAAK;EACL,GAAG;EACJ;CAKD,WACE,MACA,OACA,QAAoB,EAAE,MACP;EACf,MAAM;EACN;EACA;EACA,MAAM;EACN,GAAG;EACJ;CAKD,SACE,MACA,OACA,SACA,QAAoB,EAAE,MACP;EACf,MAAM;EACN;EACA;EACA;EACA,GAAG;EACJ;CAKD,WACE,MACA,OACA,SACA,QAAoB,EAAE,MACP;EACf,MAAM;EACN;EACA;EACA;EACA,GAAG;EACJ;CAKD,cACE,MACA,OACA,SACA,QAAoB,EAAE,MACP;EACf,MAAM;EACN;EACA;EACA;EACA,aAAa;EACb,GAAG;EACJ;CAKD,kBACE,MACA,OACA,QAAoB,EAAE,MACP;EACf,MAAM;EACN;EACA;EACA,GAAG;EACJ;CAKD,SACE,MACA,OACA,QAAoB,EAAE,MACP;EACf,MAAM;EACN;EACA;EACA,GAAG;EACJ;CAKD,UACE,MACA,OACA,QAAoB,EAAE,MACP;EACf,MAAM;EACN;EACA;EACA,GAAG;EACJ;CAKD,WACE,MACA,OACA,QAAoB,EAAE,MACP;EACf,MAAM;EACN;EACA;EACA,GAAG;EACJ;CAKD,QACE,MACA,OACA,SACA,QAAoB,EAAE,MACP;EACf,MAAM;EACN;EACA;EACA;EACA,GAAG;EACJ;CAKD,OACE,MACA,OACA,QAAoB,EAAE,MACP;EACf,MAAM;EACN;EACA;EACA,GAAG;EACJ;CAKD,OACE,MACA,OACA,QAAoB,EAAE,MACP;EACf,MAAM;EACN;EACA;EACA,aAAa;EACb,GAAG;EACJ;CAKD,OACE,MACA,OACA,QAAoB,EAAE,MACP;EACf,MAAM;EACN;EACA;EACA,aAAa;EACb,GAAG;EACJ;CAKD,OACE,MACA,OACA,QAAoB,EAAE,MACP;EACf,MAAM;EACN;EACA;EACA,GAAG;EACJ;CAKD,SACE,MACA,QAAoB,EAAE,MACP;EACf,MAAM;EACN;EACA,GAAG;EACJ;CAeD,QACE,MACA,OACA,YACA,QAAoB,EAAE,MACP;EACf,MAAM;EACN;EACA;EACA;EACA,GAAG;EACJ;CAcD,QACE,MACA,OACA,YACA,QAAoB,EAAE,MACP;EACf,MAAM;EACN;EACA;EACA;EACA,GAAG;EACJ;CAaD,SACE,MACA,OACA,QACA,QAAoB,EAAE,MACP;EACf,MAAM;EACN;EACA;EACQ;EACR,GAAG;EACJ;CACF;;;;;;;;;;;;;;;;;AAsBD,SAAgB,QACd,IACA,OACA,QACA,QAAoC,EAAE,EACf;CACvB,MAAM,EAAE,OAAO,GAAG,GAAG,SAAS;AAC9B,QAAO;EACL;EACA;EACA;EACA;EACA,GAAG;EACJ;;;;;;AAOH,SAAgB,gBACd,QACA,QAAqD,EAAE,EAChC;CACvB,MAAM,EAAE,OAAO,GAAG,GAAG,SAAS;AAC9B,QAAO;EACL;EACA;EACA,SAAS;EACT,GAAG;EACJ;;;;;;;;;;;;;;;;;;;;;;;;AC9aH,SAAgB,WACd,SACgC;CAChC,MAAM,EAAE,QAAQ,UAAU,SAAS,WAAW,eAAe,GAAG,gBAC9D;CAIF,MAAM,iBAAiB;EACrB,GAFqB,qBAAqB,OAAO;EAGjD,GAAI,OAAO,kBAAkB,YAAY,kBAAkB,OACvD,gBACA,EAAE;EACP;CAED,MAAM,OAAO,QAAsB;EACjC,GAAG;EACH,eAAe;EAChB,CAAC;CAEF,MAAM,iBAAiB,eACd;EACL;EACA,SAAS,KAAK;EACd;EACA;EACA;EACD,GACD;EAAC;EAAQ,KAAK;EAAS;EAAU;EAAS;EAAU,CACrD;AAMD,QAAO,OAAO,OAAO,MAAM,EAAE,gBAAgB,CAAC"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"server.d.mts","names":[],"sources":["../src/utils.ts","../src/types.ts","../src/schema.ts","../src/builders.ts"],"mappings":"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"}
@@ -1 +0,0 @@
1
- {"version":3,"file":"server.mjs","names":[],"sources":["../src/utils.ts","../src/schema.ts","../src/builders.ts"],"sourcesContent":["import { clsx } from \"clsx\";\r\nimport { twMerge } from \"tailwind-merge\";\r\nimport type { ClassValue } from \"clsx\";\r\n\r\n/**\r\n * Utility function to merge CSS classes with Tailwind CSS conflict resolution.\r\n *\r\n * Combines `clsx` for conditional class handling with `tailwind-merge`\r\n * for proper Tailwind CSS class conflict resolution.\r\n *\r\n * @param inputs - Class values to merge (strings, arrays, objects, or conditionals)\r\n * @returns Merged and deduplicated class string\r\n *\r\n * @example\r\n * ```tsx\r\n * // Basic usage\r\n * cn(\"px-2 py-1\", \"px-4\") // \"py-1 px-4\"\r\n *\r\n * // Conditional classes\r\n * cn(\"base\", isActive && \"active\", { \"disabled\": isDisabled })\r\n *\r\n * // Arrays\r\n * cn([\"flex\", \"items-center\"], \"gap-2\")\r\n * ```\r\n */\r\nexport function cn(...inputs: ClassValue[]): string {\r\n return twMerge(clsx(inputs));\r\n}\r\n\r\n/**\r\n * Shallow equality check for arrays and primitives.\r\n * Used to stabilize useWatch output without JSON.stringify overhead.\r\n */\r\nexport function shallowEqual(a: unknown, b: unknown): boolean {\r\n if (Object.is(a, b)) return true;\r\n if (\r\n typeof a !== \"object\" ||\r\n typeof b !== \"object\" ||\r\n a === null ||\r\n b === null\r\n ) {\r\n return false;\r\n }\r\n\r\n if (Array.isArray(a) && Array.isArray(b)) {\r\n if (a.length !== b.length) return false;\r\n for (let i = 0; i < a.length; i++) {\r\n if (!Object.is(a[i], b[i])) return false;\r\n }\r\n return true;\r\n }\r\n\r\n const keysA = Object.keys(a);\r\n const keysB = Object.keys(b);\r\n if (keysA.length !== keysB.length) return false;\r\n\r\n for (const key of keysA) {\r\n if (\r\n !Object.prototype.hasOwnProperty.call(b, key) ||\r\n !Object.is(\r\n (a as Record<string, unknown>)[key],\r\n (b as Record<string, unknown>)[key],\r\n )\r\n ) {\r\n return false;\r\n }\r\n }\r\n return true;\r\n}\r\n\r\n/**\r\n * Re-export ClassValue type for consumers who need it.\r\n */\r\nexport type { ClassValue };\r\n","import type { FieldValues } from \"react-hook-form\";\r\nimport type {\r\n FormSchema,\r\n Section,\r\n BaseField,\r\n ConditionRule,\r\n ConditionConfig,\r\n ValidationRules,\r\n} from \"./types\";\r\n\r\n// ============================================================================\r\n// Condition Types (union used by both evaluateCondition and extractWatchNames)\r\n// ============================================================================\r\n\r\n/**\r\n * All supported condition shapes.\r\n */\r\nexport type Condition<TFieldValues extends FieldValues = FieldValues> =\r\n | ((formValues: Partial<TFieldValues>) => boolean)\r\n | ConditionRule<TFieldValues>\r\n | ConditionRule<TFieldValues>[]\r\n | ConditionConfig<TFieldValues>\r\n | undefined;\r\n\r\n// ============================================================================\r\n// Internal Helpers\r\n// ============================================================================\r\n\r\n/**\r\n * Resolves a dot-notation path against an object.\r\n * Handles array indices: \"items.0.name\" resolves through arrays correctly.\r\n */\r\nfunction getNestedValue(obj: Record<string, unknown>, path: string): unknown {\r\n const parts = path.split(\".\");\r\n let current: unknown = obj;\r\n for (const part of parts) {\r\n if (current == null || typeof current !== \"object\") return undefined;\r\n if (Array.isArray(current)) {\r\n const index = Number(part);\r\n if (Number.isNaN(index)) return undefined;\r\n current = current[index];\r\n } else {\r\n current = (current as Record<string, unknown>)[part];\r\n }\r\n }\r\n return current;\r\n}\r\n\r\n/**\r\n * Evaluates a single condition rule against form values.\r\n * Supports both flat dotted keys (\"address.city\" as literal key) and\r\n * nested object resolution (values.address.city). Flat key takes priority\r\n * because DynamicFieldWrapper reconstructs watched values as flat keys.\r\n */\r\nfunction evaluateRule<TFieldValues extends FieldValues>(\r\n rule: ConditionRule<TFieldValues>,\r\n formValues: Partial<TFieldValues>,\r\n): boolean {\r\n const watchPath = rule.watch as string;\r\n const obj = formValues as Record<string, unknown>;\r\n // Flat key first (handles DynamicFieldWrapper's { \"address.city\": val }),\r\n // then nested resolution (handles full form values { address: { city: val } })\r\n const value = watchPath in obj\r\n ? obj[watchPath]\r\n : getNestedValue(obj, watchPath);\r\n\r\n switch (rule.operator) {\r\n case \"===\":\r\n return value === rule.value;\r\n case \"!==\":\r\n return value !== rule.value;\r\n case \"in\":\r\n return Array.isArray(rule.value) && rule.value.includes(value);\r\n case \"not-in\":\r\n return Array.isArray(rule.value) && !rule.value.includes(value);\r\n case \"truthy\":\r\n return Boolean(value);\r\n case \"falsy\":\r\n return !value;\r\n default:\r\n return false;\r\n }\r\n}\r\n\r\n/**\r\n * Type guard: checks if a condition is a ConditionConfig (has `rules` array).\r\n */\r\nfunction isConditionConfig<TFieldValues extends FieldValues>(\r\n condition: NonNullable<Condition<TFieldValues>>,\r\n): condition is ConditionConfig<TFieldValues> {\r\n return (\r\n typeof condition === \"object\" &&\r\n !Array.isArray(condition) &&\r\n \"rules\" in condition\r\n );\r\n}\r\n\r\n/**\r\n * Extracts the rules array from any non-function condition shape.\r\n */\r\nfunction toRules<TFieldValues extends FieldValues>(\r\n condition: Exclude<NonNullable<Condition<TFieldValues>>, Function>,\r\n): { rules: ConditionRule<TFieldValues>[]; logic: \"and\" | \"or\" } {\r\n if (isConditionConfig(condition)) {\r\n return { rules: condition.rules, logic: condition.logic ?? \"and\" };\r\n }\r\n const rules = Array.isArray(condition) ? condition : [condition];\r\n return { rules, logic: \"and\" };\r\n}\r\n\r\n// ============================================================================\r\n// Public API\r\n// ============================================================================\r\n\r\n/**\r\n * Evaluates a conditional rule, array of rules, or a ConditionConfig against form values.\r\n * Supports AND (default) and OR logic via ConditionConfig.\r\n *\r\n * @param condition - The condition function, rule(s), or config\r\n * @param formValues - The form values to evaluate against\r\n * @returns boolean indicating if condition matches\r\n */\r\nexport function evaluateCondition<\r\n TFieldValues extends FieldValues = FieldValues,\r\n>(\r\n condition: Condition<TFieldValues>,\r\n formValues: Partial<TFieldValues>,\r\n): boolean {\r\n if (!condition) return true;\r\n\r\n if (typeof condition === \"function\") {\r\n return condition(formValues);\r\n }\r\n\r\n const { rules, logic } = toRules(condition);\r\n const evalFn = (rule: ConditionRule<TFieldValues>) =>\r\n evaluateRule(rule, formValues);\r\n\r\n return logic === \"or\" ? rules.some(evalFn) : rules.every(evalFn);\r\n}\r\n\r\n/**\r\n * Extracts all watch names from a condition to optimize `useWatch`.\r\n * Handles single rules, arrays, and ConditionConfig objects.\r\n */\r\nexport function extractWatchNames<\r\n TFieldValues extends FieldValues = FieldValues,\r\n>(condition: Condition<TFieldValues>): string[] {\r\n if (!condition || typeof condition === \"function\") return [];\r\n\r\n const { rules } = toRules(condition);\r\n return rules.map((r) => r.watch as string);\r\n}\r\n\r\n/**\r\n * Strictly types a comprehensive form schema, granting exact intellisense bounds across conditions and nested watches.\r\n */\r\nexport function defineSchema<TFieldValues extends FieldValues = FieldValues>(\r\n schema: FormSchema<TFieldValues>,\r\n): FormSchema<TFieldValues> {\r\n return schema;\r\n}\r\n\r\n/**\r\n * Standard utility to strictly type a standalone field out-of-bounds, useful for externalizing massive schema structures.\r\n */\r\nexport function defineField<TFieldValues extends FieldValues = FieldValues>(\r\n field: BaseField<TFieldValues>,\r\n): BaseField<TFieldValues> {\r\n return field;\r\n}\r\n\r\n/**\r\n * Standard utility to strictly type a standalone logic section layout block.\r\n */\r\nexport function defineSection<TFieldValues extends FieldValues = FieldValues>(\r\n section: Section<TFieldValues>,\r\n): Section<TFieldValues> {\r\n return section;\r\n}\r\n\r\n/**\r\n * Extracts default values from a form schema.\r\n * Walks all sections and fields, respecting nameSpace prefixes and group nesting.\r\n *\r\n * @example\r\n * ```ts\r\n * const defaults = extractDefaultValues(schema);\r\n * const form = useForm({ defaultValues: defaults });\r\n * ```\r\n */\r\nexport function extractDefaultValues<\r\n TFieldValues extends FieldValues = FieldValues,\r\n>(schema: FormSchema<TFieldValues>): Partial<TFieldValues> {\r\n const defaults: Record<string, unknown> = {};\r\n\r\n for (const section of schema.sections) {\r\n const prefix = section.nameSpace ? `${section.nameSpace}.` : \"\";\r\n if (!section.fields) continue;\r\n\r\n for (const field of section.fields) {\r\n if (field.defaultValue !== undefined) {\r\n defaults[`${prefix}${field.name as string}`] = field.defaultValue;\r\n }\r\n // Handle group itemFields defaults (skip array types — items are dynamic)\r\n if (field.itemFields && field.type !== \"array\") {\r\n for (const sub of field.itemFields) {\r\n if (sub.defaultValue !== undefined) {\r\n defaults[\r\n `${prefix}${field.name as string}.${sub.name as string}`\r\n ] = sub.defaultValue;\r\n }\r\n }\r\n }\r\n }\r\n }\r\n\r\n return defaults as Partial<TFieldValues>;\r\n}\r\n\r\n/**\r\n * Generates react-hook-form `RegisterOptions`-compatible validation rules\r\n * from a field's schema props. Maps `required`, `min`, `max`, `minLength`,\r\n * `maxLength`, `pattern`, and `validate` to RHF rules.\r\n *\r\n * @example\r\n * ```tsx\r\n * import { buildValidationRules } from '@classytic/formkit';\r\n *\r\n * function FormInput({ field, control }: FieldComponentProps) {\r\n * const rules = buildValidationRules(field);\r\n * return <Controller name={field.name} control={control} rules={rules} render={...} />;\r\n * }\r\n * ```\r\n */\r\nexport function buildValidationRules<\r\n TFieldValues extends FieldValues = FieldValues,\r\n>(field: BaseField<TFieldValues>): ValidationRules {\r\n const rules: ValidationRules = {};\r\n\r\n if (field.required) {\r\n rules.required = `${field.label || (field.name as string)} is required`;\r\n }\r\n if (field.minLength !== undefined) {\r\n rules.minLength = {\r\n value: field.minLength,\r\n message: `At least ${field.minLength} characters`,\r\n };\r\n }\r\n if (field.maxLength !== undefined) {\r\n rules.maxLength = {\r\n value: field.maxLength,\r\n message: `At most ${field.maxLength} characters`,\r\n };\r\n }\r\n if (field.min !== undefined) {\r\n rules.min = {\r\n value: field.min,\r\n message: `Must be at least ${field.min}`,\r\n };\r\n }\r\n if (field.max !== undefined) {\r\n rules.max = {\r\n value: field.max,\r\n message: `Must be at most ${field.max}`,\r\n };\r\n }\r\n if (field.pattern) {\r\n rules.pattern = {\r\n value: new RegExp(field.pattern),\r\n message: \"Invalid format\",\r\n };\r\n }\r\n if (field.validate) {\r\n rules.validate = field.validate as ValidationRules[\"validate\"];\r\n }\r\n\r\n return rules;\r\n}\r\n","import type { ReactNode } from \"react\";\r\nimport type { FieldValues, Control, FieldError } from \"react-hook-form\";\r\nimport type {\r\n BaseField,\r\n FieldOption,\r\n FieldOptionGroup,\r\n Section,\r\n} from \"./types\";\r\n\r\n// ============================================================================\r\n// Types\r\n// ============================================================================\r\n\r\n/**\r\n * Additional field props for builder helpers.\r\n * Accepts all BaseField properties except `name`, `type`, and `label`\r\n * which are set by the builder method.\r\n */\r\ntype FieldProps<TFieldValues extends FieldValues = FieldValues> = Omit<\r\n BaseField<TFieldValues>,\r\n \"name\" | \"type\" | \"label\"\r\n> & {\r\n /** Grid column class (e.g., \"col-span-2\") */\r\n gridColumn?: string;\r\n /** Icon for the left side of input */\r\n iconLeft?: ReactNode;\r\n /** Icon for the right side of input */\r\n iconRight?: ReactNode;\r\n /** Additional custom props */\r\n [key: string]: unknown;\r\n};\r\n\r\n/**\r\n * Section configuration props.\r\n */\r\ninterface SectionProps<TFieldValues extends FieldValues = FieldValues>\r\n extends Omit<Section<TFieldValues>, \"id\" | \"title\" | \"fields\" | \"cols\"> {\r\n cols?: number;\r\n}\r\n\r\n/**\r\n * Render function for custom field types.\r\n */\r\ntype CustomRenderFn = (props: {\r\n control: Control<FieldValues>;\r\n disabled?: boolean;\r\n error?: FieldError;\r\n}) => ReactNode;\r\n\r\n// ============================================================================\r\n// Field Builder\r\n// ============================================================================\r\n\r\n/**\r\n * Type-safe field builder helpers for schema-driven forms.\r\n *\r\n * Provides shorthand methods for common field types with sensible defaults,\r\n * reducing boilerplate while maintaining full type safety.\r\n *\r\n * @example\r\n * ```ts\r\n * import { field, section } from '@classytic/formkit';\r\n *\r\n * const schema = {\r\n * sections: [\r\n * section(\"personal\", \"Personal Info\", [\r\n * field.text(\"firstName\", \"First Name\", { required: true }),\r\n * field.email(\"email\", \"Email\"),\r\n * field.select(\"role\", \"Role\", [\r\n * { label: \"Admin\", value: \"admin\" },\r\n * { label: \"User\", value: \"user\" },\r\n * ]),\r\n * ], { cols: 2 }),\r\n * ],\r\n * };\r\n * ```\r\n */\r\nexport const field = {\r\n /**\r\n * Text input field.\r\n */\r\n text: (\r\n name: string,\r\n label: string,\r\n props: FieldProps = {},\r\n ): BaseField => ({\r\n type: \"text\",\r\n name,\r\n label,\r\n ...props,\r\n }),\r\n\r\n /**\r\n * Email input field with default placeholder.\r\n */\r\n email: (\r\n name: string,\r\n label: string,\r\n props: FieldProps = {},\r\n ): BaseField => ({\r\n type: \"email\",\r\n name,\r\n label,\r\n placeholder: \"example@email.com\",\r\n ...props,\r\n }),\r\n\r\n /**\r\n * URL input field with default placeholder.\r\n */\r\n url: (\r\n name: string,\r\n label: string,\r\n props: FieldProps = {},\r\n ): BaseField => ({\r\n type: \"url\",\r\n name,\r\n label,\r\n placeholder: \"https://example.com\",\r\n ...props,\r\n }),\r\n\r\n /**\r\n * Phone/tel input field with default placeholder.\r\n */\r\n tel: (\r\n name: string,\r\n label: string,\r\n props: FieldProps = {},\r\n ): BaseField => ({\r\n type: \"tel\",\r\n name,\r\n label,\r\n placeholder: \"+1 (555) 000-0000\",\r\n ...props,\r\n }),\r\n\r\n /**\r\n * Password input field.\r\n */\r\n password: (\r\n name: string,\r\n label: string,\r\n props: FieldProps = {},\r\n ): BaseField => ({\r\n type: \"password\",\r\n name,\r\n label,\r\n ...props,\r\n }),\r\n\r\n /**\r\n * Number input field with min: 0 default.\r\n */\r\n number: (\r\n name: string,\r\n label: string,\r\n props: FieldProps = {},\r\n ): BaseField => ({\r\n type: \"number\",\r\n name,\r\n label,\r\n min: 0,\r\n ...props,\r\n }),\r\n\r\n /**\r\n * Textarea field with default 3 rows.\r\n */\r\n textarea: (\r\n name: string,\r\n label: string,\r\n props: FieldProps = {},\r\n ): BaseField => ({\r\n type: \"textarea\",\r\n name,\r\n label,\r\n rows: 3,\r\n ...props,\r\n }),\r\n\r\n /**\r\n * Select dropdown field.\r\n */\r\n select: (\r\n name: string,\r\n label: string,\r\n options: (FieldOption | FieldOptionGroup)[],\r\n props: FieldProps = {},\r\n ): BaseField => ({\r\n type: \"select\",\r\n name,\r\n label,\r\n options,\r\n ...props,\r\n }),\r\n\r\n /**\r\n * Searchable combobox field.\r\n */\r\n combobox: (\r\n name: string,\r\n label: string,\r\n options: (FieldOption | FieldOptionGroup)[],\r\n props: FieldProps = {},\r\n ): BaseField => ({\r\n type: \"combobox\",\r\n name,\r\n label,\r\n options,\r\n ...props,\r\n }),\r\n\r\n /**\r\n * Multi-select field (tag choice).\r\n */\r\n multiselect: (\r\n name: string,\r\n label: string,\r\n options: (FieldOption | FieldOptionGroup)[],\r\n props: FieldProps = {},\r\n ): BaseField => ({\r\n type: \"multiselect\",\r\n name,\r\n label,\r\n options,\r\n placeholder: \"Select options...\",\r\n ...props,\r\n }),\r\n\r\n /**\r\n * Dependent select field that reacts to parent field changes.\r\n */\r\n dependentSelect: (\r\n name: string,\r\n label: string,\r\n props: FieldProps = {},\r\n ): BaseField => ({\r\n type: \"dependentSelect\",\r\n name,\r\n label,\r\n ...props,\r\n }),\r\n\r\n /**\r\n * Switch/toggle field.\r\n */\r\n switch: (\r\n name: string,\r\n label: string,\r\n props: FieldProps = {},\r\n ): BaseField => ({\r\n type: \"switch\",\r\n name,\r\n label,\r\n ...props,\r\n }),\r\n\r\n /**\r\n * Boolean field (alias for switch).\r\n */\r\n boolean: (\r\n name: string,\r\n label: string,\r\n props: FieldProps = {},\r\n ): BaseField => ({\r\n type: \"switch\",\r\n name,\r\n label,\r\n ...props,\r\n }),\r\n\r\n /**\r\n * Checkbox field.\r\n */\r\n checkbox: (\r\n name: string,\r\n label: string,\r\n props: FieldProps = {},\r\n ): BaseField => ({\r\n type: \"checkbox\",\r\n name,\r\n label,\r\n ...props,\r\n }),\r\n\r\n /**\r\n * Radio button group field.\r\n */\r\n radio: (\r\n name: string,\r\n label: string,\r\n options: FieldOption[],\r\n props: FieldProps = {},\r\n ): BaseField => ({\r\n type: \"radio\",\r\n name,\r\n label,\r\n options,\r\n ...props,\r\n }),\r\n\r\n /**\r\n * Date picker field.\r\n */\r\n date: (\r\n name: string,\r\n label: string,\r\n props: FieldProps = {},\r\n ): BaseField => ({\r\n type: \"date\",\r\n name,\r\n label,\r\n ...props,\r\n }),\r\n\r\n /**\r\n * Tag input field with default placeholder.\r\n */\r\n tags: (\r\n name: string,\r\n label: string,\r\n props: FieldProps = {},\r\n ): BaseField => ({\r\n type: \"tags\",\r\n name,\r\n label,\r\n placeholder: \"Add tags...\",\r\n ...props,\r\n }),\r\n\r\n /**\r\n * Slug field with auto-generation from source value.\r\n */\r\n slug: (\r\n name: string,\r\n label: string,\r\n props: FieldProps = {},\r\n ): BaseField => ({\r\n type: \"slug\",\r\n name,\r\n label,\r\n placeholder: \"my-page-slug\",\r\n ...props,\r\n }),\r\n\r\n /**\r\n * File upload field.\r\n */\r\n file: (\r\n name: string,\r\n label: string,\r\n props: FieldProps = {},\r\n ): BaseField => ({\r\n type: \"file\",\r\n name,\r\n label,\r\n ...props,\r\n }),\r\n\r\n /**\r\n * Hidden field (no UI).\r\n */\r\n hidden: (\r\n name: string,\r\n props: FieldProps = {},\r\n ): BaseField => ({\r\n type: \"hidden\",\r\n name,\r\n ...props,\r\n }),\r\n\r\n /**\r\n * Group field for nested objects.\r\n * Renders itemFields as a sub-grid within the form.\r\n *\r\n * @example\r\n * ```ts\r\n * field.group(\"address\", \"Address\", [\r\n * field.text(\"street\", \"Street\"),\r\n * field.text(\"city\", \"City\"),\r\n * field.text(\"zip\", \"ZIP Code\"),\r\n * ], { cols: 3 })\r\n * ```\r\n */\r\n group: (\r\n name: string,\r\n label: string,\r\n itemFields: BaseField[],\r\n props: FieldProps = {},\r\n ): BaseField => ({\r\n type: \"group\",\r\n name,\r\n label,\r\n itemFields,\r\n ...props,\r\n }),\r\n\r\n /**\r\n * Array/repeatable field.\r\n * Renders a dynamic list of sub-forms using react-hook-form's useFieldArray.\r\n *\r\n * @example\r\n * ```ts\r\n * field.array(\"contacts\", \"Contacts\", [\r\n * field.text(\"name\", \"Name\"),\r\n * field.email(\"email\", \"Email\"),\r\n * ])\r\n * ```\r\n */\r\n array: (\r\n name: string,\r\n label: string,\r\n itemFields: BaseField[],\r\n props: FieldProps = {},\r\n ): BaseField => ({\r\n type: \"array\",\r\n name,\r\n label,\r\n itemFields,\r\n ...props,\r\n }),\r\n\r\n /**\r\n * Custom field with a render function.\r\n * Bypasses the component registry entirely.\r\n *\r\n * @example\r\n * ```ts\r\n * field.custom(\"skills\", \"Skills\", ({ control, disabled }) => (\r\n * <SkillSelector control={control} disabled={disabled} />\r\n * ))\r\n * ```\r\n */\r\n custom: (\r\n name: string,\r\n label: string,\r\n render: CustomRenderFn,\r\n props: FieldProps = {},\r\n ): BaseField => ({\r\n type: \"custom\",\r\n name,\r\n label,\r\n render: render as BaseField[\"render\"],\r\n ...props,\r\n }),\r\n};\r\n\r\n// ============================================================================\r\n// Section Builder\r\n// ============================================================================\r\n\r\n/**\r\n * Create a section definition with sensible defaults.\r\n *\r\n * @param id - Unique section identifier\r\n * @param title - Section title\r\n * @param fields - Array of field definitions\r\n * @param props - Additional section configuration\r\n *\r\n * @example\r\n * ```ts\r\n * section(\"personal\", \"Personal Info\", [\r\n * field.text(\"name\", \"Name\", { required: true }),\r\n * field.email(\"email\", \"Email\"),\r\n * ], { cols: 2, variant: \"card\" })\r\n * ```\r\n */\r\nexport function section<TFieldValues extends FieldValues = FieldValues>(\r\n id: string,\r\n title: string,\r\n fields: BaseField<TFieldValues>[],\r\n props: SectionProps<TFieldValues> = {},\r\n): Section<TFieldValues> {\r\n const { cols = 2, ...rest } = props;\r\n return {\r\n id,\r\n title,\r\n fields,\r\n cols,\r\n ...rest,\r\n };\r\n}\r\n\r\n/**\r\n * Create a section without a title (transparent section).\r\n * Useful for grouping fields without visual separation.\r\n */\r\nexport function sectionUntitled<TFieldValues extends FieldValues = FieldValues>(\r\n fields: BaseField<TFieldValues>[],\r\n props: Omit<SectionProps<TFieldValues>, \"variant\"> = {},\r\n): Section<TFieldValues> {\r\n const { cols = 1, ...rest } = props;\r\n return {\r\n fields,\r\n cols,\r\n variant: \"transparent\",\r\n ...rest,\r\n };\r\n}\r\n"],"mappings":"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,OAAO,IAAI,OAAO,MAAM,QAAQ;EAChC,SAAS;EACV;AAEH,KAAI,MAAM,SACR,OAAM,WAAW,MAAM;AAGzB,QAAO;;;;;;;;;;;;;;;;;;;;;;;;;;;;;ACxMT,MAAa,QAAQ;CAInB,OACE,MACA,OACA,QAAoB,EAAE,MACP;EACf,MAAM;EACN;EACA;EACA,GAAG;EACJ;CAKD,QACE,MACA,OACA,QAAoB,EAAE,MACP;EACf,MAAM;EACN;EACA;EACA,aAAa;EACb,GAAG;EACJ;CAKD,MACE,MACA,OACA,QAAoB,EAAE,MACP;EACf,MAAM;EACN;EACA;EACA,aAAa;EACb,GAAG;EACJ;CAKD,MACE,MACA,OACA,QAAoB,EAAE,MACP;EACf,MAAM;EACN;EACA;EACA,aAAa;EACb,GAAG;EACJ;CAKD,WACE,MACA,OACA,QAAoB,EAAE,MACP;EACf,MAAM;EACN;EACA;EACA,GAAG;EACJ;CAKD,SACE,MACA,OACA,QAAoB,EAAE,MACP;EACf,MAAM;EACN;EACA;EACA,KAAK;EACL,GAAG;EACJ;CAKD,WACE,MACA,OACA,QAAoB,EAAE,MACP;EACf,MAAM;EACN;EACA;EACA,MAAM;EACN,GAAG;EACJ;CAKD,SACE,MACA,OACA,SACA,QAAoB,EAAE,MACP;EACf,MAAM;EACN;EACA;EACA;EACA,GAAG;EACJ;CAKD,WACE,MACA,OACA,SACA,QAAoB,EAAE,MACP;EACf,MAAM;EACN;EACA;EACA;EACA,GAAG;EACJ;CAKD,cACE,MACA,OACA,SACA,QAAoB,EAAE,MACP;EACf,MAAM;EACN;EACA;EACA;EACA,aAAa;EACb,GAAG;EACJ;CAKD,kBACE,MACA,OACA,QAAoB,EAAE,MACP;EACf,MAAM;EACN;EACA;EACA,GAAG;EACJ;CAKD,SACE,MACA,OACA,QAAoB,EAAE,MACP;EACf,MAAM;EACN;EACA;EACA,GAAG;EACJ;CAKD,UACE,MACA,OACA,QAAoB,EAAE,MACP;EACf,MAAM;EACN;EACA;EACA,GAAG;EACJ;CAKD,WACE,MACA,OACA,QAAoB,EAAE,MACP;EACf,MAAM;EACN;EACA;EACA,GAAG;EACJ;CAKD,QACE,MACA,OACA,SACA,QAAoB,EAAE,MACP;EACf,MAAM;EACN;EACA;EACA;EACA,GAAG;EACJ;CAKD,OACE,MACA,OACA,QAAoB,EAAE,MACP;EACf,MAAM;EACN;EACA;EACA,GAAG;EACJ;CAKD,OACE,MACA,OACA,QAAoB,EAAE,MACP;EACf,MAAM;EACN;EACA;EACA,aAAa;EACb,GAAG;EACJ;CAKD,OACE,MACA,OACA,QAAoB,EAAE,MACP;EACf,MAAM;EACN;EACA;EACA,aAAa;EACb,GAAG;EACJ;CAKD,OACE,MACA,OACA,QAAoB,EAAE,MACP;EACf,MAAM;EACN;EACA;EACA,GAAG;EACJ;CAKD,SACE,MACA,QAAoB,EAAE,MACP;EACf,MAAM;EACN;EACA,GAAG;EACJ;CAeD,QACE,MACA,OACA,YACA,QAAoB,EAAE,MACP;EACf,MAAM;EACN;EACA;EACA;EACA,GAAG;EACJ;CAcD,QACE,MACA,OACA,YACA,QAAoB,EAAE,MACP;EACf,MAAM;EACN;EACA;EACA;EACA,GAAG;EACJ;CAaD,SACE,MACA,OACA,QACA,QAAoB,EAAE,MACP;EACf,MAAM;EACN;EACA;EACQ;EACR,GAAG;EACJ;CACF;;;;;;;;;;;;;;;;;AAsBD,SAAgB,QACd,IACA,OACA,QACA,QAAoC,EAAE,EACf;CACvB,MAAM,EAAE,OAAO,GAAG,GAAG,SAAS;AAC9B,QAAO;EACL;EACA;EACA;EACA;EACA,GAAG;EACJ;;;;;;AAOH,SAAgB,gBACd,QACA,QAAqD,EAAE,EAChC;CACvB,MAAM,EAAE,OAAO,GAAG,GAAG,SAAS;AAC9B,QAAO;EACL;EACA;EACA,SAAS;EACT,GAAG;EACJ"}