@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 +71 -25
- package/dist/index.d.mts +40 -12
- package/dist/index.d.ts +40 -12
- package/dist/index.js +14 -6
- package/dist/index.mjs +14 -6
- package/package.json +1 -1
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 | `(
|
|
199
|
-
| `onSelectionChange` | Scalar / nested selection field | `(id, value)`
|
|
200
|
-
| `onArraySelectionChange` | Array item selection field | `(
|
|
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
|
-
|
|
211
|
+
// Update a selection field inside an array item
|
|
212
|
+
onArraySelectionChange({ at: "users.role", id: userId, value: "admin" });
|
|
213
213
|
```
|
|
214
214
|
|
|
215
|
-
>
|
|
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
|
|
224
|
-
|
|
|
225
|
-
| `addItem(path, item, index?)`
|
|
226
|
-
| `
|
|
227
|
-
| `removeById(path, id)`
|
|
228
|
-
| `
|
|
229
|
-
| `updateById(path, id, partial)`
|
|
230
|
-
| `
|
|
231
|
-
| `moveById(path, fromId, toId)`
|
|
232
|
-
| `
|
|
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
|
-
|
|
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(
|
|
251
|
+
.of(
|
|
252
|
+
object({
|
|
253
|
+
uuid: string().required(),
|
|
254
|
+
name: string().required(),
|
|
255
|
+
role: string().required(),
|
|
256
|
+
}),
|
|
257
|
+
)
|
|
252
258
|
.default([]),
|
|
253
259
|
},
|
|
254
|
-
{
|
|
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
|
-
|
|
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:
|
|
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]
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
209
|
-
onArrayItemChange<P extends ObjectArrayFieldPaths<O>>(
|
|
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>>(
|
|
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:
|
|
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]
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
|
209
|
-
onArrayItemChange<P extends ObjectArrayFieldPaths<O>>(
|
|
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>>(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
(
|
|
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
|
-
(
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
|
|
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
|
-
(
|
|
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
|
-
(
|
|
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],
|