@juantroconisf/lib 10.0.0 → 11.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/README.md CHANGED
@@ -192,12 +192,12 @@ All methods support both **scalar/nested** paths and **array item** paths (compo
192
192
 
193
193
  For updating state outside of a component (e.g. in an event handler, after an API call), use the manual functions returned by `useForm`.
194
194
 
195
- | Function | Use for | Signature |
196
- | ------------------------ | ------------------------------- | -------------------------------- |
197
- | `onFieldChange` | Scalar / nested object field | `(id, value)` |
198
- | `onArrayItemChange` | Object array item field | `("array.field", itemId, value)` |
199
- | `onSelectionChange` | Scalar / nested selection field | `(id, value)` |
200
- | `onArraySelectionChange` | Array item selection field | `("array.field", itemId, value)` |
195
+ | Function | Use for | Signature |
196
+ | ------------------------ | ------------------------------- | --------------------- |
197
+ | `onFieldChange` | Scalar / nested object field | `(id, value)` |
198
+ | `onArrayItemChange` | Object array item field | `({ at, id, value })` |
199
+ | `onSelectionChange` | Scalar / nested selection field | `(id, value)` |
200
+ | `onArraySelectionChange` | Array item selection field | `({ at, id, value })` |
201
201
 
202
202
  ```ts
203
203
  const { onFieldChange, onArrayItemChange, onSelectionChange } = useForm(schema);
@@ -206,13 +206,13 @@ const { onFieldChange, onArrayItemChange, onSelectionChange } = useForm(schema);
206
206
  onFieldChange("email", "user@example.com");
207
207
 
208
208
  // Update a field inside an array item
209
- onArrayItemChange("users.name", userId, "Alice");
209
+ onArrayItemChange({ at: "users.name", id: userId, value: "Alice" });
210
210
 
211
- // Update a selection field
212
- onSelectionChange("theme", "dark");
211
+ // Update a selection field inside an array item
212
+ onArraySelectionChange({ at: "users.role", id: userId, value: "admin" });
213
213
  ```
214
214
 
215
- > **Note:** `onFieldChange` only handles scalar and nested object paths. Use `onArrayItemChange` for array items they each have a unique signature so TypeScript will guide you.
215
+ > **`at`** is the composite dot-notation path (`"array.field"`), **`id`** is the item's unique identifier, **`value`** is the new value to set. These are direct setters call them imperatively, not as event listeners.
216
216
 
217
217
  ---
218
218
 
@@ -220,16 +220,16 @@ onSelectionChange("theme", "dark");
220
220
 
221
221
  Extracted from `helpers` on the `useForm` return value. Items in object arrays are tracked by ID (default field: `id`).
222
222
 
223
- | Method | Description |
224
- | ------------------------------------ | -------------------------------------------------- |
225
- | `addItem(path, item, index?)` | Adds an item to the end (or at `index`) |
226
- | `removeItem(path, index)` | Removes by index |
227
- | `removeById(path, id)` | Removes by item ID |
228
- | `updateItem(path, index, partial)` | Partially updates an item by index (shallow merge) |
229
- | `updateById(path, id, partial)` | Partially updates an item by ID (shallow merge) |
230
- | `moveItem(path, fromIndex, toIndex)` | Reorders by index |
231
- | `moveById(path, fromId, toId)` | Reorders by ID |
232
- | `getItem(path, id)` | O(1) lookup by ID |
223
+ | Method | Description |
224
+ | ------------------------------------------- | -------------------------------------------------- |
225
+ | `addItem(path, item, index?)` | Adds an item to the end (or at `index`) |
226
+ | `removeItemByIndexByIndex(path, index)` | Removes by index |
227
+ | `removeById(path, id)` | Removes by item ID |
228
+ | `updateByIndex(path, index, partial)` | Partially updates an item by index (shallow merge) |
229
+ | `updateById(path, id, partial)` | Partially updates an item by ID (shallow merge) |
230
+ | `moveItemByIndex(path, fromIndex, toIndex)` | Reorders by index |
231
+ | `moveById(path, fromId, toId)` | Reorders by ID |
232
+ | `getItemById(path, id)` | O(1) lookup by ID |
233
233
 
234
234
  ```ts
235
235
  const { helpers } = useForm(schema);
@@ -242,19 +242,65 @@ helpers.moveById("users", 123, 456); // moves item 123 to where item 456 is
242
242
 
243
243
  ### Custom Array Identifier
244
244
 
245
- If your array items don't use an `id` field, specify the key via `arrayIdentifiers`:
245
+ By default, the library tracks array items by their `id` field. If your items use a different field (e.g. `uuid`, `slug`, `code`), configure it via `arrayIdentifiers` in the options.
246
246
 
247
247
  ```ts
248
- const { helpers } = useForm(
248
+ const { on, helpers, onArrayItemChange } = useForm(
249
249
  {
250
250
  employees: array()
251
- .of(object({ uuid: string(), name: string() }))
251
+ .of(
252
+ object({
253
+ uuid: string().required(),
254
+ name: string().required(),
255
+ role: string().required(),
256
+ }),
257
+ )
252
258
  .default([]),
253
259
  },
254
- { arrayIdentifiers: { employees: "uuid" } },
260
+ {
261
+ arrayIdentifiers: {
262
+ employees: "uuid", // tells the library to use `uuid` instead of `id`
263
+ },
264
+ },
255
265
  );
266
+ ```
267
+
268
+ **Every ID-based function picks this up automatically:**
269
+
270
+ ```ts
271
+ // on.* bindings — the second arg is the item identifier
272
+ <Input {...on.input("employees.name", employee.uuid)} label="Name" />
273
+ <Select {...on.select("employees.role", employee.uuid)} label="Role">...</Select>
274
+
275
+ // Manual setters — `id` is the item identifier
276
+ onArrayItemChange({ at: "employees.name", id: employee.uuid, value: "Alice" });
277
+ onArraySelectionChange({ at: "employees.role", id: employee.uuid, value: "admin" });
278
+
279
+ // Helpers — all `*ById` methods use the configured identifier
280
+ helpers.removeById("employees", employee.uuid);
281
+ helpers.updateById("employees", employee.uuid, { name: "Alice" }); // partial update
282
+ helpers.moveById("employees", fromUuid, toUuid);
283
+ helpers.getItemById("employees", employee.uuid);
284
+ ```
256
285
 
257
- helpers.removeById("employees", "some-uuid-string");
286
+ > The identifier field you configure must be a **scalar** (string or number) present in every item. The library uses it to build an internal O(1) index map, which is why array operations are fast regardless of list size.
287
+
288
+ **Type inference:** `arrayIdentifiers` is typed so only valid scalar keys of each array element are accepted:
289
+
290
+ ```ts
291
+ // ✅ uuid is a string field on each employee
292
+ {
293
+ arrayIdentifiers: {
294
+ employees: "uuid";
295
+ }
296
+ }
297
+
298
+ // ❌ TypeScript error — name is not a valid identifier (may not be unique)
299
+ {
300
+ arrayIdentifiers: {
301
+ employees: "name";
302
+ }
303
+ } // error if "name" is not in type
258
304
  ```
259
305
 
260
306
  ---
package/dist/index.d.mts CHANGED
@@ -92,7 +92,7 @@ interface ItemNumberInputProps extends ComponentInputProps {
92
92
  /** Props returned by on.select() */
93
93
  interface ItemSelectProps extends ComponentInputProps {
94
94
  onSelectionChange: NonNullable<SelectProps["onSelectionChange"]>;
95
- selectedKeys: string[] | number[] | string | null;
95
+ selectedKeys: NonNullable<SelectProps["selectedKeys"]>;
96
96
  }
97
97
  /** Props returned by on.autocomplete() */
98
98
  interface ItemAutocompleteProps extends ComponentInputProps {
@@ -164,16 +164,30 @@ type ObjectArrayFieldPaths<O extends StateType> = {
164
164
  [K in keyof O]: O[K] extends Record<string, any>[] ? `${K & string}.${FieldPaths<ArrayElement<O[K]>>}` : never;
165
165
  }[keyof O];
166
166
  type ArrayElement<T> = T extends (infer E)[] ? E : never;
167
+ /** Resolves the type of the identifier field for an array element (defaults to "id"). */
168
+ type ItemIdType<O extends StateType, K extends keyof O> = "id" extends keyof ArrayElement<O[K]> ? ArrayElement<O[K]>["id"] : string | number;
169
+ /** Extracts the array key from a composite path e.g. "relatives.age" → "relatives". */
170
+ type ExtractArrayKey<P extends string> = P extends `${infer K}.${string}` ? K : never;
171
+ /**
172
+ * Resolves the identifier field type for the array referenced by a composite path.
173
+ * e.g. if relatives[].id is string, then ArrayItemIdTypeFromPath<O, "relatives.age"> = string
174
+ */
175
+ type ArrayItemIdTypeFromPath<O extends StateType, P extends string> = ExtractArrayKey<P> extends keyof O ? ItemIdType<O, ExtractArrayKey<P>> : string | number;
176
+ /**
177
+ * Resolves the value type for the field referenced by a composite path.
178
+ * e.g. "relatives.age" → number (the type of the `age` field in each relative item)
179
+ */
180
+ type CompositeFieldValue<O extends StateType, P extends string> = P extends `${infer K}.${infer F}` ? K extends keyof O ? O[K] extends (infer E)[] ? F extends keyof E ? NonNullable<E[F]> : any : any : any : any;
167
181
  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;
168
182
  type FieldPaths<T> = T extends Record<string, any> ? {
169
183
  [K in keyof T & string]: T[K] extends any[] ? K : T[K] extends Record<string, any> ? `${K}.${FieldPaths<T[K]>}` : K;
170
184
  }[keyof T & string] : never;
171
185
  type NestedObjectPaths<O extends StateType> = {
172
- [K in keyof O & string]: O[K] extends any[] ? never : O[K] extends Record<string, any> ? `${K}.${FieldPaths<O[K]>}` : never;
186
+ [K in keyof O & string]: NonNullable<O[K]> extends any[] ? never : NonNullable<O[K]> extends Date ? never : NonNullable<O[K]> extends Record<string, any> ? `${K}.${FieldPaths<NonNullable<O[K]>>}` : never;
173
187
  }[keyof O & string];
174
- /** Keys whose values are not arrays and not plain objects (i.e. scalar/primitive fields). */
188
+ /** Keys whose values are not arrays and not plain objects (i.e. scalar/primitive fields). Date is treated as a scalar. */
175
189
  type ScalarKeys<O extends StateType> = {
176
- [K in keyof O]: O[K] extends any[] ? never : O[K] extends Record<string, any> ? never : K;
190
+ [K in keyof O]: NonNullable<O[K]> extends any[] ? never : NonNullable<O[K]> extends Date ? K : NonNullable<O[K]> extends Record<string, any> ? never : K;
177
191
  }[keyof O];
178
192
  type AllPaths<O extends StateType> = ScalarKeys<O> | NestedObjectPaths<O>;
179
193
  /**
@@ -183,19 +197,19 @@ interface HelpersFunc<O extends StateType> {
183
197
  /** Adds a new item to an array. */
184
198
  addItem: <K extends ArrayPaths<O>>(arrayKey: K, item: NestedFieldValue<O, K> extends (infer E)[] ? E : never, index?: number) => void;
185
199
  /** Removes an item from an array by its index. */
186
- removeItem: <K extends ArrayPaths<O>>(arrayKey: K, index: number) => void;
200
+ removeItemByIndexByIndex: <K extends ArrayPaths<O>>(arrayKey: K, index: number) => void;
187
201
  /** Removes an item from an array by its unique identifier. */
188
202
  removeById: <K extends ArrayPaths<O>>(arrayKey: K, itemId: string | number) => void;
189
203
  /** Updates an item in an array at the given index (supports partial updates). */
190
- updateItem: <K extends ArrayPaths<O>>(arrayKey: K, index: number, value: NestedFieldValue<O, K> extends (infer E)[] ? Partial<E> : never) => void;
204
+ updateByIndex: <K extends ArrayPaths<O>>(arrayKey: K, index: number, value: NestedFieldValue<O, K> extends (infer E)[] ? Partial<E> : never) => void;
191
205
  /** Updates an item in an array by its unique identifier (supports partial updates). */
192
206
  updateById: <K extends ArrayPaths<O>>(arrayKey: K, itemId: string | number, value: NestedFieldValue<O, K> extends (infer E)[] ? Partial<E> : never) => void;
193
207
  /** Moves an item within an array using indices. */
194
- moveItem: <K extends ArrayPaths<O>>(arrayKey: K, from: number, to: number) => void;
208
+ moveItemByIndex: <K extends ArrayPaths<O>>(arrayKey: K, from: number, to: number) => void;
195
209
  /** Moves an item within an array using unique identifiers. */
196
210
  moveById: <K extends ArrayPaths<O>>(arrayKey: K, fromId: string | number, toId: string | number) => void;
197
211
  /** Gets an item from an array by its unique identifier (O(1) via indexMap). */
198
- getItem: <K extends ArrayPaths<O>>(arrayKey: K, itemId: string | number) => (NestedFieldValue<O, K> extends (infer E)[] ? E : never) | undefined;
212
+ getItemById: <K extends ArrayPaths<O>>(arrayKey: K, itemId: string | number) => (NestedFieldValue<O, K> extends (infer E)[] ? E : never) | undefined;
199
213
  }
200
214
  /**
201
215
  * The response object from the useForm hook.
@@ -205,12 +219,26 @@ interface UseFormResponse<O extends StateType> {
205
219
  onFieldBlur: BlurFunc<O>;
206
220
  /** Updates a scalar or nested object field. */
207
221
  onFieldChange<P extends AllPaths<O>>(id: P, value: NestedFieldValue<O, P & string>): void;
208
- /** Manually updates a field within an object array item using "array.field" composite path. */
209
- onArrayItemChange<P extends ObjectArrayFieldPaths<O>>(compositePath: P, itemId: string | number, value: any): void;
222
+ /** Manually updates a field within an object array item. */
223
+ onArrayItemChange<P extends ObjectArrayFieldPaths<O>>(options: {
224
+ /** Composite dot-notation path: e.g. "users.name" */
225
+ at: P;
226
+ /** The unique identifier of the target array item — type is inferred from the array element's id field. */
227
+ id: ArrayItemIdTypeFromPath<O, P & string>;
228
+ /** The new value — type is inferred from the field referenced by `at`. */
229
+ value: CompositeFieldValue<O, P & string>;
230
+ }): void;
210
231
  /** Manually updates a scalar or nested object selection field. */
211
232
  onSelectionChange: ValueChangeFunc<O, keyof O>;
212
233
  /** Manually updates a selection-based field within an object array item. */
213
- onArraySelectionChange<P extends ObjectArrayFieldPaths<O>>(compositePath: P, itemId: string | number, value: any): void;
234
+ onArraySelectionChange<P extends ObjectArrayFieldPaths<O>>(options: {
235
+ /** Composite dot-notation path: e.g. "users.role" */
236
+ at: P;
237
+ /** The unique identifier of the target array item — type is inferred from the array element's id field. */
238
+ id: ArrayItemIdTypeFromPath<O, P & string>;
239
+ /** The new selection value — type is inferred from the field referenced by `at`. */
240
+ value: CompositeFieldValue<O, P & string>;
241
+ }): void;
214
242
  state: O;
215
243
  setState: React.Dispatch<React.SetStateAction<O>>;
216
244
  metadata: MetadataType;
@@ -240,4 +268,4 @@ interface UseFormResponse<O extends StateType> {
240
268
 
241
269
  declare function useForm<S extends Record<string, ConfigType>>(schema: S, { arrayIdentifiers, onFormSubmit: onFormSubmitProp, resetOnSubmit, keepValues: keepValuesProp, }?: FormOptions<InferState<S>>): UseFormResponse<InferState<S>>;
242
270
 
243
- 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 };
271
+ export { type BlurFunc, type ComponentInputProps, type ConfigType, type FieldMetadata, type FormOptions, type FormResetOptions, type FormSubmitHandler, type HelpersFunc, type InferState, type InferSubmitHandler, type ItemAutocompleteProps, type ItemInputProps, type ItemNumberInputProps, type ItemRadioGroupProps, type ItemSelectProps, type ItemToggleProps, type MetadataType, type NestedChangeProps, NextUIError, type OnMethods, type StateType, type UseFormResponse, type ValueChangeFunc, useForm };
package/dist/index.d.ts CHANGED
@@ -92,7 +92,7 @@ interface ItemNumberInputProps extends ComponentInputProps {
92
92
  /** Props returned by on.select() */
93
93
  interface ItemSelectProps extends ComponentInputProps {
94
94
  onSelectionChange: NonNullable<SelectProps["onSelectionChange"]>;
95
- selectedKeys: string[] | number[] | string | null;
95
+ selectedKeys: NonNullable<SelectProps["selectedKeys"]>;
96
96
  }
97
97
  /** Props returned by on.autocomplete() */
98
98
  interface ItemAutocompleteProps extends ComponentInputProps {
@@ -164,16 +164,30 @@ type ObjectArrayFieldPaths<O extends StateType> = {
164
164
  [K in keyof O]: O[K] extends Record<string, any>[] ? `${K & string}.${FieldPaths<ArrayElement<O[K]>>}` : never;
165
165
  }[keyof O];
166
166
  type ArrayElement<T> = T extends (infer E)[] ? E : never;
167
+ /** Resolves the type of the identifier field for an array element (defaults to "id"). */
168
+ type ItemIdType<O extends StateType, K extends keyof O> = "id" extends keyof ArrayElement<O[K]> ? ArrayElement<O[K]>["id"] : string | number;
169
+ /** Extracts the array key from a composite path e.g. "relatives.age" → "relatives". */
170
+ type ExtractArrayKey<P extends string> = P extends `${infer K}.${string}` ? K : never;
171
+ /**
172
+ * Resolves the identifier field type for the array referenced by a composite path.
173
+ * e.g. if relatives[].id is string, then ArrayItemIdTypeFromPath<O, "relatives.age"> = string
174
+ */
175
+ type ArrayItemIdTypeFromPath<O extends StateType, P extends string> = ExtractArrayKey<P> extends keyof O ? ItemIdType<O, ExtractArrayKey<P>> : string | number;
176
+ /**
177
+ * Resolves the value type for the field referenced by a composite path.
178
+ * e.g. "relatives.age" → number (the type of the `age` field in each relative item)
179
+ */
180
+ type CompositeFieldValue<O extends StateType, P extends string> = P extends `${infer K}.${infer F}` ? K extends keyof O ? O[K] extends (infer E)[] ? F extends keyof E ? NonNullable<E[F]> : any : any : any : any;
167
181
  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;
168
182
  type FieldPaths<T> = T extends Record<string, any> ? {
169
183
  [K in keyof T & string]: T[K] extends any[] ? K : T[K] extends Record<string, any> ? `${K}.${FieldPaths<T[K]>}` : K;
170
184
  }[keyof T & string] : never;
171
185
  type NestedObjectPaths<O extends StateType> = {
172
- [K in keyof O & string]: O[K] extends any[] ? never : O[K] extends Record<string, any> ? `${K}.${FieldPaths<O[K]>}` : never;
186
+ [K in keyof O & string]: NonNullable<O[K]> extends any[] ? never : NonNullable<O[K]> extends Date ? never : NonNullable<O[K]> extends Record<string, any> ? `${K}.${FieldPaths<NonNullable<O[K]>>}` : never;
173
187
  }[keyof O & string];
174
- /** Keys whose values are not arrays and not plain objects (i.e. scalar/primitive fields). */
188
+ /** Keys whose values are not arrays and not plain objects (i.e. scalar/primitive fields). Date is treated as a scalar. */
175
189
  type ScalarKeys<O extends StateType> = {
176
- [K in keyof O]: O[K] extends any[] ? never : O[K] extends Record<string, any> ? never : K;
190
+ [K in keyof O]: NonNullable<O[K]> extends any[] ? never : NonNullable<O[K]> extends Date ? K : NonNullable<O[K]> extends Record<string, any> ? never : K;
177
191
  }[keyof O];
178
192
  type AllPaths<O extends StateType> = ScalarKeys<O> | NestedObjectPaths<O>;
179
193
  /**
@@ -183,19 +197,19 @@ interface HelpersFunc<O extends StateType> {
183
197
  /** Adds a new item to an array. */
184
198
  addItem: <K extends ArrayPaths<O>>(arrayKey: K, item: NestedFieldValue<O, K> extends (infer E)[] ? E : never, index?: number) => void;
185
199
  /** Removes an item from an array by its index. */
186
- removeItem: <K extends ArrayPaths<O>>(arrayKey: K, index: number) => void;
200
+ removeItemByIndexByIndex: <K extends ArrayPaths<O>>(arrayKey: K, index: number) => void;
187
201
  /** Removes an item from an array by its unique identifier. */
188
202
  removeById: <K extends ArrayPaths<O>>(arrayKey: K, itemId: string | number) => void;
189
203
  /** Updates an item in an array at the given index (supports partial updates). */
190
- updateItem: <K extends ArrayPaths<O>>(arrayKey: K, index: number, value: NestedFieldValue<O, K> extends (infer E)[] ? Partial<E> : never) => void;
204
+ updateByIndex: <K extends ArrayPaths<O>>(arrayKey: K, index: number, value: NestedFieldValue<O, K> extends (infer E)[] ? Partial<E> : never) => void;
191
205
  /** Updates an item in an array by its unique identifier (supports partial updates). */
192
206
  updateById: <K extends ArrayPaths<O>>(arrayKey: K, itemId: string | number, value: NestedFieldValue<O, K> extends (infer E)[] ? Partial<E> : never) => void;
193
207
  /** Moves an item within an array using indices. */
194
- moveItem: <K extends ArrayPaths<O>>(arrayKey: K, from: number, to: number) => void;
208
+ moveItemByIndex: <K extends ArrayPaths<O>>(arrayKey: K, from: number, to: number) => void;
195
209
  /** Moves an item within an array using unique identifiers. */
196
210
  moveById: <K extends ArrayPaths<O>>(arrayKey: K, fromId: string | number, toId: string | number) => void;
197
211
  /** Gets an item from an array by its unique identifier (O(1) via indexMap). */
198
- getItem: <K extends ArrayPaths<O>>(arrayKey: K, itemId: string | number) => (NestedFieldValue<O, K> extends (infer E)[] ? E : never) | undefined;
212
+ getItemById: <K extends ArrayPaths<O>>(arrayKey: K, itemId: string | number) => (NestedFieldValue<O, K> extends (infer E)[] ? E : never) | undefined;
199
213
  }
200
214
  /**
201
215
  * The response object from the useForm hook.
@@ -205,12 +219,26 @@ interface UseFormResponse<O extends StateType> {
205
219
  onFieldBlur: BlurFunc<O>;
206
220
  /** Updates a scalar or nested object field. */
207
221
  onFieldChange<P extends AllPaths<O>>(id: P, value: NestedFieldValue<O, P & string>): void;
208
- /** Manually updates a field within an object array item using "array.field" composite path. */
209
- onArrayItemChange<P extends ObjectArrayFieldPaths<O>>(compositePath: P, itemId: string | number, value: any): void;
222
+ /** Manually updates a field within an object array item. */
223
+ onArrayItemChange<P extends ObjectArrayFieldPaths<O>>(options: {
224
+ /** Composite dot-notation path: e.g. "users.name" */
225
+ at: P;
226
+ /** The unique identifier of the target array item — type is inferred from the array element's id field. */
227
+ id: ArrayItemIdTypeFromPath<O, P & string>;
228
+ /** The new value — type is inferred from the field referenced by `at`. */
229
+ value: CompositeFieldValue<O, P & string>;
230
+ }): void;
210
231
  /** Manually updates a scalar or nested object selection field. */
211
232
  onSelectionChange: ValueChangeFunc<O, keyof O>;
212
233
  /** Manually updates a selection-based field within an object array item. */
213
- onArraySelectionChange<P extends ObjectArrayFieldPaths<O>>(compositePath: P, itemId: string | number, value: any): void;
234
+ onArraySelectionChange<P extends ObjectArrayFieldPaths<O>>(options: {
235
+ /** Composite dot-notation path: e.g. "users.role" */
236
+ at: P;
237
+ /** The unique identifier of the target array item — type is inferred from the array element's id field. */
238
+ id: ArrayItemIdTypeFromPath<O, P & string>;
239
+ /** The new selection value — type is inferred from the field referenced by `at`. */
240
+ value: CompositeFieldValue<O, P & string>;
241
+ }): void;
214
242
  state: O;
215
243
  setState: React.Dispatch<React.SetStateAction<O>>;
216
244
  metadata: MetadataType;
@@ -240,4 +268,4 @@ interface UseFormResponse<O extends StateType> {
240
268
 
241
269
  declare function useForm<S extends Record<string, ConfigType>>(schema: S, { arrayIdentifiers, onFormSubmit: onFormSubmitProp, resetOnSubmit, keepValues: keepValuesProp, }?: FormOptions<InferState<S>>): UseFormResponse<InferState<S>>;
242
270
 
243
- 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 };
271
+ export { type BlurFunc, type ComponentInputProps, type ConfigType, type FieldMetadata, type FormOptions, type FormResetOptions, type FormSubmitHandler, type HelpersFunc, type InferState, type InferSubmitHandler, type ItemAutocompleteProps, type ItemInputProps, type ItemNumberInputProps, type ItemRadioGroupProps, type ItemSelectProps, type ItemToggleProps, type MetadataType, type NestedChangeProps, NextUIError, type OnMethods, type StateType, type UseFormResponse, type ValueChangeFunc, useForm };
package/dist/index.js CHANGED
@@ -752,7 +752,7 @@ function useForm(schema, {
752
752
  });
753
753
  });
754
754
  },
755
- removeItem: (arrayKey, index) => {
755
+ removeItemByIndexByIndex: (arrayKey, index) => {
756
756
  const currentArr = getNestedValue(stateRef.current, arrayKey) || [];
757
757
  const item = currentArr[index];
758
758
  const idKey = arrayIdentifiers?.[arrayKey] || "id";
@@ -789,7 +789,7 @@ function useForm(schema, {
789
789
  setMetadata((prev) => removeCompositeKeysByPrefix(prev, prefix));
790
790
  }
791
791
  },
792
- updateItem: (arrayKey, index, value) => {
792
+ updateByIndex: (arrayKey, index, value) => {
793
793
  setState((prev) => {
794
794
  const arr = [...getNestedValue(prev, arrayKey) || []];
795
795
  arr[index] = typeof arr[index] === "object" && typeof value === "object" ? { ...arr[index], ...value } : value;
@@ -816,7 +816,7 @@ function useForm(schema, {
816
816
  });
817
817
  }
818
818
  },
819
- moveItem: (arrayKey, from, to) => {
819
+ moveItemByIndex: (arrayKey, from, to) => {
820
820
  setState((prev) => {
821
821
  const arr = [...getNestedValue(prev, arrayKey) || []];
822
822
  const [item] = arr.splice(from, 1);
@@ -846,7 +846,7 @@ function useForm(schema, {
846
846
  });
847
847
  }
848
848
  },
849
- getItem: (arrayKey, itemId) => {
849
+ getItemById: (arrayKey, itemId) => {
850
850
  const index = getIndex(arrayKey, itemId);
851
851
  if (index === void 0) return void 0;
852
852
  return getNestedValue(stateRef.current, arrayKey)[index];
@@ -889,7 +889,11 @@ function useForm(schema, {
889
889
  [getIndex, handleFieldChange]
890
890
  );
891
891
  const arrayItemChange = (0, import_react2.useCallback)(
892
- (compositePath, itemId, value) => {
892
+ ({
893
+ at: compositePath,
894
+ id: itemId,
895
+ value
896
+ }) => {
893
897
  const data = resolveFieldData(
894
898
  [compositePath, itemId],
895
899
  stateRef.current,
@@ -915,7 +919,11 @@ function useForm(schema, {
915
919
  [validateField]
916
920
  );
917
921
  const arraySelectionChange = (0, import_react2.useCallback)(
918
- (compositePath, itemId, val) => {
922
+ ({
923
+ at: compositePath,
924
+ id: itemId,
925
+ value: val
926
+ }) => {
919
927
  const fixed = typeof val === "string" || val === null ? val : Array.from(val);
920
928
  const data = resolveFieldData(
921
929
  [compositePath, itemId],
package/dist/index.mjs CHANGED
@@ -726,7 +726,7 @@ function useForm(schema, {
726
726
  });
727
727
  });
728
728
  },
729
- removeItem: (arrayKey, index) => {
729
+ removeItemByIndexByIndex: (arrayKey, index) => {
730
730
  const currentArr = getNestedValue(stateRef.current, arrayKey) || [];
731
731
  const item = currentArr[index];
732
732
  const idKey = arrayIdentifiers?.[arrayKey] || "id";
@@ -763,7 +763,7 @@ function useForm(schema, {
763
763
  setMetadata((prev) => removeCompositeKeysByPrefix(prev, prefix));
764
764
  }
765
765
  },
766
- updateItem: (arrayKey, index, value) => {
766
+ updateByIndex: (arrayKey, index, value) => {
767
767
  setState((prev) => {
768
768
  const arr = [...getNestedValue(prev, arrayKey) || []];
769
769
  arr[index] = typeof arr[index] === "object" && typeof value === "object" ? { ...arr[index], ...value } : value;
@@ -790,7 +790,7 @@ function useForm(schema, {
790
790
  });
791
791
  }
792
792
  },
793
- moveItem: (arrayKey, from, to) => {
793
+ moveItemByIndex: (arrayKey, from, to) => {
794
794
  setState((prev) => {
795
795
  const arr = [...getNestedValue(prev, arrayKey) || []];
796
796
  const [item] = arr.splice(from, 1);
@@ -820,7 +820,7 @@ function useForm(schema, {
820
820
  });
821
821
  }
822
822
  },
823
- getItem: (arrayKey, itemId) => {
823
+ getItemById: (arrayKey, itemId) => {
824
824
  const index = getIndex(arrayKey, itemId);
825
825
  if (index === void 0) return void 0;
826
826
  return getNestedValue(stateRef.current, arrayKey)[index];
@@ -863,7 +863,11 @@ function useForm(schema, {
863
863
  [getIndex, handleFieldChange]
864
864
  );
865
865
  const arrayItemChange = useCallback(
866
- (compositePath, itemId, value) => {
866
+ ({
867
+ at: compositePath,
868
+ id: itemId,
869
+ value
870
+ }) => {
867
871
  const data = resolveFieldData(
868
872
  [compositePath, itemId],
869
873
  stateRef.current,
@@ -889,7 +893,11 @@ function useForm(schema, {
889
893
  [validateField]
890
894
  );
891
895
  const arraySelectionChange = useCallback(
892
- (compositePath, itemId, val) => {
896
+ ({
897
+ at: compositePath,
898
+ id: itemId,
899
+ value: val
900
+ }) => {
893
901
  const fixed = typeof val === "string" || val === null ? val : Array.from(val);
894
902
  const data = resolveFieldData(
895
903
  [compositePath, itemId],
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@juantroconisf/lib",
3
- "version": "10.0.0",
3
+ "version": "11.0.1",
4
4
  "description": "A form validation library for HeroUI.",
5
5
  "main": "dist/index.js",
6
6
  "module": "dist/index.mjs",