@juantroconisf/lib 9.1.0 → 9.2.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/README.md CHANGED
@@ -1,8 +1,8 @@
1
1
  # @juantroconisf/lib
2
2
 
3
- A powerful, type-safe form management and validation library optimized for **HeroUI** (formerly NextUI) and **React**.
3
+ A powerful, type-safe form management and validation library tailored for **HeroUI** and **React**.
4
4
 
5
- Designed for complex applications, it provides **O(1) value updates**, stable **ID-based array management**, and deep nesting support, all while fully integrating with **Yup** for schema validation.
5
+ Designed for complex applications, it provides **O(1) value updates**, stable **ID-based array management**, and deep nesting support, all seamlessly integrated with **Yup** schemas.
6
6
 
7
7
  ---
8
8
 
@@ -10,30 +10,31 @@ Designed for complex applications, it provides **O(1) value updates**, stable **
10
10
 
11
11
  - [Features](#features)
12
12
  - [Installation](#installation)
13
+ - [Localization](#localization)
13
14
  - [Quick Start](#quick-start)
14
15
  - [Usage Guide](#usage-guide)
15
16
  - [Scalar Fields](#scalar-fields)
16
17
  - [Nested Objects](#nested-objects)
17
18
  - [Managing Arrays](#managing-arrays)
18
- - [Validation](#validation)
19
- - [Submitting Forms](#submitting-forms)
19
+ - [Form Submission](#form-submission)
20
20
  - [API Reference](#api-reference)
21
21
  - [useForm](#useform)
22
- - [The `on` Object](#the-on-object)
22
+ - [The `on` API](#the-on-api)
23
+ - [ControlledForm](#controlledform)
23
24
  - [Array Helpers](#array-helpers)
24
- - [Metadata & Reset](#metadata--reset)
25
+ - [Form Controls](#form-controls)
25
26
 
26
27
  ---
27
28
 
28
29
  ## Features
29
30
 
30
- - 🎯 **Polymorphic `on` API**: Single consistent interface for `input`, `select`, and `autocomplete`.
31
- - 🧩 **Deep Nesting**: Effortlessly manage complex objects with dot-notation support (e.g., `address.city`).
32
- - 🔢 **ID-Based Arrays**: Stable state management for dynamic lists. Items are tracked by unique identifiers (default: `id`), preventing state loss during reordering or deletions.
33
- - **O(1) Performance**: Internal mapping for array items ensures lightning-fast updates regardless of list size.
34
- - 🛡️ **Total Type Safety**: Best-in-class Intellisense for paths, types, and array identifiers.
35
- - 🎨 **HeroUI Optimized**: Returns props ready to be spread directly onto HeroUI components (`isInvalid`, `errorMessage`, `onFieldBlur`, etc.).
36
- - **Yup Integration**: Built-in support for Yup schemas for validation.
31
+ - 🎯 **Polymorphic `on` API**: A unified interface (`on.input`, `on.select`, `on.autocomplete`) saving lines of boilerplate.
32
+ - 🧱 **ControlledForm Component**: Zero-boilerplate validated submissions leveraging the `@heroui/react` Form component directly.
33
+ - 🧩 **Deep Nesting**: Dot-notation support (e.g., `settings.theme`) out of the box.
34
+ - 🔢 **ID-Based Arrays**: List items are tracked by unique identifiers (default: `id`), ensuring states survive mapping, reordering, and deletions.
35
+ - **O(1) Performance**: Internal mapping for array updates offers incredible speed regardless of data density.
36
+ - 🛡️ **Complete Type Safety**: TypeScript infers all acceptable paths, data structures, and outputs natively.
37
+ - 🌍 **Built-in Localization**: Ships with English and Spanish validation translations via runtime cookies.
37
38
 
38
39
  ---
39
40
 
@@ -45,69 +46,107 @@ pnpm add @juantroconisf/lib yup
45
46
 
46
47
  ---
47
48
 
49
+ ## Localization
50
+
51
+ Validation strings (e.g., minimum length, required fields) are localized automatically. The library checks for a browser cookie named `LOCALE` on initialization.
52
+
53
+ - **Supported Locales**: `en` (English - default) and `es` (Spanish).
54
+ - **How to Set**:
55
+ Set the cookie in your client application:
56
+ ```ts
57
+ document.cookie = "LOCALE=es; path=/; max-age=31536000"; // Sets language to Spanish
58
+ ```
59
+ If no cookie is detected, or the value is unrecognized, the library gracefully falls back to English (`en`).
60
+
61
+ ---
62
+
48
63
  ## Quick Start
49
64
 
50
- Here is a complete example demonstrating scalar fields, object arrays, and validation.
65
+ Throughout this documentation, we will refer to a common, diverse schema. It includes simple scalars, deep objects, and complex arrays.
51
66
 
52
67
  ```tsx
53
68
  import { useForm } from "@juantroconisf/lib";
54
- import { string, number, array, object } from "yup";
55
- import { Input, Button } from "@heroui/react";
69
+ import { string, number, array, object, boolean } from "yup";
70
+ import { Input, Switch, Select, SelectItem, Button } from "@heroui/react";
56
71
 
57
- const MyForm = () => {
58
- const { on, state, helpers, onSubmit } = useForm({
59
- name: string().required("Name is required").default(""),
60
- items: array()
61
- .of(
62
- object().shape({
63
- id: number().required(),
64
- label: string().required("Label is required"),
65
- }),
66
- )
67
- .default([{ id: 1, label: "Initial Item" }]),
68
- });
72
+ // 1. Define your diverse schema structure
73
+ const mySchema = {
74
+ fullName: string().required("Name is required").default(""),
75
+ age: number().min(18).default(18),
76
+ settings: object({
77
+ theme: string().oneOf(["light", "dark"]).default("dark"),
78
+ notifications: boolean().default(true),
79
+ }),
80
+ users: array()
81
+ .of(
82
+ object().shape({
83
+ id: number().required(),
84
+ role: string().required(),
85
+ }),
86
+ )
87
+ .default([{ id: Date.now(), role: "admin" }]),
88
+ };
69
89
 
70
- const handleSubmit = (data) => {
71
- console.log("Submitted:", data);
90
+ const MyForm = () => {
91
+ // 2. Initialize the hook with fully inferred types
92
+ const { on, state, helpers, ControlledForm } = useForm(mySchema);
93
+
94
+ // 3. Types are perfectly inferred from your Yup schema
95
+ const handleSubmit = (data, event) => {
96
+ console.log("Submitted payload:", data);
97
+ // data.fullName -> string
98
+ // data.settings.theme -> "light" | "dark"
99
+ // data.users[0].role -> string
72
100
  };
73
101
 
74
102
  return (
75
- <form onSubmit={onSubmit(handleSubmit)} className='flex flex-col gap-4'>
76
- {/* 1. Scalar Registration */}
77
- <Input {...on.input("name")} label='Name' />
78
-
79
- {/* 2. Array Registration */}
80
- {state.items.map((item) => (
81
- <div key={item.id} className='flex gap-2 items-center'>
82
-
83
- {/*
84
- Bind by Path + ID
85
- This ensures that even if the array order changes,
86
- the input remains bound to the correct item.
87
- */}
88
- <Input
89
- {...on.input("items.label", item.id)}
90
- label='Item Label'
91
- />
92
-
93
- <Button
94
- color="danger"
95
- onClick={() => helpers.removeById("items", item.id)}
96
- >
97
- Remove
98
- </Button>
99
- </div>
100
- ))}
101
-
102
- <div className="flex gap-2">
103
+ <ControlledForm onSubmit={handleSubmit} className='flex flex-col gap-4'>
104
+ {/* Scalar Fields */}
105
+ <Input {...on.input("fullName")} label='Full Name' />
106
+ <Input {...on.input("age")} type='number' label='Age' />
107
+
108
+ {/* Nested Object Fields */}
109
+ <Switch {...on.input("settings.notifications")}>
110
+ Enable Notifications
111
+ </Switch>
112
+ <Select {...on.select("settings.theme")} label='Theme'>
113
+ <SelectItem key='light'>Light</SelectItem>
114
+ <SelectItem key='dark'>Dark</SelectItem>
115
+ </Select>
116
+
117
+ {/* Array Fields */}
118
+ <div className='flex flex-col gap-2'>
119
+ <h3>Users</h3>
120
+ {state.users.map((user) => (
121
+ <div key={user.id} className='flex gap-2 items-center'>
122
+ {/* Bind by Array Path + Item ID */}
123
+ <Select {...on.select("users.role", user.id)} label='Role'>
124
+ <SelectItem key='admin'>Admin</SelectItem>
125
+ <SelectItem key='guest'>Guest</SelectItem>
126
+ </Select>
127
+ <Button
128
+ color='danger'
129
+ onPress={() => helpers.removeById("users", user.id)}
130
+ >
131
+ Remove
132
+ </Button>
133
+ </div>
134
+ ))}
135
+ </div>
136
+
137
+ <div className='flex gap-2'>
103
138
  <Button
104
- onClick={() => helpers.addItem("items", { id: Date.now(), label: "" })}
139
+ onPress={() =>
140
+ helpers.addItem("users", { id: Date.now(), role: "guest" })
141
+ }
105
142
  >
106
- Add Item
143
+ Add User
144
+ </Button>
145
+ <Button type='submit' color='primary'>
146
+ Submit
107
147
  </Button>
108
- <Button type='submit' color="primary">Submit</Button>
109
148
  </div>
110
- </form>
149
+ </ControlledForm>
111
150
  );
112
151
  };
113
152
  ```
@@ -116,86 +155,122 @@ const MyForm = () => {
116
155
 
117
156
  ## Usage Guide
118
157
 
158
+ All examples below continue referencing the `mySchema` definition from the Quick Start.
159
+
119
160
  ### Scalar Fields
120
161
 
121
- Scalar fields are the bread and butter of any form. Use `on.input`, `on.select`, or `on.autocomplete` to bind them.
162
+ Scalar fields map directly to your schema definitions. Use `on.input`, `on.select`, or `on.autocomplete` to yield binding props instantly compatible with HeroUI.
122
163
 
123
164
  ```tsx
124
165
  <Input {...on.input("fullName")} label="Full Name" />
125
- <Input {...on.input("email")} type="email" label="Email" />
166
+ <Input {...on.input("age")} type="number" label="Age" />
126
167
  ```
127
168
 
128
169
  ### Nested Objects
129
170
 
130
- No special configuration needed. Just use standard dot notation.
171
+ Nested state is managed intuitively via dot-notation directly on your identifiers. Your TypeScript types will validate that the path points to real endpoints on your data shape.
131
172
 
132
173
  ```tsx
133
- const { on } = useForm({
134
- settings: object({
135
- theme: object({
136
- mode: string().default("dark"),
137
- }),
138
- }),
139
- });
140
-
141
- <Input {...on.input("settings.theme.mode")} />
174
+ // Binds seamlessly to state.settings.theme
175
+ <Select {...on.select("settings.theme")} label="Theme">
176
+ <SelectItem key="light">Light</SelectItem>
177
+ <SelectItem key="dark">Dark</SelectItem>
178
+ </Select>
179
+
180
+ // Booleans map smoothly to Switches/Checkboxes
181
+ <Switch {...on.input("settings.notifications")}>Enable Alerts</Switch>
142
182
  ```
143
183
 
144
184
  ### Managing Arrays
145
185
 
146
- The library shines with arrays. It tracks items by ID, so you can reorder or delete items without losing focus or state.
186
+ Array management is uniquely built around tracking entries by ID (`'id'` field by default). This stops issues where UI inputs lose state references if the array gets shifted.
147
187
 
148
- **1. Binding Inputs:**
188
+ **Binding UI to Items:**
189
+ Combine the general array path and the item ID.
149
190
 
150
- Always bind using the composite syntax: `path.field` + `itemId`.
191
+ ```tsx
192
+ // ✅ Correct: Binds perfectly regardless of list index changes
193
+ on.select("users.role", userId);
194
+
195
+ // ❌ Warning (Unless primitives array): Prevents index-shifting stability
196
+ on.select("users", 0);
197
+ ```
198
+
199
+ **Using the `helpers` Library:**
200
+ Extract `helpers` out of `useForm(...)` to manipulate array state securely.
151
201
 
152
202
  ```tsx
153
- // Correct: Binds to the item with ID 123
154
- on.input("users.name", 123)
203
+ const { helpers } = useForm(mySchema);
204
+
205
+ // Add an item (Optionally provide index as a 3rd argument to insert)
206
+ helpers.addItem("users", { id: Date.now(), role: "guest" });
207
+
208
+ // Remove item by ID
209
+ helpers.removeById("users", 12345);
155
210
 
156
- // Avoid (unless primitive array): Binds to index 0
157
- on.input("users", 0)
211
+ // Reorder items by ID
212
+ helpers.moveById("users", fromId, toId);
158
213
  ```
159
214
 
160
- **2. Manipulating the Array:**
215
+ ### Form Submission
161
216
 
162
- Use the `helpers` object.
217
+ There are two primary ways to submit, validate, and handle your logic, both fully type-safe.
163
218
 
164
- ```tsx
165
- // Add
166
- helpers.addItem("users", { id: "new-id", name: "" });
219
+ **1. The `ControlledForm` Wrapper (Recommended)**
167
220
 
168
- // Remove by ID (Safe)
169
- helpers.removeById("users", "user-id-123");
221
+ `ControlledForm` behaves exactly like a HeroUI `Form` component. It automatically intercepts submit events, validates all bindings through your schema, and invokes `onSubmit` with the validated dataset.
170
222
 
171
- // Move (Reorder)
172
- helpers.moveById("users", "from-id", "to-id");
223
+ ```tsx
224
+ const { ControlledForm } = useForm(mySchema);
225
+
226
+ return (
227
+ <ControlledForm onSubmit={(data, event) => console.log(data.fullName)}>
228
+ <Input {...on.input("fullName")} />
229
+ <Button type='submit'>Submit</Button>
230
+ </ControlledForm>
231
+ );
173
232
  ```
174
233
 
175
- ### Validation
234
+ **2. The `onFormSubmit` Handler Wrapper**
176
235
 
177
- Validation is "Schema-First" via Yup.
236
+ If you prefer using native HTML `<form>` tags, you can pass your callback into `onFormSubmit`. The params exposed to your callback are tightly inferred from the schema.
237
+
238
+ ```tsx
239
+ const { onFormSubmit, state } = useForm(mySchema);
178
240
 
179
- 1. **Define Rules**: Pass a Yup schema to `useForm`.
180
- 2. **Auto-Validation**:
181
- - Fields validate on `blur`.
182
- - If a field is `touched` and `invalid`, it re-validates on every keystroke (`onChange`).
183
- 3. **Submit Validation**: Use `onSubmit` wrapper to validate all fields before executing your handler.
241
+ // Automatically infers your final structured data (data) and the React form event (e)
242
+ const submitHandler = onFormSubmit((data, e) => {
243
+ // Validation passed successfully!
244
+ // 'data.settings.theme' is correctly typed as string.
245
+ api.post("/endpoint", data);
246
+ });
247
+
248
+ // Used manually on form tags or button invocations
249
+ <form onSubmit={submitHandler}>{/* inputs */}</form>;
250
+ ```
184
251
 
185
- ### Submitting Forms
252
+ **3. External Handler Definitions**
186
253
 
187
- The `onSubmit` wrapper handles `preventDefault`, runs full validation, and only executes your callback if valid.
254
+ If you define your schemas inline inside `useForm( { ... } )` but want to extract your `submit` handler natively without destructing variables you aren't using:
188
255
 
189
256
  ```tsx
190
- const { onSubmit } = useForm(...);
257
+ export const MyForm = () => {
258
+ // 1. Schema is defined organically inline inside the component execution
259
+ const { ControlledForm } = useForm({
260
+ fullName: string().required(),
261
+ });
191
262
 
192
- const handleSubmit = (data) => {
193
- // 1. Validation has already passed!
194
- // 2. Proceed with submission
195
- api.post("/users", data);
196
- };
263
+ // 2. Type your extract handler capturing React.ComponentProps directly on the wrapper
264
+ const handleSubmit: React.ComponentProps<
265
+ typeof ControlledForm
266
+ >["onSubmit"] = (data, event) => {
267
+ // Both data.fullName and React Events are perfectly inferred natively!
268
+ console.log(data.fullName);
269
+ };
197
270
 
198
- return <form onSubmit={onSubmit(handleSubmit)}>...</form>;
271
+ // 3. Destructure whatever you need right on your JSX render
272
+ return <ControlledForm onSubmit={handleSubmit}>...</ControlledForm>;
273
+ };
199
274
  ```
200
275
 
201
276
  ---
@@ -204,76 +279,81 @@ return <form onSubmit={onSubmit(handleSubmit)}>...</form>;
204
279
 
205
280
  ### `useForm`
206
281
 
282
+ Instantiates state and schema configurations.
283
+
207
284
  ```ts
208
- const {
209
- state,
210
- on,
211
- helpers,
212
- metadata,
213
- reset,
214
- onSubmit,
215
- reset,
216
- onSubmit,
217
- isDirty,
218
- onFieldChange,
219
- onFieldBlur
220
- } = useForm(schema, options?);
285
+ const formApi = useForm(schema, options?);
221
286
  ```
222
287
 
223
288
  #### Arguments
224
289
 
225
- | Argument | Type | Description |
226
- | :--- | :--- | :--- |
227
- | **`schema`** | `Yup.Schema` | A Yup schema object defining structure, default values, and validation rules. |
228
- | **`options`** | `FormOptions` | Configuration object. |
290
+ | Parameter | Type | Description |
291
+ | :------------ | :--------------------------- | :------------------------------------------------------------------------------- |
292
+ | **`schema`** | `Record<string, ConfigType>` | Your form shape configuration containing `Yup` schemas or primitive constraints. |
293
+ | **`options`** | `FormOptions` | Configuration behaviors. |
229
294
 
230
295
  #### Options
231
296
 
232
- - **`arrayIdentifiers`**: Mapping of array paths to their unique ID property (default: `"id"`).
297
+ | Option | Type | Description |
298
+ | :--------------------- | :--------- | :------------------------------------------------------------------------------ |
299
+ | **`arrayIdentifiers`** | `Object` | Identifier maps for objects missing `id` (e.g. `{ users: "uuid" }`). |
300
+ | **`resetOnSubmit`** | `boolean` | Instantly resets all values tracking arrays to initialization configurations. |
301
+ | **`onFormSubmit`** | `Function` | Fallback default submission pipeline. |
302
+ | **`keepValues`** | `string[]` | Keys in the root state to preserve during a reset (e.g. `["settings", "age"]`). |
233
303
 
234
- ### The `on` Object
304
+ ---
235
305
 
236
- The `on` object generates props for your components: `value`, `onValueChange`, `isInvalid`, `errorMessage`, `onBlur`.
306
+ ### The `on` API
237
307
 
238
- | Method | Signature | Description |
239
- | :--- | :--- | :--- |
240
- | **`on.input`** | `(path, [id])` | Generic input handler. Returns standard input props. |
241
- | **`on.select`** | `(path, [id])` | Returns props compatible with `Select` (handles `selectedKeys`). |
242
- | **`on.autocomplete`** | `(path, [id])` | Returns props compatible with `Autocomplete` (handles `selectedKey`). |
308
+ `on` hooks dynamically assign value tracks, validity checks, error text extractions, and update invocations back to the controller.
243
309
 
244
- ### Array Helpers
310
+ | Method | Description |
311
+ | :-------------------------------- | :--------------------------------------------------------------------------- |
312
+ | **`on.input(path, [itemId])`** | Exports `{ id, isInvalid, errorMessage, value, onValueChange, onBlur }`. |
313
+ | **`on.select(path, [itemId])`** | Exports properties mapped for `<Select>` components matching `selectedKeys`. |
314
+ | **`on.autocomplete(path, [id])`** | Exports properties mapped for `<Autocomplete>` matching `selectedKey`. |
245
315
 
246
- Utilities for manipulating array state.
316
+ ---
247
317
 
248
- | Method | Description |
249
- | :--- | :--- |
250
- | **`addItem(key, item, index?)`** | Adds an item to the array. |
251
- | **`removeItem(key, index)`** | Removes an item at a specific index. |
252
- | **`removeById(key, id)`** | **Recommended**. Removes an item by its unique ID. |
253
- | **`updateItem(key, index, val)`** | Replaces an item at a specific index. |
254
- | **`moveItem(key, from, to)`** | Moves an item from one index to another. |
255
- | **`moveById(key, fromId, toId)`** | Moves an item by ID. |
256
- | **`getItem(key, id)`** | Retrieval helper. |
318
+ ### ControlledForm
257
319
 
258
- ### Metadata & Reset
320
+ A Drop-in `<Form />` equivalent handling submit event delegation natively linked to validation triggers internally.
259
321
 
260
- | Property | Type | Description |
261
- | :--- | :--- | :--- |
262
- | **`metadata`** | `Map<string, FieldMetadata>` | Contains validation state (`isInvalid`, `errorMessage`) and `isTouched`. |
263
- | **`reset`** | `(options?) => void` | Resets form state and metadata to initial values. |
322
+ | Prop | Type | Description |
323
+ | :------------- | :------------------ | :----------------------------------------------------------------------------------------------------------------------------------------------------------------- |
324
+ | **`onSubmit`** | `(data, e) => void` | Invoked strictly post-validation of `schema` variables passing criteria. Both arguments `data` (your state payload) and `e` (the React event) are correctly typed. |
264
325
 
265
- **Reset Options:**
326
+ _Notes: Spreads any traditional `<form>` properties to standard HeroUI mappings out of the box._
266
327
 
267
- ```ts
268
- // Reset everything
269
- reset();
328
+ ---
270
329
 
271
- // Keep specific fields
272
- reset({ keys: ["organizationId"] });
330
+ ### Array Helpers
273
331
 
274
- // Only clear touched status (keep values)
275
- reset({ onlyTouched: true });
276
- ```
332
+ Array adjustments exported off the `helpers` map:
333
+
334
+ | Utility | Description |
335
+ | :--------------------------------- | :---------------------------------------------------------------------------- |
336
+ | **`addItem(path, item, index?)`** | Submits entries safely. |
337
+ | **`removeItem(path, index)`** | Excludes entry mapped at index map offset. |
338
+ | **`removeById(path, id)`** | Standard and secure ID withdrawal. |
339
+ | **`updateItem(path, index, val)`** | Hot swap content without re-render destruction. |
340
+ | **`moveItem(path, current, to)`** | Re-order index slots. |
341
+ | **`moveById(path, fromId, toId)`** | Shift lists seamlessly referencing fixed ID targets. |
342
+ | **`getItem(path, id)`** | Read items immediately via O(1) indexed lookups without array mapping cycles. |
343
+
344
+ ---
345
+
346
+ ### Form Controls
347
+
348
+ Additional utilities available directly out of `useForm`:
349
+
350
+ | Method | Signatures / Types | Info |
351
+ | :---------------- | :---------------------------------- | :------------------------------------------------------------------ |
352
+ | **`state`** | `InferState<S>` | Evaluated state values matching object signatures defined. |
353
+ | **`setState`** | `Dispatch<SetStateAction>` | The fundamental state mutation. |
354
+ | **`onFormReset`** | `(opts?: { keepValues: string[] })` | Discards invalidity layers and remounts variables back to defaults. |
355
+ | **`isDirty`** | `boolean` | Truthy flag reflecting if state parameters altered. |
356
+ | **`metadata`** | `Map<string, FieldMetadata>` | Touched and Error metadata instances tracked. |
277
357
 
278
358
  ---
279
359
 
package/dist/index.d.mts CHANGED
@@ -61,6 +61,11 @@ type FieldMetadata = {
61
61
  };
62
62
  type MetadataType = Map<string, FieldMetadata>;
63
63
  type FormSubmitHandler<O extends StateType> = (data: O, e: React.FormEvent) => void;
64
+ /**
65
+ * A utility type for inferring the submit handler's signature directly from a Yup schema object.
66
+ * This saves developers from manually mapping `InferType` back to `FormSubmitHandler` when extracting sumbits.
67
+ */
68
+ type InferSubmitHandler<S extends Record<string, ConfigType>> = (data: InferState<S>, e: React.FormEvent) => void;
64
69
  interface FormResetOptions<O> {
65
70
  keepValues?: (keyof O)[];
66
71
  }
@@ -205,4 +210,4 @@ interface UseFormResponse<O extends StateType> {
205
210
 
206
211
  declare function useForm<S extends Record<string, ConfigType>>(schema: S, { arrayIdentifiers, onFormSubmit: onFormSubmitProp, resetOnSubmit, keepValues: keepValuesProp, }?: FormOptions<InferState<S>>): UseFormResponse<InferState<S>>;
207
212
 
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 };
213
+ export { type BlurFunc, type ConfigType, type FieldMetadata, type FormOptions, type FormSubmitHandler, type HelpersFunc, type InferState, type InferSubmitHandler, type MetadataType, type NestedChangeProps, NextUIError, type OnMethods, type StateType, type UseFormResponse, type ValueChangeFunc, useForm };
package/dist/index.d.ts CHANGED
@@ -61,6 +61,11 @@ type FieldMetadata = {
61
61
  };
62
62
  type MetadataType = Map<string, FieldMetadata>;
63
63
  type FormSubmitHandler<O extends StateType> = (data: O, e: React.FormEvent) => void;
64
+ /**
65
+ * A utility type for inferring the submit handler's signature directly from a Yup schema object.
66
+ * This saves developers from manually mapping `InferType` back to `FormSubmitHandler` when extracting sumbits.
67
+ */
68
+ type InferSubmitHandler<S extends Record<string, ConfigType>> = (data: InferState<S>, e: React.FormEvent) => void;
64
69
  interface FormResetOptions<O> {
65
70
  keepValues?: (keyof O)[];
66
71
  }
@@ -205,4 +210,4 @@ interface UseFormResponse<O extends StateType> {
205
210
 
206
211
  declare function useForm<S extends Record<string, ConfigType>>(schema: S, { arrayIdentifiers, onFormSubmit: onFormSubmitProp, resetOnSubmit, keepValues: keepValuesProp, }?: FormOptions<InferState<S>>): UseFormResponse<InferState<S>>;
207
212
 
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 };
213
+ export { type BlurFunc, type ConfigType, type FieldMetadata, type FormOptions, type FormSubmitHandler, type HelpersFunc, type InferState, type InferSubmitHandler, type MetadataType, type NestedChangeProps, NextUIError, type OnMethods, type StateType, type UseFormResponse, type ValueChangeFunc, useForm };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@juantroconisf/lib",
3
- "version": "9.1.0",
3
+ "version": "9.2.0",
4
4
  "description": "A form validation library for HeroUI.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",