@juantroconisf/lib 8.0.0 → 9.0.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/dist/index.d.mts CHANGED
@@ -1,4 +1,4 @@
1
- import { SelectProps, AutocompleteProps } from '@heroui/react';
1
+ import { SelectProps, AutocompleteProps, FormProps } from '@heroui/react';
2
2
  import { SingleSelection } from '@react-types/shared';
3
3
  import { Schema, InferType } from 'yup';
4
4
 
@@ -37,7 +37,22 @@ interface FormOptions<O extends StateType> {
37
37
  * Custom property names used as unique identifiers for items in specific arrays.
38
38
  * Default is "id".
39
39
  */
40
- arrayIdentifiers?: Partial<Record<ArrayPaths<O>, string>>;
40
+ arrayIdentifiers?: {
41
+ [K in ArrayPaths<O>]?: NestedFieldValue<O, K> extends (infer E)[] ? E extends object ? ScalarKeys<E> : never : never;
42
+ };
43
+ /**
44
+ * Optional submit handler that is called when the form is submitted and validation passes.
45
+ */
46
+ onFormSubmit?: FormSubmitHandler<O>;
47
+ /**
48
+ * Whether to automatically reset the form after a successful submission.
49
+ * @default false
50
+ */
51
+ resetOnSubmit?: boolean;
52
+ /**
53
+ * Keys to preserve when resetting the form.
54
+ */
55
+ keepValues?: (keyof O)[];
41
56
  }
42
57
  type FieldMetadata = {
43
58
  isTouched: boolean;
@@ -45,10 +60,9 @@ type FieldMetadata = {
45
60
  errorMessage: string;
46
61
  };
47
62
  type MetadataType = Map<string, FieldMetadata>;
48
- type SubmitHandler<O extends StateType> = (data: O, e: React.FormEvent) => void;
49
- interface ResetOptions<O> {
50
- preservedStateKeys?: (keyof O)[];
51
- preserveTouched?: boolean;
63
+ type FormSubmitHandler<O extends StateType> = (data: O, e: React.FormEvent) => void;
64
+ interface FormResetOptions<O> {
65
+ keepValues?: (keyof O)[];
52
66
  }
53
67
  type ValueChangeFunc<O extends StateType, K extends keyof O> = (id: K, value: O[K]) => void;
54
68
  type BlurFunc<O extends StateType> = (id: keyof O) => void;
@@ -81,28 +95,25 @@ interface OnMethods<O extends StateType> {
81
95
  input<P extends AllPaths<O>>(id: P): ItemInputProps<NestedFieldValue<O, P & string>>;
82
96
  /** Registers an array element — adapts to primitive arrays (by index) or object arrays (by ID + field). */
83
97
  /** Registers an array element — adapts to primitive arrays (by index). */
84
- input<K extends ArrayKeys<O>>(arrayKey: K, index: number): ItemInputProps<any>;
98
+ input<K extends ArrayPaths<O>>(arrayKey: K, index: number): ItemInputProps<any>;
85
99
  /** Registers an object array element's field using composite syntax "array.field". */
86
- input<P extends ObjectArrayFieldPaths<O>>(compositePath: P, itemId: ItemIdType<O, GetArrayKeyFromPath<O, P>>): ItemInputProps<any>;
100
+ input<P extends ObjectArrayFieldPaths<O>>(compositePath: P, itemId: string | number): ItemInputProps<any>;
87
101
  /** Registers a scalar or nested object field. */
88
102
  select<P extends AllPaths<O>>(id: P): ItemSelectProps;
89
103
  /** Registers a complete array field for multi-selection. */
90
- select<K extends ArrayKeys<O>>(arrayKey: K): ItemSelectProps;
104
+ select<K extends ArrayPaths<O>>(arrayKey: K): ItemSelectProps;
91
105
  /** Registers an array element — adapts to primitive arrays (by index) or object arrays (by ID + field). */
92
- select<K extends ArrayKeys<O>>(arrayKey: K, index: number): ItemSelectProps;
106
+ select<K extends ArrayPaths<O>>(arrayKey: K, index: number): ItemSelectProps;
93
107
  /** Registers an object array element's field using composite syntax "array.field". */
94
- select<P extends ObjectArrayFieldPaths<O>>(compositePath: P, itemId: ItemIdType<O, GetArrayKeyFromPath<O, P>>): ItemSelectProps;
108
+ select<P extends ObjectArrayFieldPaths<O>>(compositePath: P, itemId: string | number): ItemSelectProps;
95
109
  /** Registers a scalar or nested object field. */
96
110
  autocomplete<P extends AllPaths<O>>(id: P): ItemAutocompleteProps;
97
111
  /** Registers an array element — adapts to primitive arrays (by index) or object arrays (by ID + field). */
98
112
  /** Registers an array element — adapts to primitive arrays (by index). */
99
- autocomplete<K extends ArrayKeys<O>>(arrayKey: K, index: number): ItemAutocompleteProps;
113
+ autocomplete<K extends ArrayPaths<O>>(arrayKey: K, index: number): ItemAutocompleteProps;
100
114
  /** Registers an object array element's field using composite syntax "array.field". */
101
- autocomplete<P extends ObjectArrayFieldPaths<O>>(compositePath: P, itemId: ItemIdType<O, GetArrayKeyFromPath<O, P>>): ItemAutocompleteProps;
115
+ autocomplete<P extends ObjectArrayFieldPaths<O>>(compositePath: P, itemId: string | number): ItemAutocompleteProps;
102
116
  }
103
- type ArrayKeys<O extends StateType> = {
104
- [K in keyof O]: O[K] extends any[] ? K : never;
105
- }[keyof O];
106
117
  /**
107
118
  * Recursive type to find all paths to arrays in the state.
108
119
  */
@@ -120,14 +131,10 @@ type ObjectArrayKeys<O extends StateType> = {
120
131
  type ObjectArrayFieldPaths<O extends StateType> = {
121
132
  [K in keyof O]: O[K] extends Record<string, any>[] ? `${K & string}.${FieldPaths<ArrayElement<O[K]>>}` : never;
122
133
  }[keyof O];
123
- /**
124
- * Helper to extract the array key from a path string like "arrayKey.field".
125
- */
126
- type GetArrayKeyFromPath<O extends StateType, P extends string> = P extends `${infer K}.${string}` ? K extends keyof O ? O[K] extends any[] ? K : never : never : never;
127
134
  type ArrayElement<T> = T extends (infer E)[] ? E : never;
128
135
  /** Resolves the type of the identifier field for an array element (defaults to "id"). */
129
136
  type ItemIdType<O extends StateType, K extends keyof O> = "id" extends keyof ArrayElement<O[K]> ? ArrayElement<O[K]>["id"] : string | number;
130
- type NestedFieldValue<T, F extends string> = F extends `${infer First}.${infer Rest}` ? First extends keyof T ? NestedFieldValue<T[First], Rest> : any : F extends keyof T ? T[F] : any;
137
+ type NestedFieldValue<T, F extends string> = F extends `${infer First}.${infer Rest}` ? First extends keyof T ? NestedFieldValue<NonNullable<T[First]>, Rest> : NonNullable<T> extends (infer U)[] ? NestedFieldValue<U, F> : any : F extends keyof T ? NonNullable<T[F]> : NonNullable<T> extends (infer U)[] ? F extends keyof U ? NonNullable<U[F]> : any : any;
131
138
  type FieldPaths<T> = T extends Record<string, any> ? {
132
139
  [K in keyof T & string]: T[K] extends any[] ? K : T[K] extends Record<string, any> ? `${K}.${FieldPaths<T[K]>}` : K;
133
140
  }[keyof T & string] : never;
@@ -144,19 +151,19 @@ type AllPaths<O extends StateType> = ScalarKeys<O> | NestedObjectPaths<O>;
144
151
  */
145
152
  interface HelpersFunc<O extends StateType> {
146
153
  /** Adds a new item to an array. */
147
- addItem: <K extends ArrayKeys<O>>(arrayKey: K, item: ArrayElement<O[K]>, index?: number) => void;
154
+ addItem: <K extends ArrayPaths<O>>(arrayKey: K, item: NestedFieldValue<O, K> extends (infer E)[] ? E : never, index?: number) => void;
148
155
  /** Removes an item from an array by its index. */
149
- removeItem: <K extends ArrayKeys<O>>(arrayKey: K, index: number) => void;
156
+ removeItem: <K extends ArrayPaths<O>>(arrayKey: K, index: number) => void;
150
157
  /** Removes an item from an array by its unique identifier. */
151
- removeById: <K extends ArrayKeys<O>>(arrayKey: K, itemId: string | number) => void;
158
+ removeById: <K extends ArrayPaths<O>>(arrayKey: K, itemId: string | number) => void;
152
159
  /** Replaces an item in an array at the given index. */
153
- updateItem: <K extends ArrayKeys<O>>(arrayKey: K, index: number, value: ArrayElement<O[K]>) => void;
160
+ updateItem: <K extends ArrayPaths<O>>(arrayKey: K, index: number, value: NestedFieldValue<O, K> extends (infer E)[] ? E : never) => void;
154
161
  /** Moves an item within an array using indices. */
155
- moveItem: <K extends ArrayKeys<O>>(arrayKey: K, from: number, to: number) => void;
162
+ moveItem: <K extends ArrayPaths<O>>(arrayKey: K, from: number, to: number) => void;
156
163
  /** Moves an item within an array using unique identifiers. */
157
- moveById: <K extends ArrayKeys<O>>(arrayKey: K, fromId: string | number, toId: string | number) => void;
164
+ moveById: <K extends ArrayPaths<O>>(arrayKey: K, fromId: string | number, toId: string | number) => void;
158
165
  /** Gets an item from an array by its unique identifier (O(1) via indexMap). */
159
- getItem: <K extends ArrayKeys<O>>(arrayKey: K, itemId: ItemIdType<O, K>) => ArrayElement<O[K]> | undefined;
166
+ getItem: <K extends ArrayPaths<O>>(arrayKey: K, itemId: string | number) => (NestedFieldValue<O, K> extends (infer E)[] ? E : never) | undefined;
160
167
  }
161
168
  /**
162
169
  * The response object from the useForm hook.
@@ -179,17 +186,23 @@ interface UseFormResponse<O extends StateType> {
179
186
  isDirty: boolean;
180
187
  /**
181
188
  * Resets the form state and metadata.
182
- * @param options Configuration for the reset (preserve keys, preserve touched).
189
+ * @param options Configuration for the reset (e.g., keys to keep).
183
190
  */
184
- reset: (options?: ResetOptions<O>) => void;
191
+ onFormReset: (options?: FormResetOptions<O>) => void;
185
192
  /**
186
193
  * Wraps a form submission handler to automatically validate the form.
187
194
  * If validation fails, identifying errors and touching fields.
188
195
  * If validation succeeds, calls the provided handler with the current state.
189
196
  */
190
- onSubmit: (fn: SubmitHandler<O>) => (e: React.FormEvent) => void;
197
+ onFormSubmit: (fn: FormSubmitHandler<O>) => (e: React.FormEvent) => void;
198
+ /**
199
+ * A controlled form component that handles submission and validation.
200
+ */
201
+ ControlledForm: React.ComponentType<Omit<FormProps, "onSubmit"> & {
202
+ onSubmit?: (data: O, e: React.FormEvent<HTMLFormElement>) => void;
203
+ }>;
191
204
  }
192
205
 
193
- declare function useForm<S extends Record<string, ConfigType>>(schema: S, { arrayIdentifiers }?: FormOptions<InferState<S>>): UseFormResponse<InferState<S>>;
206
+ declare function useForm<S extends Record<string, ConfigType>>(schema: S, { arrayIdentifiers, onFormSubmit: onFormSubmitProp, resetOnSubmit, keepValues: keepValuesProp, }?: FormOptions<InferState<S>>): UseFormResponse<InferState<S>>;
194
207
 
195
- export { type BlurFunc, type ConfigType, type FieldMetadata, type FormOptions, type HelpersFunc, type InferState, type MetadataType, type NestedChangeProps, NextUIError, type OnMethods, type StateType, type SubmitHandler, type UseFormResponse, type ValueChangeFunc, useForm };
208
+ export { type BlurFunc, type ConfigType, type FieldMetadata, type FormOptions, type FormSubmitHandler, type HelpersFunc, type InferState, type MetadataType, type NestedChangeProps, NextUIError, type OnMethods, type StateType, type UseFormResponse, type ValueChangeFunc, useForm };
package/dist/index.d.ts CHANGED
@@ -1,4 +1,4 @@
1
- import { SelectProps, AutocompleteProps } from '@heroui/react';
1
+ import { SelectProps, AutocompleteProps, FormProps } from '@heroui/react';
2
2
  import { SingleSelection } from '@react-types/shared';
3
3
  import { Schema, InferType } from 'yup';
4
4
 
@@ -37,7 +37,22 @@ interface FormOptions<O extends StateType> {
37
37
  * Custom property names used as unique identifiers for items in specific arrays.
38
38
  * Default is "id".
39
39
  */
40
- arrayIdentifiers?: Partial<Record<ArrayPaths<O>, string>>;
40
+ arrayIdentifiers?: {
41
+ [K in ArrayPaths<O>]?: NestedFieldValue<O, K> extends (infer E)[] ? E extends object ? ScalarKeys<E> : never : never;
42
+ };
43
+ /**
44
+ * Optional submit handler that is called when the form is submitted and validation passes.
45
+ */
46
+ onFormSubmit?: FormSubmitHandler<O>;
47
+ /**
48
+ * Whether to automatically reset the form after a successful submission.
49
+ * @default false
50
+ */
51
+ resetOnSubmit?: boolean;
52
+ /**
53
+ * Keys to preserve when resetting the form.
54
+ */
55
+ keepValues?: (keyof O)[];
41
56
  }
42
57
  type FieldMetadata = {
43
58
  isTouched: boolean;
@@ -45,10 +60,9 @@ type FieldMetadata = {
45
60
  errorMessage: string;
46
61
  };
47
62
  type MetadataType = Map<string, FieldMetadata>;
48
- type SubmitHandler<O extends StateType> = (data: O, e: React.FormEvent) => void;
49
- interface ResetOptions<O> {
50
- preservedStateKeys?: (keyof O)[];
51
- preserveTouched?: boolean;
63
+ type FormSubmitHandler<O extends StateType> = (data: O, e: React.FormEvent) => void;
64
+ interface FormResetOptions<O> {
65
+ keepValues?: (keyof O)[];
52
66
  }
53
67
  type ValueChangeFunc<O extends StateType, K extends keyof O> = (id: K, value: O[K]) => void;
54
68
  type BlurFunc<O extends StateType> = (id: keyof O) => void;
@@ -81,28 +95,25 @@ interface OnMethods<O extends StateType> {
81
95
  input<P extends AllPaths<O>>(id: P): ItemInputProps<NestedFieldValue<O, P & string>>;
82
96
  /** Registers an array element — adapts to primitive arrays (by index) or object arrays (by ID + field). */
83
97
  /** Registers an array element — adapts to primitive arrays (by index). */
84
- input<K extends ArrayKeys<O>>(arrayKey: K, index: number): ItemInputProps<any>;
98
+ input<K extends ArrayPaths<O>>(arrayKey: K, index: number): ItemInputProps<any>;
85
99
  /** Registers an object array element's field using composite syntax "array.field". */
86
- input<P extends ObjectArrayFieldPaths<O>>(compositePath: P, itemId: ItemIdType<O, GetArrayKeyFromPath<O, P>>): ItemInputProps<any>;
100
+ input<P extends ObjectArrayFieldPaths<O>>(compositePath: P, itemId: string | number): ItemInputProps<any>;
87
101
  /** Registers a scalar or nested object field. */
88
102
  select<P extends AllPaths<O>>(id: P): ItemSelectProps;
89
103
  /** Registers a complete array field for multi-selection. */
90
- select<K extends ArrayKeys<O>>(arrayKey: K): ItemSelectProps;
104
+ select<K extends ArrayPaths<O>>(arrayKey: K): ItemSelectProps;
91
105
  /** Registers an array element — adapts to primitive arrays (by index) or object arrays (by ID + field). */
92
- select<K extends ArrayKeys<O>>(arrayKey: K, index: number): ItemSelectProps;
106
+ select<K extends ArrayPaths<O>>(arrayKey: K, index: number): ItemSelectProps;
93
107
  /** Registers an object array element's field using composite syntax "array.field". */
94
- select<P extends ObjectArrayFieldPaths<O>>(compositePath: P, itemId: ItemIdType<O, GetArrayKeyFromPath<O, P>>): ItemSelectProps;
108
+ select<P extends ObjectArrayFieldPaths<O>>(compositePath: P, itemId: string | number): ItemSelectProps;
95
109
  /** Registers a scalar or nested object field. */
96
110
  autocomplete<P extends AllPaths<O>>(id: P): ItemAutocompleteProps;
97
111
  /** Registers an array element — adapts to primitive arrays (by index) or object arrays (by ID + field). */
98
112
  /** Registers an array element — adapts to primitive arrays (by index). */
99
- autocomplete<K extends ArrayKeys<O>>(arrayKey: K, index: number): ItemAutocompleteProps;
113
+ autocomplete<K extends ArrayPaths<O>>(arrayKey: K, index: number): ItemAutocompleteProps;
100
114
  /** Registers an object array element's field using composite syntax "array.field". */
101
- autocomplete<P extends ObjectArrayFieldPaths<O>>(compositePath: P, itemId: ItemIdType<O, GetArrayKeyFromPath<O, P>>): ItemAutocompleteProps;
115
+ autocomplete<P extends ObjectArrayFieldPaths<O>>(compositePath: P, itemId: string | number): ItemAutocompleteProps;
102
116
  }
103
- type ArrayKeys<O extends StateType> = {
104
- [K in keyof O]: O[K] extends any[] ? K : never;
105
- }[keyof O];
106
117
  /**
107
118
  * Recursive type to find all paths to arrays in the state.
108
119
  */
@@ -120,14 +131,10 @@ type ObjectArrayKeys<O extends StateType> = {
120
131
  type ObjectArrayFieldPaths<O extends StateType> = {
121
132
  [K in keyof O]: O[K] extends Record<string, any>[] ? `${K & string}.${FieldPaths<ArrayElement<O[K]>>}` : never;
122
133
  }[keyof O];
123
- /**
124
- * Helper to extract the array key from a path string like "arrayKey.field".
125
- */
126
- type GetArrayKeyFromPath<O extends StateType, P extends string> = P extends `${infer K}.${string}` ? K extends keyof O ? O[K] extends any[] ? K : never : never : never;
127
134
  type ArrayElement<T> = T extends (infer E)[] ? E : never;
128
135
  /** Resolves the type of the identifier field for an array element (defaults to "id"). */
129
136
  type ItemIdType<O extends StateType, K extends keyof O> = "id" extends keyof ArrayElement<O[K]> ? ArrayElement<O[K]>["id"] : string | number;
130
- type NestedFieldValue<T, F extends string> = F extends `${infer First}.${infer Rest}` ? First extends keyof T ? NestedFieldValue<T[First], Rest> : any : F extends keyof T ? T[F] : any;
137
+ type NestedFieldValue<T, F extends string> = F extends `${infer First}.${infer Rest}` ? First extends keyof T ? NestedFieldValue<NonNullable<T[First]>, Rest> : NonNullable<T> extends (infer U)[] ? NestedFieldValue<U, F> : any : F extends keyof T ? NonNullable<T[F]> : NonNullable<T> extends (infer U)[] ? F extends keyof U ? NonNullable<U[F]> : any : any;
131
138
  type FieldPaths<T> = T extends Record<string, any> ? {
132
139
  [K in keyof T & string]: T[K] extends any[] ? K : T[K] extends Record<string, any> ? `${K}.${FieldPaths<T[K]>}` : K;
133
140
  }[keyof T & string] : never;
@@ -144,19 +151,19 @@ type AllPaths<O extends StateType> = ScalarKeys<O> | NestedObjectPaths<O>;
144
151
  */
145
152
  interface HelpersFunc<O extends StateType> {
146
153
  /** Adds a new item to an array. */
147
- addItem: <K extends ArrayKeys<O>>(arrayKey: K, item: ArrayElement<O[K]>, index?: number) => void;
154
+ addItem: <K extends ArrayPaths<O>>(arrayKey: K, item: NestedFieldValue<O, K> extends (infer E)[] ? E : never, index?: number) => void;
148
155
  /** Removes an item from an array by its index. */
149
- removeItem: <K extends ArrayKeys<O>>(arrayKey: K, index: number) => void;
156
+ removeItem: <K extends ArrayPaths<O>>(arrayKey: K, index: number) => void;
150
157
  /** Removes an item from an array by its unique identifier. */
151
- removeById: <K extends ArrayKeys<O>>(arrayKey: K, itemId: string | number) => void;
158
+ removeById: <K extends ArrayPaths<O>>(arrayKey: K, itemId: string | number) => void;
152
159
  /** Replaces an item in an array at the given index. */
153
- updateItem: <K extends ArrayKeys<O>>(arrayKey: K, index: number, value: ArrayElement<O[K]>) => void;
160
+ updateItem: <K extends ArrayPaths<O>>(arrayKey: K, index: number, value: NestedFieldValue<O, K> extends (infer E)[] ? E : never) => void;
154
161
  /** Moves an item within an array using indices. */
155
- moveItem: <K extends ArrayKeys<O>>(arrayKey: K, from: number, to: number) => void;
162
+ moveItem: <K extends ArrayPaths<O>>(arrayKey: K, from: number, to: number) => void;
156
163
  /** Moves an item within an array using unique identifiers. */
157
- moveById: <K extends ArrayKeys<O>>(arrayKey: K, fromId: string | number, toId: string | number) => void;
164
+ moveById: <K extends ArrayPaths<O>>(arrayKey: K, fromId: string | number, toId: string | number) => void;
158
165
  /** Gets an item from an array by its unique identifier (O(1) via indexMap). */
159
- getItem: <K extends ArrayKeys<O>>(arrayKey: K, itemId: ItemIdType<O, K>) => ArrayElement<O[K]> | undefined;
166
+ getItem: <K extends ArrayPaths<O>>(arrayKey: K, itemId: string | number) => (NestedFieldValue<O, K> extends (infer E)[] ? E : never) | undefined;
160
167
  }
161
168
  /**
162
169
  * The response object from the useForm hook.
@@ -179,17 +186,23 @@ interface UseFormResponse<O extends StateType> {
179
186
  isDirty: boolean;
180
187
  /**
181
188
  * Resets the form state and metadata.
182
- * @param options Configuration for the reset (preserve keys, preserve touched).
189
+ * @param options Configuration for the reset (e.g., keys to keep).
183
190
  */
184
- reset: (options?: ResetOptions<O>) => void;
191
+ onFormReset: (options?: FormResetOptions<O>) => void;
185
192
  /**
186
193
  * Wraps a form submission handler to automatically validate the form.
187
194
  * If validation fails, identifying errors and touching fields.
188
195
  * If validation succeeds, calls the provided handler with the current state.
189
196
  */
190
- onSubmit: (fn: SubmitHandler<O>) => (e: React.FormEvent) => void;
197
+ onFormSubmit: (fn: FormSubmitHandler<O>) => (e: React.FormEvent) => void;
198
+ /**
199
+ * A controlled form component that handles submission and validation.
200
+ */
201
+ ControlledForm: React.ComponentType<Omit<FormProps, "onSubmit"> & {
202
+ onSubmit?: (data: O, e: React.FormEvent<HTMLFormElement>) => void;
203
+ }>;
191
204
  }
192
205
 
193
- declare function useForm<S extends Record<string, ConfigType>>(schema: S, { arrayIdentifiers }?: FormOptions<InferState<S>>): UseFormResponse<InferState<S>>;
206
+ declare function useForm<S extends Record<string, ConfigType>>(schema: S, { arrayIdentifiers, onFormSubmit: onFormSubmitProp, resetOnSubmit, keepValues: keepValuesProp, }?: FormOptions<InferState<S>>): UseFormResponse<InferState<S>>;
194
207
 
195
- export { type BlurFunc, type ConfigType, type FieldMetadata, type FormOptions, type HelpersFunc, type InferState, type MetadataType, type NestedChangeProps, NextUIError, type OnMethods, type StateType, type SubmitHandler, type UseFormResponse, type ValueChangeFunc, useForm };
208
+ export { type BlurFunc, type ConfigType, type FieldMetadata, type FormOptions, type FormSubmitHandler, type HelpersFunc, type InferState, type MetadataType, type NestedChangeProps, NextUIError, type OnMethods, type StateType, type UseFormResponse, type ValueChangeFunc, useForm };
package/dist/index.js CHANGED
@@ -49,7 +49,11 @@ function handleNestedChange({
49
49
  let current = newValues;
50
50
  for (let i = 0; i < propertyDepth.length - 1; i++) {
51
51
  const key = propertyDepth[i];
52
- current[key] = { ...current[key] };
52
+ if (Array.isArray(current[key])) {
53
+ current[key] = [...current[key]];
54
+ } else {
55
+ current[key] = { ...current[key] };
56
+ }
53
57
  current = current[key];
54
58
  }
55
59
  current[propertyDepth[propertyDepth.length - 1]] = value;
@@ -70,7 +74,11 @@ function handleArrayItemChange({
70
74
  } else {
71
75
  let current = item;
72
76
  for (let i = 0; i < fieldDepth.length - 1; i++) {
73
- current[fieldDepth[i]] = { ...current[fieldDepth[i]] };
77
+ if (Array.isArray(current[fieldDepth[i]])) {
78
+ current[fieldDepth[i]] = [...current[fieldDepth[i]]];
79
+ } else {
80
+ current[fieldDepth[i]] = { ...current[fieldDepth[i]] };
81
+ }
74
82
  current = current[fieldDepth[i]];
75
83
  }
76
84
  current[fieldDepth[fieldDepth.length - 1]] = value;
@@ -91,6 +99,9 @@ function removeCompositeKeysByPrefix(map, prefix) {
91
99
  return result;
92
100
  }
93
101
 
102
+ // src/hooks/useForm.tsx
103
+ var import_react3 = require("@heroui/react");
104
+
94
105
  // src/hooks/useComponentLang.tsx
95
106
  var import_yup = require("yup");
96
107
  var import_react = require("react");
@@ -249,7 +260,7 @@ function resolveFieldData(args, state, getIndex, getNestedValue2) {
249
260
  }
250
261
  const arrayKey = arg0;
251
262
  const index = arg1;
252
- const arr = state[arrayKey];
263
+ const arr = getNestedValue2(state, arrayKey);
253
264
  return {
254
265
  type: "primitiveArray" /* PrimitiveArray */,
255
266
  compositeKey: `${arrayKey}.@${index}`,
@@ -304,15 +315,21 @@ function resolveFieldData(args, state, getIndex, getNestedValue2) {
304
315
 
305
316
  // src/hooks/useForm.tsx
306
317
  var import_yup2 = require("yup");
318
+ var import_jsx_runtime = require("react/jsx-runtime");
307
319
  var DEFAULT_OPTIONS = {};
308
- function useForm(schema, { arrayIdentifiers } = DEFAULT_OPTIONS) {
320
+ function useForm(schema, {
321
+ arrayIdentifiers,
322
+ onFormSubmit: onFormSubmitProp,
323
+ resetOnSubmit = false,
324
+ keepValues: keepValuesProp
325
+ } = DEFAULT_OPTIONS) {
309
326
  const { initialState, validationSchema } = (0, import_react2.useMemo)(() => {
310
327
  const state2 = {};
311
328
  const extractedRules = {};
312
329
  Object.entries(schema).forEach(([key, value]) => {
313
330
  if ((0, import_yup2.isSchema)(value)) {
314
331
  try {
315
- state2[key] = value.getDefault();
332
+ state2[key] = value.cast(void 0);
316
333
  } catch {
317
334
  state2[key] = void 0;
318
335
  }
@@ -524,9 +541,12 @@ function useForm(schema, { arrayIdentifiers } = DEFAULT_OPTIONS) {
524
541
  });
525
542
  }
526
543
  if (type === "primitiveArray" /* PrimitiveArray */) {
527
- const arr = [...prev[arrayKey]];
528
- arr[index] = finalValue;
529
- return { ...prev, [arrayKey]: arr };
544
+ return handleNestedChange({
545
+ state: prev,
546
+ id: `${arrayKey}.${index}`,
547
+ value: finalValue,
548
+ hasNestedValues: true
549
+ });
530
550
  }
531
551
  if (type === "objectArray" /* ObjectArray */) {
532
552
  return handleArrayItemChange({
@@ -640,21 +660,31 @@ function useForm(schema, { arrayIdentifiers } = DEFAULT_OPTIONS) {
640
660
  () => ({
641
661
  addItem: (arrayKey, item, index) => {
642
662
  setState((prev) => {
643
- const arr = [...prev[arrayKey]];
663
+ const arr = [...getNestedValue(prev, arrayKey) || []];
644
664
  if (index === void 0) arr.push(item);
645
665
  else arr.splice(index, 0, item);
646
- return { ...prev, [arrayKey]: arr };
666
+ return handleNestedChange({
667
+ state: prev,
668
+ id: arrayKey,
669
+ value: arr,
670
+ hasNestedValues: String(arrayKey).includes(".")
671
+ });
647
672
  });
648
673
  },
649
674
  removeItem: (arrayKey, index) => {
650
- const currentArr = stateRef.current[arrayKey];
675
+ const currentArr = getNestedValue(stateRef.current, arrayKey) || [];
651
676
  const item = currentArr[index];
652
677
  const idKey = arrayIdentifiers?.[arrayKey] || "id";
653
678
  const itemId = item?.[idKey];
654
679
  setState((prev) => {
655
- const arr = [...prev[arrayKey]];
680
+ const arr = [...getNestedValue(prev, arrayKey) || []];
656
681
  arr.splice(index, 1);
657
- return { ...prev, [arrayKey]: arr };
682
+ return handleNestedChange({
683
+ state: prev,
684
+ id: arrayKey,
685
+ value: arr,
686
+ hasNestedValues: String(arrayKey).includes(".")
687
+ });
658
688
  });
659
689
  if (itemId !== void 0) {
660
690
  const prefix = `${String(arrayKey)}.${itemId}.`;
@@ -665,9 +695,14 @@ function useForm(schema, { arrayIdentifiers } = DEFAULT_OPTIONS) {
665
695
  const index = getIndex(arrayKey, itemId);
666
696
  if (index !== void 0) {
667
697
  setState((prev) => {
668
- const arr = [...prev[arrayKey]];
698
+ const arr = [...getNestedValue(prev, arrayKey) || []];
669
699
  arr.splice(index, 1);
670
- return { ...prev, [arrayKey]: arr };
700
+ return handleNestedChange({
701
+ state: prev,
702
+ id: arrayKey,
703
+ value: arr,
704
+ hasNestedValues: String(arrayKey).includes(".")
705
+ });
671
706
  });
672
707
  const prefix = `${String(arrayKey)}.${itemId}.`;
673
708
  setMetadata((prev) => removeCompositeKeysByPrefix(prev, prefix));
@@ -675,17 +710,27 @@ function useForm(schema, { arrayIdentifiers } = DEFAULT_OPTIONS) {
675
710
  },
676
711
  updateItem: (arrayKey, index, value) => {
677
712
  setState((prev) => {
678
- const arr = [...prev[arrayKey]];
713
+ const arr = [...getNestedValue(prev, arrayKey) || []];
679
714
  arr[index] = value;
680
- return { ...prev, [arrayKey]: arr };
715
+ return handleNestedChange({
716
+ state: prev,
717
+ id: arrayKey,
718
+ value: arr,
719
+ hasNestedValues: String(arrayKey).includes(".")
720
+ });
681
721
  });
682
722
  },
683
723
  moveItem: (arrayKey, from, to) => {
684
724
  setState((prev) => {
685
- const arr = [...prev[arrayKey]];
725
+ const arr = [...getNestedValue(prev, arrayKey) || []];
686
726
  const [item] = arr.splice(from, 1);
687
727
  arr.splice(to, 0, item);
688
- return { ...prev, [arrayKey]: arr };
728
+ return handleNestedChange({
729
+ state: prev,
730
+ id: arrayKey,
731
+ value: arr,
732
+ hasNestedValues: String(arrayKey).includes(".")
733
+ });
689
734
  });
690
735
  },
691
736
  moveById: (arrayKey, fromId, toId) => {
@@ -693,17 +738,22 @@ function useForm(schema, { arrayIdentifiers } = DEFAULT_OPTIONS) {
693
738
  const toIndex = getIndex(arrayKey, toId);
694
739
  if (fromIndex !== void 0 && toIndex !== void 0) {
695
740
  setState((prev) => {
696
- const arr = [...prev[arrayKey]];
741
+ const arr = [...getNestedValue(prev, arrayKey) || []];
697
742
  const [item] = arr.splice(fromIndex, 1);
698
743
  arr.splice(toIndex, 0, item);
699
- return { ...prev, [arrayKey]: arr };
744
+ return handleNestedChange({
745
+ state: prev,
746
+ id: arrayKey,
747
+ value: arr,
748
+ hasNestedValues: String(arrayKey).includes(".")
749
+ });
700
750
  });
701
751
  }
702
752
  },
703
753
  getItem: (arrayKey, itemId) => {
704
754
  const index = getIndex(arrayKey, itemId);
705
755
  if (index === void 0) return void 0;
706
- return stateRef.current[arrayKey][index];
756
+ return getNestedValue(stateRef.current, arrayKey)[index];
707
757
  }
708
758
  }),
709
759
  [getIndex, arrayIdentifiers]
@@ -746,7 +796,7 @@ function useForm(schema, { arrayIdentifiers } = DEFAULT_OPTIONS) {
746
796
  },
747
797
  [validateField]
748
798
  );
749
- const onSubmit = (0, import_react2.useCallback)(
799
+ const onFormSubmit = (0, import_react2.useCallback)(
750
800
  (fn) => (e) => {
751
801
  e.preventDefault();
752
802
  if (validateAll()) return;
@@ -754,6 +804,48 @@ function useForm(schema, { arrayIdentifiers } = DEFAULT_OPTIONS) {
754
804
  },
755
805
  [validateAll]
756
806
  );
807
+ const onFormSubmitPropRef = (0, import_react2.useRef)(onFormSubmitProp);
808
+ onFormSubmitPropRef.current = onFormSubmitProp;
809
+ const resetOnSubmitRef = (0, import_react2.useRef)(resetOnSubmit);
810
+ resetOnSubmitRef.current = resetOnSubmit;
811
+ const keepValuesPropRef = (0, import_react2.useRef)(keepValuesProp);
812
+ keepValuesPropRef.current = keepValuesProp;
813
+ const handleReset = (0, import_react2.useCallback)(
814
+ (options) => {
815
+ const { keepValues } = options || {};
816
+ if (keepValues && keepValues.length > 0) {
817
+ const nextState = { ...initialState };
818
+ keepValues.forEach((k) => {
819
+ if (stateRef.current[k] !== void 0)
820
+ nextState[k] = stateRef.current[k];
821
+ });
822
+ setState(nextState);
823
+ } else {
824
+ setState(initialState);
825
+ }
826
+ setMetadata(/* @__PURE__ */ new Map());
827
+ },
828
+ [initialState]
829
+ );
830
+ const validateAllRef = (0, import_react2.useRef)(validateAll);
831
+ validateAllRef.current = validateAll;
832
+ const ControlledForm = (0, import_react2.useMemo)(() => {
833
+ return (props) => {
834
+ const { onSubmit, ...rest } = props;
835
+ const handleSubmit = (e) => {
836
+ e.preventDefault();
837
+ if (validateAllRef.current()) {
838
+ return;
839
+ }
840
+ onFormSubmitPropRef.current?.(stateRef.current, e);
841
+ if (resetOnSubmitRef.current) {
842
+ handleReset({ keepValues: keepValuesPropRef.current });
843
+ }
844
+ onSubmit?.(stateRef.current, e);
845
+ };
846
+ return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_react3.Form, { onSubmit: handleSubmit, ...rest });
847
+ };
848
+ }, []);
757
849
  return (0, import_react2.useMemo)(
758
850
  () => ({
759
851
  state,
@@ -765,37 +857,9 @@ function useForm(schema, { arrayIdentifiers } = DEFAULT_OPTIONS) {
765
857
  onFieldBlur: onBlur,
766
858
  onSelectionChange: polymorphicOnSelectionChange,
767
859
  isDirty: Array.from(metadata.values()).some((m) => m.isTouched),
768
- reset: (options) => {
769
- const { preservedStateKeys, preserveTouched } = options || {};
770
- if (preservedStateKeys && preservedStateKeys.length > 0) {
771
- const nextState = { ...initialState };
772
- preservedStateKeys.forEach((k) => {
773
- if (stateRef.current[k] !== void 0)
774
- nextState[k] = stateRef.current[k];
775
- });
776
- setState(nextState);
777
- } else {
778
- setState(initialState);
779
- }
780
- if (preserveTouched) {
781
- setMetadata((prev) => {
782
- const next = /* @__PURE__ */ new Map();
783
- prev.forEach((v, k) => {
784
- if (v.isTouched) {
785
- next.set(k, {
786
- isTouched: true,
787
- isInvalid: false,
788
- errorMessage: ""
789
- });
790
- }
791
- });
792
- return next;
793
- });
794
- } else {
795
- setMetadata(/* @__PURE__ */ new Map());
796
- }
797
- },
798
- onSubmit
860
+ onFormReset: handleReset,
861
+ onFormSubmit,
862
+ ControlledForm
799
863
  }),
800
864
  [
801
865
  state,
@@ -807,7 +871,8 @@ function useForm(schema, { arrayIdentifiers } = DEFAULT_OPTIONS) {
807
871
  polymorphicOnValueChange,
808
872
  polymorphicOnSelectionChange,
809
873
  validateAll,
810
- onSubmit,
874
+ onFormSubmit,
875
+ ControlledForm,
811
876
  initialState
812
877
  ]
813
878
  );
package/dist/index.mjs CHANGED
@@ -23,7 +23,11 @@ function handleNestedChange({
23
23
  let current = newValues;
24
24
  for (let i = 0; i < propertyDepth.length - 1; i++) {
25
25
  const key = propertyDepth[i];
26
- current[key] = { ...current[key] };
26
+ if (Array.isArray(current[key])) {
27
+ current[key] = [...current[key]];
28
+ } else {
29
+ current[key] = { ...current[key] };
30
+ }
27
31
  current = current[key];
28
32
  }
29
33
  current[propertyDepth[propertyDepth.length - 1]] = value;
@@ -44,7 +48,11 @@ function handleArrayItemChange({
44
48
  } else {
45
49
  let current = item;
46
50
  for (let i = 0; i < fieldDepth.length - 1; i++) {
47
- current[fieldDepth[i]] = { ...current[fieldDepth[i]] };
51
+ if (Array.isArray(current[fieldDepth[i]])) {
52
+ current[fieldDepth[i]] = [...current[fieldDepth[i]]];
53
+ } else {
54
+ current[fieldDepth[i]] = { ...current[fieldDepth[i]] };
55
+ }
48
56
  current = current[fieldDepth[i]];
49
57
  }
50
58
  current[fieldDepth[fieldDepth.length - 1]] = value;
@@ -65,6 +73,9 @@ function removeCompositeKeysByPrefix(map, prefix) {
65
73
  return result;
66
74
  }
67
75
 
76
+ // src/hooks/useForm.tsx
77
+ import { Form } from "@heroui/react";
78
+
68
79
  // src/hooks/useComponentLang.tsx
69
80
  import { setLocale } from "yup";
70
81
  import { useEffect } from "react";
@@ -223,7 +234,7 @@ function resolveFieldData(args, state, getIndex, getNestedValue2) {
223
234
  }
224
235
  const arrayKey = arg0;
225
236
  const index = arg1;
226
- const arr = state[arrayKey];
237
+ const arr = getNestedValue2(state, arrayKey);
227
238
  return {
228
239
  type: "primitiveArray" /* PrimitiveArray */,
229
240
  compositeKey: `${arrayKey}.@${index}`,
@@ -278,15 +289,21 @@ function resolveFieldData(args, state, getIndex, getNestedValue2) {
278
289
 
279
290
  // src/hooks/useForm.tsx
280
291
  import { isSchema, object, reach } from "yup";
292
+ import { jsx } from "react/jsx-runtime";
281
293
  var DEFAULT_OPTIONS = {};
282
- function useForm(schema, { arrayIdentifiers } = DEFAULT_OPTIONS) {
294
+ function useForm(schema, {
295
+ arrayIdentifiers,
296
+ onFormSubmit: onFormSubmitProp,
297
+ resetOnSubmit = false,
298
+ keepValues: keepValuesProp
299
+ } = DEFAULT_OPTIONS) {
283
300
  const { initialState, validationSchema } = useMemo(() => {
284
301
  const state2 = {};
285
302
  const extractedRules = {};
286
303
  Object.entries(schema).forEach(([key, value]) => {
287
304
  if (isSchema(value)) {
288
305
  try {
289
- state2[key] = value.getDefault();
306
+ state2[key] = value.cast(void 0);
290
307
  } catch {
291
308
  state2[key] = void 0;
292
309
  }
@@ -498,9 +515,12 @@ function useForm(schema, { arrayIdentifiers } = DEFAULT_OPTIONS) {
498
515
  });
499
516
  }
500
517
  if (type === "primitiveArray" /* PrimitiveArray */) {
501
- const arr = [...prev[arrayKey]];
502
- arr[index] = finalValue;
503
- return { ...prev, [arrayKey]: arr };
518
+ return handleNestedChange({
519
+ state: prev,
520
+ id: `${arrayKey}.${index}`,
521
+ value: finalValue,
522
+ hasNestedValues: true
523
+ });
504
524
  }
505
525
  if (type === "objectArray" /* ObjectArray */) {
506
526
  return handleArrayItemChange({
@@ -614,21 +634,31 @@ function useForm(schema, { arrayIdentifiers } = DEFAULT_OPTIONS) {
614
634
  () => ({
615
635
  addItem: (arrayKey, item, index) => {
616
636
  setState((prev) => {
617
- const arr = [...prev[arrayKey]];
637
+ const arr = [...getNestedValue(prev, arrayKey) || []];
618
638
  if (index === void 0) arr.push(item);
619
639
  else arr.splice(index, 0, item);
620
- return { ...prev, [arrayKey]: arr };
640
+ return handleNestedChange({
641
+ state: prev,
642
+ id: arrayKey,
643
+ value: arr,
644
+ hasNestedValues: String(arrayKey).includes(".")
645
+ });
621
646
  });
622
647
  },
623
648
  removeItem: (arrayKey, index) => {
624
- const currentArr = stateRef.current[arrayKey];
649
+ const currentArr = getNestedValue(stateRef.current, arrayKey) || [];
625
650
  const item = currentArr[index];
626
651
  const idKey = arrayIdentifiers?.[arrayKey] || "id";
627
652
  const itemId = item?.[idKey];
628
653
  setState((prev) => {
629
- const arr = [...prev[arrayKey]];
654
+ const arr = [...getNestedValue(prev, arrayKey) || []];
630
655
  arr.splice(index, 1);
631
- return { ...prev, [arrayKey]: arr };
656
+ return handleNestedChange({
657
+ state: prev,
658
+ id: arrayKey,
659
+ value: arr,
660
+ hasNestedValues: String(arrayKey).includes(".")
661
+ });
632
662
  });
633
663
  if (itemId !== void 0) {
634
664
  const prefix = `${String(arrayKey)}.${itemId}.`;
@@ -639,9 +669,14 @@ function useForm(schema, { arrayIdentifiers } = DEFAULT_OPTIONS) {
639
669
  const index = getIndex(arrayKey, itemId);
640
670
  if (index !== void 0) {
641
671
  setState((prev) => {
642
- const arr = [...prev[arrayKey]];
672
+ const arr = [...getNestedValue(prev, arrayKey) || []];
643
673
  arr.splice(index, 1);
644
- return { ...prev, [arrayKey]: arr };
674
+ return handleNestedChange({
675
+ state: prev,
676
+ id: arrayKey,
677
+ value: arr,
678
+ hasNestedValues: String(arrayKey).includes(".")
679
+ });
645
680
  });
646
681
  const prefix = `${String(arrayKey)}.${itemId}.`;
647
682
  setMetadata((prev) => removeCompositeKeysByPrefix(prev, prefix));
@@ -649,17 +684,27 @@ function useForm(schema, { arrayIdentifiers } = DEFAULT_OPTIONS) {
649
684
  },
650
685
  updateItem: (arrayKey, index, value) => {
651
686
  setState((prev) => {
652
- const arr = [...prev[arrayKey]];
687
+ const arr = [...getNestedValue(prev, arrayKey) || []];
653
688
  arr[index] = value;
654
- return { ...prev, [arrayKey]: arr };
689
+ return handleNestedChange({
690
+ state: prev,
691
+ id: arrayKey,
692
+ value: arr,
693
+ hasNestedValues: String(arrayKey).includes(".")
694
+ });
655
695
  });
656
696
  },
657
697
  moveItem: (arrayKey, from, to) => {
658
698
  setState((prev) => {
659
- const arr = [...prev[arrayKey]];
699
+ const arr = [...getNestedValue(prev, arrayKey) || []];
660
700
  const [item] = arr.splice(from, 1);
661
701
  arr.splice(to, 0, item);
662
- return { ...prev, [arrayKey]: arr };
702
+ return handleNestedChange({
703
+ state: prev,
704
+ id: arrayKey,
705
+ value: arr,
706
+ hasNestedValues: String(arrayKey).includes(".")
707
+ });
663
708
  });
664
709
  },
665
710
  moveById: (arrayKey, fromId, toId) => {
@@ -667,17 +712,22 @@ function useForm(schema, { arrayIdentifiers } = DEFAULT_OPTIONS) {
667
712
  const toIndex = getIndex(arrayKey, toId);
668
713
  if (fromIndex !== void 0 && toIndex !== void 0) {
669
714
  setState((prev) => {
670
- const arr = [...prev[arrayKey]];
715
+ const arr = [...getNestedValue(prev, arrayKey) || []];
671
716
  const [item] = arr.splice(fromIndex, 1);
672
717
  arr.splice(toIndex, 0, item);
673
- return { ...prev, [arrayKey]: arr };
718
+ return handleNestedChange({
719
+ state: prev,
720
+ id: arrayKey,
721
+ value: arr,
722
+ hasNestedValues: String(arrayKey).includes(".")
723
+ });
674
724
  });
675
725
  }
676
726
  },
677
727
  getItem: (arrayKey, itemId) => {
678
728
  const index = getIndex(arrayKey, itemId);
679
729
  if (index === void 0) return void 0;
680
- return stateRef.current[arrayKey][index];
730
+ return getNestedValue(stateRef.current, arrayKey)[index];
681
731
  }
682
732
  }),
683
733
  [getIndex, arrayIdentifiers]
@@ -720,7 +770,7 @@ function useForm(schema, { arrayIdentifiers } = DEFAULT_OPTIONS) {
720
770
  },
721
771
  [validateField]
722
772
  );
723
- const onSubmit = useCallback(
773
+ const onFormSubmit = useCallback(
724
774
  (fn) => (e) => {
725
775
  e.preventDefault();
726
776
  if (validateAll()) return;
@@ -728,6 +778,48 @@ function useForm(schema, { arrayIdentifiers } = DEFAULT_OPTIONS) {
728
778
  },
729
779
  [validateAll]
730
780
  );
781
+ const onFormSubmitPropRef = useRef(onFormSubmitProp);
782
+ onFormSubmitPropRef.current = onFormSubmitProp;
783
+ const resetOnSubmitRef = useRef(resetOnSubmit);
784
+ resetOnSubmitRef.current = resetOnSubmit;
785
+ const keepValuesPropRef = useRef(keepValuesProp);
786
+ keepValuesPropRef.current = keepValuesProp;
787
+ const handleReset = useCallback(
788
+ (options) => {
789
+ const { keepValues } = options || {};
790
+ if (keepValues && keepValues.length > 0) {
791
+ const nextState = { ...initialState };
792
+ keepValues.forEach((k) => {
793
+ if (stateRef.current[k] !== void 0)
794
+ nextState[k] = stateRef.current[k];
795
+ });
796
+ setState(nextState);
797
+ } else {
798
+ setState(initialState);
799
+ }
800
+ setMetadata(/* @__PURE__ */ new Map());
801
+ },
802
+ [initialState]
803
+ );
804
+ const validateAllRef = useRef(validateAll);
805
+ validateAllRef.current = validateAll;
806
+ const ControlledForm = useMemo(() => {
807
+ return (props) => {
808
+ const { onSubmit, ...rest } = props;
809
+ const handleSubmit = (e) => {
810
+ e.preventDefault();
811
+ if (validateAllRef.current()) {
812
+ return;
813
+ }
814
+ onFormSubmitPropRef.current?.(stateRef.current, e);
815
+ if (resetOnSubmitRef.current) {
816
+ handleReset({ keepValues: keepValuesPropRef.current });
817
+ }
818
+ onSubmit?.(stateRef.current, e);
819
+ };
820
+ return /* @__PURE__ */ jsx(Form, { onSubmit: handleSubmit, ...rest });
821
+ };
822
+ }, []);
731
823
  return useMemo(
732
824
  () => ({
733
825
  state,
@@ -739,37 +831,9 @@ function useForm(schema, { arrayIdentifiers } = DEFAULT_OPTIONS) {
739
831
  onFieldBlur: onBlur,
740
832
  onSelectionChange: polymorphicOnSelectionChange,
741
833
  isDirty: Array.from(metadata.values()).some((m) => m.isTouched),
742
- reset: (options) => {
743
- const { preservedStateKeys, preserveTouched } = options || {};
744
- if (preservedStateKeys && preservedStateKeys.length > 0) {
745
- const nextState = { ...initialState };
746
- preservedStateKeys.forEach((k) => {
747
- if (stateRef.current[k] !== void 0)
748
- nextState[k] = stateRef.current[k];
749
- });
750
- setState(nextState);
751
- } else {
752
- setState(initialState);
753
- }
754
- if (preserveTouched) {
755
- setMetadata((prev) => {
756
- const next = /* @__PURE__ */ new Map();
757
- prev.forEach((v, k) => {
758
- if (v.isTouched) {
759
- next.set(k, {
760
- isTouched: true,
761
- isInvalid: false,
762
- errorMessage: ""
763
- });
764
- }
765
- });
766
- return next;
767
- });
768
- } else {
769
- setMetadata(/* @__PURE__ */ new Map());
770
- }
771
- },
772
- onSubmit
834
+ onFormReset: handleReset,
835
+ onFormSubmit,
836
+ ControlledForm
773
837
  }),
774
838
  [
775
839
  state,
@@ -781,7 +845,8 @@ function useForm(schema, { arrayIdentifiers } = DEFAULT_OPTIONS) {
781
845
  polymorphicOnValueChange,
782
846
  polymorphicOnSelectionChange,
783
847
  validateAll,
784
- onSubmit,
848
+ onFormSubmit,
849
+ ControlledForm,
785
850
  initialState
786
851
  ]
787
852
  );
package/package.json CHANGED
@@ -1,45 +1,45 @@
1
- {
2
- "name": "@juantroconisf/lib",
3
- "version": "8.0.0",
4
- "description": "A form validation library for HeroUI.",
5
- "main": "dist/index.js",
6
- "module": "dist/index.mjs",
7
- "types": "dist/index.d.ts",
8
- "files": [
9
- "dist",
10
- "README.md"
11
- ],
12
- "scripts": {
13
- "test": "vitest run",
14
- "build": "pnpm test && tsup src/index.ts --format cjs,esm --dts",
15
- "lint": "tsc",
16
- "prepublishOnly": "pnpm run build"
17
- },
18
- "author": "Juan T",
19
- "license": "ISC",
20
- "bugs": {
21
- "url": "https://github.com/juandiegotroconis/lib/issues"
22
- },
23
- "typings": "dist/index.d.ts",
24
- "homepage": "https://github.com/juandiegotroconis/lib#readme",
25
- "devDependencies": {
26
- "@heroui/react": "^2.8.5",
27
- "@react-types/shared": "^3.32.1",
28
- "@testing-library/jest-dom": "^6.9.1",
29
- "@testing-library/react": "^16.3.2",
30
- "@types/node": "^24.7.1",
31
- "@types/react": "^19.2.2",
32
- "jsdom": "^28.1.0",
33
- "react": "^19.2.0",
34
- "tsup": "^8.5.0",
35
- "typescript": "^5.9.3",
36
- "vitest": "^4.0.18"
37
- },
38
- "peerDependencies": {
39
- "@heroui/react": ">=2.0.0",
40
- "react": ">=18.0.0"
41
- },
42
- "dependencies": {
43
- "yup": "^1.7.1"
44
- }
45
- }
1
+ {
2
+ "name": "@juantroconisf/lib",
3
+ "version": "9.0.0",
4
+ "description": "A form validation library for HeroUI.",
5
+ "main": "dist/index.js",
6
+ "module": "dist/index.mjs",
7
+ "types": "dist/index.d.ts",
8
+ "files": [
9
+ "dist",
10
+ "README.md"
11
+ ],
12
+ "scripts": {
13
+ "test": "vitest run",
14
+ "build": "pnpm test && tsup src/index.ts --format cjs,esm --dts",
15
+ "lint": "tsc",
16
+ "prepublishOnly": "pnpm run build"
17
+ },
18
+ "author": "Juan T",
19
+ "license": "ISC",
20
+ "bugs": {
21
+ "url": "https://github.com/juandiegotroconis/lib/issues"
22
+ },
23
+ "typings": "dist/index.d.ts",
24
+ "homepage": "https://github.com/juandiegotroconis/lib#readme",
25
+ "devDependencies": {
26
+ "@heroui/react": "^2.8.5",
27
+ "@react-types/shared": "^3.32.1",
28
+ "@testing-library/jest-dom": "^6.9.1",
29
+ "@testing-library/react": "^16.3.2",
30
+ "@types/node": "^24.7.1",
31
+ "@types/react": "^19.2.2",
32
+ "jsdom": "^28.1.0",
33
+ "react": "^19.2.0",
34
+ "tsup": "^8.5.0",
35
+ "typescript": "^5.9.3",
36
+ "vitest": "^4.0.18"
37
+ },
38
+ "peerDependencies": {
39
+ "@heroui/react": ">=2.0.0",
40
+ "react": ">=18.0.0"
41
+ },
42
+ "dependencies": {
43
+ "yup": "^1.7.1"
44
+ }
45
+ }