@classytic/formkit 1.2.0 → 1.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +23 -1
- package/README.md +14 -3
- package/dist/index.d.mts +25 -6
- package/dist/index.mjs +48 -12
- package/dist/server.d.mts +21 -2
- package/dist/server.mjs +32 -2
- package/package.json +4 -4
- package/dist/index.d.mts.map +0 -1
- package/dist/index.mjs.map +0 -1
- package/dist/server.d.mts.map +0 -1
- package/dist/server.mjs.map +0 -1
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,29 @@ 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
|
+
|
|
20
|
+
## [1.2.2] - 2026-02-26
|
|
21
|
+
|
|
22
|
+
### Fixed
|
|
23
|
+
|
|
24
|
+
- **`useFormKit` referential stability** — Return value now preserves the original `useForm` object identity across re-renders using `Object.assign` instead of object spread. Previously, spreading `{...form, generatorProps}` created a new object every render, which caused infinite loops when the form was used in `useEffect` dependency arrays (e.g., `form.reset()` in effects triggered re-renders → new object → effect fires again)
|
|
25
|
+
- **`generatorProps` memoized** — The `generatorProps` object returned by `useFormKit` is now wrapped in `useMemo`, preventing unnecessary re-renders of `<FormGenerator />` when unrelated props change
|
|
26
|
+
|
|
27
|
+
### Added
|
|
28
|
+
|
|
29
|
+
- **Referential stability test** — New test case verifying that `useFormKit` return value and its methods (`reset`, `setValue`, `handleSubmit`) maintain referential identity across re-renders
|
|
30
|
+
|
|
8
31
|
## [1.1.0] - 2026-02-24
|
|
9
32
|
|
|
10
33
|
### Added
|
|
@@ -75,4 +98,3 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|
|
75
98
|
### Added
|
|
76
99
|
|
|
77
100
|
- Initial release
|
|
78
|
-
|
package/README.md
CHANGED
|
@@ -12,7 +12,7 @@ Headless, type-safe form generation engine for React 19. Schema-driven with full
|
|
|
12
12
|
- **Headless** - Bring your own UI components (Shadcn, MUI, Chakra, etc.)
|
|
13
13
|
- **Schema-driven** - Define forms with JSON/TypeScript schemas, defaults extracted automatically
|
|
14
14
|
- **Type-safe** - Full TypeScript support with generics
|
|
15
|
-
- **React Hook Form** - Built on top of the best form library
|
|
15
|
+
- **React Hook Form** - Built on top of the best form library, referentially stable return values
|
|
16
16
|
- **React 19** - Uses modern React 19 patterns (Context as provider, ref as prop)
|
|
17
17
|
- **Server Components** - Dedicated `@classytic/formkit/server` entry point for RSC
|
|
18
18
|
- **Variants** - Support for multiple component variants
|
|
@@ -25,7 +25,7 @@ Headless, type-safe form generation engine for React 19. Schema-driven with full
|
|
|
25
25
|
## Requirements
|
|
26
26
|
|
|
27
27
|
- **React 19.0+** (React 18 is not supported)
|
|
28
|
-
- **React Hook Form 7.
|
|
28
|
+
- **React Hook Form 7.55.0+**
|
|
29
29
|
|
|
30
30
|
## Installation
|
|
31
31
|
|
|
@@ -191,10 +191,12 @@ export default function SignupPage() {
|
|
|
191
191
|
|
|
192
192
|
Convenience hook that combines schema default extraction with react-hook-form setup. Returns all `useForm` methods plus ready-to-spread `generatorProps`.
|
|
193
193
|
|
|
194
|
+
**Referentially stable** — the return value preserves the original `useForm` object identity across re-renders, so it's safe to use in `useEffect` dependency arrays.
|
|
195
|
+
|
|
194
196
|
```tsx
|
|
195
197
|
import { useFormKit, FormGenerator } from "@classytic/formkit";
|
|
196
198
|
|
|
197
|
-
const
|
|
199
|
+
const form = useFormKit({
|
|
198
200
|
schema: formSchema,
|
|
199
201
|
resolver: zodResolver(validationSchema), // optional
|
|
200
202
|
defaultValues: { email: "pre@fill.com" }, // optional overrides
|
|
@@ -204,6 +206,13 @@ const { handleSubmit, generatorProps, formState, reset, ...rest } = useFormKit({
|
|
|
204
206
|
mode: "onBlur", // any useForm option
|
|
205
207
|
});
|
|
206
208
|
|
|
209
|
+
const { handleSubmit, generatorProps } = form;
|
|
210
|
+
|
|
211
|
+
// Safe to use in useEffect deps — form is referentially stable
|
|
212
|
+
useEffect(() => {
|
|
213
|
+
if (open) form.reset(defaults);
|
|
214
|
+
}, [open, form]);
|
|
215
|
+
|
|
207
216
|
return (
|
|
208
217
|
<form onSubmit={handleSubmit(onSubmit)}>
|
|
209
218
|
<FormGenerator {...generatorProps} />
|
|
@@ -214,6 +223,8 @@ return (
|
|
|
214
223
|
|
|
215
224
|
Schema `defaultValue` fields are automatically extracted and merged with any explicit `defaultValues` you provide (explicit values take priority).
|
|
216
225
|
|
|
226
|
+
`generatorProps` is memoized — it only recomputes when `schema`, `control`, `disabled`, `variant`, or `className` change.
|
|
227
|
+
|
|
217
228
|
### FormGenerator
|
|
218
229
|
|
|
219
230
|
The main component that renders forms from a schema. Supports React 19 `ref` as a regular prop.
|
package/dist/index.d.mts
CHANGED
|
@@ -390,8 +390,8 @@ interface FormSystemProviderProps {
|
|
|
390
390
|
* @template TFieldValues - Form field values type
|
|
391
391
|
*/
|
|
392
392
|
interface FormGeneratorProps<TFieldValues extends FieldValues = FieldValues> {
|
|
393
|
-
/** Form schema defining sections and fields */
|
|
394
|
-
schema: FormSchema<
|
|
393
|
+
/** Form schema defining sections and fields. Accepts any FormSchema generic. */
|
|
394
|
+
schema: FormSchema<any>;
|
|
395
395
|
/** React Hook Form control object */
|
|
396
396
|
control?: Control<TFieldValues>;
|
|
397
397
|
/** Global disabled state for all fields */
|
|
@@ -761,6 +761,10 @@ declare const field: {
|
|
|
761
761
|
* Multi-select field (tag choice).
|
|
762
762
|
*/
|
|
763
763
|
multiselect: (name: string, label: string, options: (FieldOption | FieldOptionGroup)[], props?: FieldProps) => BaseField;
|
|
764
|
+
/**
|
|
765
|
+
* Tag choice field for selecting options as tags/chips.
|
|
766
|
+
*/
|
|
767
|
+
tagChoice: (name: string, label: string, options: (FieldOption | FieldOptionGroup)[], props?: FieldProps) => BaseField;
|
|
764
768
|
/**
|
|
765
769
|
* Dependent select field that reacts to parent field changes.
|
|
766
770
|
*/
|
|
@@ -797,6 +801,22 @@ declare const field: {
|
|
|
797
801
|
* File upload field.
|
|
798
802
|
*/
|
|
799
803
|
file: (name: string, label: string, props?: FieldProps) => BaseField;
|
|
804
|
+
/**
|
|
805
|
+
* OTP/PIN input field.
|
|
806
|
+
*/
|
|
807
|
+
otp: (name: string, label: string, props?: FieldProps) => BaseField;
|
|
808
|
+
/**
|
|
809
|
+
* Async searchable combobox with server-side search.
|
|
810
|
+
*/
|
|
811
|
+
asyncCombobox: (name: string, label: string, props?: FieldProps) => BaseField;
|
|
812
|
+
/**
|
|
813
|
+
* Async searchable multi-select with server-side search.
|
|
814
|
+
*/
|
|
815
|
+
asyncMultiselect: (name: string, label: string, props?: FieldProps) => BaseField;
|
|
816
|
+
/**
|
|
817
|
+
* Date and optional time picker field.
|
|
818
|
+
*/
|
|
819
|
+
dateTime: (name: string, label: string, props?: FieldProps) => BaseField;
|
|
800
820
|
/**
|
|
801
821
|
* Hidden field (no UI).
|
|
802
822
|
*/
|
|
@@ -870,8 +890,8 @@ declare function sectionUntitled<TFieldValues extends FieldValues = FieldValues>
|
|
|
870
890
|
* Extends react-hook-form's UseFormProps with schema-driven defaults.
|
|
871
891
|
*/
|
|
872
892
|
interface UseFormKitOptions<TFieldValues extends FieldValues = FieldValues> extends Omit<UseFormProps<TFieldValues>, "defaultValues"> {
|
|
873
|
-
/** Form schema defining sections and fields */
|
|
874
|
-
schema: FormSchema<
|
|
893
|
+
/** Form schema defining sections and fields. Accepts any FormSchema generic. */
|
|
894
|
+
schema: FormSchema<any>;
|
|
875
895
|
/** Override or extend default values extracted from schema */
|
|
876
896
|
defaultValues?: UseFormProps<TFieldValues>["defaultValues"];
|
|
877
897
|
/** Disable all fields */
|
|
@@ -910,5 +930,4 @@ interface UseFormKitReturn<TFieldValues extends FieldValues = FieldValues> exten
|
|
|
910
930
|
*/
|
|
911
931
|
declare function useFormKit<TFieldValues extends FieldValues = FieldValues>(options: UseFormKitOptions<TFieldValues>): UseFormKitReturn<TFieldValues>;
|
|
912
932
|
//#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
|
|
933
|
+
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 };
|
package/dist/index.mjs
CHANGED
|
@@ -868,6 +868,13 @@ const field = {
|
|
|
868
868
|
placeholder: "Select options...",
|
|
869
869
|
...props
|
|
870
870
|
}),
|
|
871
|
+
tagChoice: (name, label, options, props = {}) => ({
|
|
872
|
+
type: "tagChoice",
|
|
873
|
+
name,
|
|
874
|
+
label,
|
|
875
|
+
options,
|
|
876
|
+
...props
|
|
877
|
+
}),
|
|
871
878
|
dependentSelect: (name, label, props = {}) => ({
|
|
872
879
|
type: "dependentSelect",
|
|
873
880
|
name,
|
|
@@ -925,6 +932,30 @@ const field = {
|
|
|
925
932
|
label,
|
|
926
933
|
...props
|
|
927
934
|
}),
|
|
935
|
+
otp: (name, label, props = {}) => ({
|
|
936
|
+
type: "otp",
|
|
937
|
+
name,
|
|
938
|
+
label,
|
|
939
|
+
...props
|
|
940
|
+
}),
|
|
941
|
+
asyncCombobox: (name, label, props = {}) => ({
|
|
942
|
+
type: "asyncCombobox",
|
|
943
|
+
name,
|
|
944
|
+
label,
|
|
945
|
+
...props
|
|
946
|
+
}),
|
|
947
|
+
asyncMultiselect: (name, label, props = {}) => ({
|
|
948
|
+
type: "asyncMultiselect",
|
|
949
|
+
name,
|
|
950
|
+
label,
|
|
951
|
+
...props
|
|
952
|
+
}),
|
|
953
|
+
dateTime: (name, label, props = {}) => ({
|
|
954
|
+
type: "dateTime",
|
|
955
|
+
name,
|
|
956
|
+
label,
|
|
957
|
+
...props
|
|
958
|
+
}),
|
|
928
959
|
hidden: (name, props = {}) => ({
|
|
929
960
|
type: "hidden",
|
|
930
961
|
name,
|
|
@@ -1020,21 +1051,26 @@ function useFormKit(options) {
|
|
|
1020
1051
|
...typeof defaultValues === "object" && defaultValues !== null ? defaultValues : {}
|
|
1021
1052
|
};
|
|
1022
1053
|
const form = useForm({
|
|
1054
|
+
mode: "onBlur",
|
|
1055
|
+
reValidateMode: "onChange",
|
|
1023
1056
|
...formOptions,
|
|
1024
1057
|
defaultValues: mergedDefaults
|
|
1025
1058
|
});
|
|
1026
|
-
|
|
1027
|
-
|
|
1028
|
-
|
|
1029
|
-
|
|
1030
|
-
|
|
1031
|
-
|
|
1032
|
-
|
|
1033
|
-
|
|
1034
|
-
|
|
1035
|
-
|
|
1059
|
+
const generatorProps = useMemo(() => ({
|
|
1060
|
+
schema,
|
|
1061
|
+
control: form.control,
|
|
1062
|
+
disabled,
|
|
1063
|
+
variant,
|
|
1064
|
+
className
|
|
1065
|
+
}), [
|
|
1066
|
+
schema,
|
|
1067
|
+
form.control,
|
|
1068
|
+
disabled,
|
|
1069
|
+
variant,
|
|
1070
|
+
className
|
|
1071
|
+
]);
|
|
1072
|
+
return Object.assign(form, { generatorProps });
|
|
1036
1073
|
}
|
|
1037
1074
|
|
|
1038
1075
|
//#endregion
|
|
1039
|
-
export { FieldWrapper, FormGenerator, FormSystemProvider, GridRenderer, SectionRenderer, buildValidationRules, cn, defineField, defineSchema, defineSection, evaluateCondition, extractDefaultValues, extractWatchNames, field, section, sectionUntitled, shallowEqual, useFieldComponent, useFormKit, useFormSystem, useLayoutComponent };
|
|
1040
|
-
//# sourceMappingURL=index.mjs.map
|
|
1076
|
+
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
|
@@ -518,6 +518,10 @@ declare const field: {
|
|
|
518
518
|
* Multi-select field (tag choice).
|
|
519
519
|
*/
|
|
520
520
|
multiselect: (name: string, label: string, options: (FieldOption | FieldOptionGroup)[], props?: FieldProps) => BaseField;
|
|
521
|
+
/**
|
|
522
|
+
* Tag choice field for selecting options as tags/chips.
|
|
523
|
+
*/
|
|
524
|
+
tagChoice: (name: string, label: string, options: (FieldOption | FieldOptionGroup)[], props?: FieldProps) => BaseField;
|
|
521
525
|
/**
|
|
522
526
|
* Dependent select field that reacts to parent field changes.
|
|
523
527
|
*/
|
|
@@ -554,6 +558,22 @@ declare const field: {
|
|
|
554
558
|
* File upload field.
|
|
555
559
|
*/
|
|
556
560
|
file: (name: string, label: string, props?: FieldProps) => BaseField;
|
|
561
|
+
/**
|
|
562
|
+
* OTP/PIN input field.
|
|
563
|
+
*/
|
|
564
|
+
otp: (name: string, label: string, props?: FieldProps) => BaseField;
|
|
565
|
+
/**
|
|
566
|
+
* Async searchable combobox with server-side search.
|
|
567
|
+
*/
|
|
568
|
+
asyncCombobox: (name: string, label: string, props?: FieldProps) => BaseField;
|
|
569
|
+
/**
|
|
570
|
+
* Async searchable multi-select with server-side search.
|
|
571
|
+
*/
|
|
572
|
+
asyncMultiselect: (name: string, label: string, props?: FieldProps) => BaseField;
|
|
573
|
+
/**
|
|
574
|
+
* Date and optional time picker field.
|
|
575
|
+
*/
|
|
576
|
+
dateTime: (name: string, label: string, props?: FieldProps) => BaseField;
|
|
557
577
|
/**
|
|
558
578
|
* Hidden field (no UI).
|
|
559
579
|
*/
|
|
@@ -621,5 +641,4 @@ declare function section<TFieldValues extends FieldValues = FieldValues>(id: str
|
|
|
621
641
|
*/
|
|
622
642
|
declare function sectionUntitled<TFieldValues extends FieldValues = FieldValues>(fields: BaseField<TFieldValues>[], props?: Omit<SectionProps<TFieldValues>, "variant">): Section<TFieldValues>;
|
|
623
643
|
//#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
|
|
644
|
+
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
|
@@ -289,6 +289,13 @@ const field = {
|
|
|
289
289
|
placeholder: "Select options...",
|
|
290
290
|
...props
|
|
291
291
|
}),
|
|
292
|
+
tagChoice: (name, label, options, props = {}) => ({
|
|
293
|
+
type: "tagChoice",
|
|
294
|
+
name,
|
|
295
|
+
label,
|
|
296
|
+
options,
|
|
297
|
+
...props
|
|
298
|
+
}),
|
|
292
299
|
dependentSelect: (name, label, props = {}) => ({
|
|
293
300
|
type: "dependentSelect",
|
|
294
301
|
name,
|
|
@@ -346,6 +353,30 @@ const field = {
|
|
|
346
353
|
label,
|
|
347
354
|
...props
|
|
348
355
|
}),
|
|
356
|
+
otp: (name, label, props = {}) => ({
|
|
357
|
+
type: "otp",
|
|
358
|
+
name,
|
|
359
|
+
label,
|
|
360
|
+
...props
|
|
361
|
+
}),
|
|
362
|
+
asyncCombobox: (name, label, props = {}) => ({
|
|
363
|
+
type: "asyncCombobox",
|
|
364
|
+
name,
|
|
365
|
+
label,
|
|
366
|
+
...props
|
|
367
|
+
}),
|
|
368
|
+
asyncMultiselect: (name, label, props = {}) => ({
|
|
369
|
+
type: "asyncMultiselect",
|
|
370
|
+
name,
|
|
371
|
+
label,
|
|
372
|
+
...props
|
|
373
|
+
}),
|
|
374
|
+
dateTime: (name, label, props = {}) => ({
|
|
375
|
+
type: "dateTime",
|
|
376
|
+
name,
|
|
377
|
+
label,
|
|
378
|
+
...props
|
|
379
|
+
}),
|
|
349
380
|
hidden: (name, props = {}) => ({
|
|
350
381
|
type: "hidden",
|
|
351
382
|
name,
|
|
@@ -414,5 +445,4 @@ function sectionUntitled(fields, props = {}) {
|
|
|
414
445
|
}
|
|
415
446
|
|
|
416
447
|
//#endregion
|
|
417
|
-
export { buildValidationRules, cn, defineField, defineSchema, defineSection, evaluateCondition, extractDefaultValues, extractWatchNames, field, section, sectionUntitled };
|
|
418
|
-
//# sourceMappingURL=server.mjs.map
|
|
448
|
+
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.
|
|
3
|
+
"version": "1.3.0",
|
|
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": "^
|
|
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": "^
|
|
104
|
+
"vitest": "^4.0.18"
|
|
105
105
|
},
|
|
106
106
|
"engines": {
|
|
107
107
|
"node": ">=18.0.0"
|
|
@@ -110,4 +110,4 @@
|
|
|
110
110
|
"access": "public",
|
|
111
111
|
"registry": "https://registry.npmjs.org/"
|
|
112
112
|
}
|
|
113
|
-
}
|
|
113
|
+
}
|
package/dist/index.d.mts.map
DELETED
|
@@ -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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"}
|
package/dist/index.mjs.map
DELETED
|
@@ -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 { 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 */\r\n schema: FormSchema<TFieldValues>;\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 return {\r\n ...form,\r\n generatorProps: {\r\n schema,\r\n control: form.control,\r\n disabled,\r\n variant,\r\n className,\r\n },\r\n };\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;;;;;;;;;;;;;;;;;;;;;;;;AC/aH,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;AAEF,QAAO;EACL,GAAG;EACH,gBAAgB;GACd;GACA,SAAS,KAAK;GACd;GACA;GACA;GACD;EACF"}
|
package/dist/server.d.mts.map
DELETED
|
@@ -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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"}
|
package/dist/server.mjs.map
DELETED
|
@@ -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"}
|