@juantroconisf/lib 6.1.0 → 7.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/README.md CHANGED
@@ -27,36 +27,33 @@ pnpm add @juantroconisf/lib
27
27
  import { useForm } from "@juantroconisf/lib";
28
28
 
29
29
  const MyForm = () => {
30
- const { on, state, helpers } = useForm({
31
- name: "Juan",
32
- lines: [
33
- { id: 1, amount: 10 }
34
- ]
35
- }, {
36
- rules: {
37
- name: { required: true }
30
+ const { on, state, helpers } = useForm(
31
+ {
32
+ name: "Juan",
33
+ lines: [{ id: 1, amount: 10 }],
38
34
  },
39
- arrayRules: {
40
- lines: {
41
- amount: (item, index) => ({ min: 1 })
42
- }
43
- }
44
- });
35
+ {
36
+ rules: {
37
+ name: { required: true },
38
+ "lines.amount": (value, state, item) => ({ min: 1 }),
39
+ },
40
+ },
41
+ );
45
42
 
46
43
  return (
47
44
  <form>
48
45
  {/* Scalar/Nested Registration */}
49
- <Input {...on.input("name")} label="Name" />
46
+ <Input {...on.input("name")} label='Name' />
50
47
 
51
- {/* Array Registration (By ID) */}
48
+ {/* Array Registration (By ID + Composite Key) */}
52
49
  {state.lines.map((line) => (
53
- <Input
54
- key={line.id}
55
- {...on.input("lines", line.id, "amount")}
56
- label="Amount"
50
+ <Input
51
+ key={line.id}
52
+ {...on.input("lines.amount", line.id)}
53
+ label='Amount'
57
54
  />
58
55
  ))}
59
-
56
+
60
57
  <Button onClick={() => helpers.removeById("lines", 1)}>
61
58
  Remove First
62
59
  </Button>
@@ -72,26 +69,30 @@ const MyForm = () => {
72
69
  ### `useForm(initialState, options)`
73
70
 
74
71
  #### Options
75
- - **`rules`**: Validation rules for root/nested fields.
76
- - **`messages`**: Custom error messages for root/nested fields.
77
- - **`arrayRules`**: Validation rules for array items. Receives `(item, index)`.
78
- - **`arrayMessages`**: Custom error messages for array items.
79
- - **`arrayIdentifiers`**: Mapping of array keys to their unique ID property (defaults to `"id"`).
72
+
73
+ - **`rules`**: Validation rules map. Keys can be deep paths (e.g. `user.name`, `lines.amount`). Supports functional rules `(value, state, item?, index?)`.
74
+ - **`messages`**: Custom error messages map. Keys match rules.
75
+ - **`arrayIdentifiers`**: Mapping of array keys (supporting dot-notation for nested arrays) to their unique ID property (defaults to `"id"`).
80
76
 
81
77
  ### The `on` Object
82
- Provides methods to register components with the form state. Support both scalar/nested paths and array tracking.
83
78
 
84
- - **`on.input(path)`** / **`on.input(arrayKey, itemId, field)`**
85
- - **`on.select(path)`** / **`on.select(arrayKey, itemId, field)`**
86
- - **`on.autocomplete(path)`** / **`on.autocomplete(arrayKey, itemId, field)`**
79
+ Provides methods to register components with the form state. Support both scalar/nested paths and array tracking via composite keys.
80
+
81
+ - **`on.input(path)`** / **`on.input(compositeKey, itemId)`** / **`on.input(arrayKey, index)`** (for primitive arrays)
82
+ - **`on.select(path)`** / **`on.select(compositeKey, itemId)`** / **`on.select(arrayKey, index)`**
83
+ - **`on.autocomplete(path)`** / **`on.autocomplete(compositeKey, itemId)`** / **`on.autocomplete(arrayKey, index)`**
87
84
 
88
85
  ### Helpers
86
+
89
87
  Utilities for common state manipulations:
88
+
90
89
  - **`addItem(arrayKey, item, index?)`**
91
90
  - **`removeItem(arrayKey, index)`**
92
91
  - **`removeById(arrayKey, itemId)`**
92
+ - **`updateItem(arrayKey, index, value)`**
93
93
  - **`moveItem(arrayKey, from, to)`**
94
94
  - **`moveById(arrayKey, fromId, toId)`**
95
+ - **`getItem(arrayKey, itemId)`**
95
96
 
96
97
  ---
97
98
 
package/dist/index.d.mts CHANGED
@@ -60,7 +60,7 @@ interface FormOptions<O extends StateType> {
60
60
  * Custom property names used as unique identifiers for items in specific arrays.
61
61
  * Default is "id".
62
62
  */
63
- arrayIdentifiers?: Partial<Record<ArrayKeys<O>, string>>;
63
+ arrayIdentifiers?: Partial<Record<ArrayPaths<O>, string>>;
64
64
  }
65
65
  type TouchedType = Map<string, boolean>;
66
66
  type ErrorsType = Map<string, NextUIError>;
@@ -72,10 +72,6 @@ interface ComponentInputProps<O extends StateType> {
72
72
  isInvalid: boolean;
73
73
  errorMessage: string;
74
74
  }
75
- type UXProps<O extends StateType> = Record<keyof O, {
76
- isInvalid: boolean;
77
- errorMessage: string;
78
- }>;
79
75
  /** Props returned by on.input() */
80
76
  interface ItemInputProps<V = any> extends ComponentInputProps<any> {
81
77
  onValueChange: (value: V) => void;
@@ -98,23 +94,49 @@ interface OnMethods<O extends StateType> {
98
94
  /** Registers a scalar or nested object field. */
99
95
  input<P extends AllPaths<O>>(id: P): ItemInputProps<NestedFieldValue<O, P & string>>;
100
96
  /** Registers an array element — adapts to primitive arrays (by index) or object arrays (by ID + field). */
101
- input<K extends ArrayKeys<O>>(arrayKey: K, ...args: O[K] extends Record<string, any>[] ? [itemId: ItemIdType<O, K>, field: FieldPaths<ArrayElement<O[K]>>] | [itemId: ItemIdType<O, K>, field: string, index: number] : [index: number]): ItemInputProps<any>;
97
+ /** Registers an array element adapts to primitive arrays (by index). */
98
+ input<K extends ArrayKeys<O>>(arrayKey: K, index: number): ItemInputProps<any>;
99
+ /** Registers an object array element's field using composite syntax "array.field". */
100
+ input<P extends ObjectArrayFieldPaths<O>>(compositePath: P, itemId: ItemIdType<O, GetArrayKeyFromPath<O, P>>): ItemInputProps<any>;
102
101
  /** Registers a scalar or nested object field. */
103
102
  select<P extends AllPaths<O>>(id: P): ItemSelectProps;
104
103
  /** Registers an array element — adapts to primitive arrays (by index) or object arrays (by ID + field). */
105
- select<K extends ArrayKeys<O>>(arrayKey: K, ...args: O[K] extends Record<string, any>[] ? [itemId: ItemIdType<O, K>, field: FieldPaths<ArrayElement<O[K]>>] | [itemId: ItemIdType<O, K>, field: string, index: number] : [index: number]): ItemSelectProps;
104
+ /** Registers an array element adapts to primitive arrays (by index). */
105
+ select<K extends ArrayKeys<O>>(arrayKey: K, index: number): ItemSelectProps;
106
+ /** Registers an object array element's field using composite syntax "array.field". */
107
+ select<P extends ObjectArrayFieldPaths<O>>(compositePath: P, itemId: ItemIdType<O, GetArrayKeyFromPath<O, P>>): ItemSelectProps;
106
108
  /** Registers a scalar or nested object field. */
107
109
  autocomplete<P extends AllPaths<O>>(id: P): ItemAutocompleteProps;
108
110
  /** Registers an array element — adapts to primitive arrays (by index) or object arrays (by ID + field). */
109
- autocomplete<K extends ArrayKeys<O>>(arrayKey: K, ...args: O[K] extends Record<string, any>[] ? [itemId: ItemIdType<O, K>, field: FieldPaths<ArrayElement<O[K]>>] | [itemId: ItemIdType<O, K>, field: string, index: number] : [index: number]): ItemAutocompleteProps;
111
+ /** Registers an array element adapts to primitive arrays (by index). */
112
+ autocomplete<K extends ArrayKeys<O>>(arrayKey: K, index: number): ItemAutocompleteProps;
113
+ /** Registers an object array element's field using composite syntax "array.field". */
114
+ autocomplete<P extends ObjectArrayFieldPaths<O>>(compositePath: P, itemId: ItemIdType<O, GetArrayKeyFromPath<O, P>>): ItemAutocompleteProps;
110
115
  }
111
116
  type ArrayKeys<O extends StateType> = {
112
117
  [K in keyof O]: O[K] extends any[] ? K : never;
113
118
  }[keyof O];
119
+ /**
120
+ * Recursive type to find all paths to arrays in the state.
121
+ */
122
+ type ArrayPaths<T> = T extends object ? {
123
+ [K in keyof T & string]: NonNullable<T[K]> extends (infer E)[] ? K | (E extends object ? `${K}.${ArrayPaths<E>}` : never) : NonNullable<T[K]> extends object ? NonNullable<T[K]> extends Date ? never : `${K}.${ArrayPaths<NonNullable<T[K]>>}` : never;
124
+ }[keyof T & string] : never;
114
125
  /** Keys whose values are arrays of objects (not primitives). */
115
126
  type ObjectArrayKeys<O extends StateType> = {
116
127
  [K in keyof O]: O[K] extends Record<string, any>[] ? K : never;
117
128
  }[keyof O];
129
+ /**
130
+ * Helper to get paths for fields within object arrays.
131
+ * Returns paths like "arrayKey.fieldName".
132
+ */
133
+ type ObjectArrayFieldPaths<O extends StateType> = {
134
+ [K in keyof O]: O[K] extends Record<string, any>[] ? `${K & string}.${FieldPaths<ArrayElement<O[K]>>}` : never;
135
+ }[keyof O];
136
+ /**
137
+ * Helper to extract the array key from a path string like "arrayKey.field".
138
+ */
139
+ 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;
118
140
  type ArrayElement<T> = T extends (infer E)[] ? E : never;
119
141
  /** Resolves the type of the identifier field for an array element (defaults to "id"). */
120
142
  type ItemIdType<O extends StateType, K extends keyof O> = "id" extends keyof ArrayElement<O[K]> ? ArrayElement<O[K]>["id"] : string | number;
@@ -179,4 +201,4 @@ interface UseFormResponse<O extends StateType> {
179
201
 
180
202
  declare function useForm<O extends StateType>(initialState: O, { rules, messages, arrayIdentifiers }?: FormOptions<O>): UseFormResponse<O>;
181
203
 
182
- export { type BlurFunc, type ErrorsType, type FormOptions, type HelpersFunc, type NestedChangeProps, NextUIError, type OnMethods, type StateType, type TouchedType, type UXProps, type UseFormResponse, type Validator, type ValidatorErrorMessage, type ValidatorParams, type ValidatorRule, type ValidatorTypes, type ValueChangeFunc, useForm };
204
+ export { type BlurFunc, type ErrorsType, type FormOptions, type HelpersFunc, type NestedChangeProps, NextUIError, type OnMethods, type StateType, type TouchedType, type UseFormResponse, type Validator, type ValidatorErrorMessage, type ValidatorParams, type ValidatorRule, type ValidatorTypes, type ValueChangeFunc, useForm };
package/dist/index.d.ts CHANGED
@@ -60,7 +60,7 @@ interface FormOptions<O extends StateType> {
60
60
  * Custom property names used as unique identifiers for items in specific arrays.
61
61
  * Default is "id".
62
62
  */
63
- arrayIdentifiers?: Partial<Record<ArrayKeys<O>, string>>;
63
+ arrayIdentifiers?: Partial<Record<ArrayPaths<O>, string>>;
64
64
  }
65
65
  type TouchedType = Map<string, boolean>;
66
66
  type ErrorsType = Map<string, NextUIError>;
@@ -72,10 +72,6 @@ interface ComponentInputProps<O extends StateType> {
72
72
  isInvalid: boolean;
73
73
  errorMessage: string;
74
74
  }
75
- type UXProps<O extends StateType> = Record<keyof O, {
76
- isInvalid: boolean;
77
- errorMessage: string;
78
- }>;
79
75
  /** Props returned by on.input() */
80
76
  interface ItemInputProps<V = any> extends ComponentInputProps<any> {
81
77
  onValueChange: (value: V) => void;
@@ -98,23 +94,49 @@ interface OnMethods<O extends StateType> {
98
94
  /** Registers a scalar or nested object field. */
99
95
  input<P extends AllPaths<O>>(id: P): ItemInputProps<NestedFieldValue<O, P & string>>;
100
96
  /** Registers an array element — adapts to primitive arrays (by index) or object arrays (by ID + field). */
101
- input<K extends ArrayKeys<O>>(arrayKey: K, ...args: O[K] extends Record<string, any>[] ? [itemId: ItemIdType<O, K>, field: FieldPaths<ArrayElement<O[K]>>] | [itemId: ItemIdType<O, K>, field: string, index: number] : [index: number]): ItemInputProps<any>;
97
+ /** Registers an array element adapts to primitive arrays (by index). */
98
+ input<K extends ArrayKeys<O>>(arrayKey: K, index: number): ItemInputProps<any>;
99
+ /** Registers an object array element's field using composite syntax "array.field". */
100
+ input<P extends ObjectArrayFieldPaths<O>>(compositePath: P, itemId: ItemIdType<O, GetArrayKeyFromPath<O, P>>): ItemInputProps<any>;
102
101
  /** Registers a scalar or nested object field. */
103
102
  select<P extends AllPaths<O>>(id: P): ItemSelectProps;
104
103
  /** Registers an array element — adapts to primitive arrays (by index) or object arrays (by ID + field). */
105
- select<K extends ArrayKeys<O>>(arrayKey: K, ...args: O[K] extends Record<string, any>[] ? [itemId: ItemIdType<O, K>, field: FieldPaths<ArrayElement<O[K]>>] | [itemId: ItemIdType<O, K>, field: string, index: number] : [index: number]): ItemSelectProps;
104
+ /** Registers an array element adapts to primitive arrays (by index). */
105
+ select<K extends ArrayKeys<O>>(arrayKey: K, index: number): ItemSelectProps;
106
+ /** Registers an object array element's field using composite syntax "array.field". */
107
+ select<P extends ObjectArrayFieldPaths<O>>(compositePath: P, itemId: ItemIdType<O, GetArrayKeyFromPath<O, P>>): ItemSelectProps;
106
108
  /** Registers a scalar or nested object field. */
107
109
  autocomplete<P extends AllPaths<O>>(id: P): ItemAutocompleteProps;
108
110
  /** Registers an array element — adapts to primitive arrays (by index) or object arrays (by ID + field). */
109
- autocomplete<K extends ArrayKeys<O>>(arrayKey: K, ...args: O[K] extends Record<string, any>[] ? [itemId: ItemIdType<O, K>, field: FieldPaths<ArrayElement<O[K]>>] | [itemId: ItemIdType<O, K>, field: string, index: number] : [index: number]): ItemAutocompleteProps;
111
+ /** Registers an array element adapts to primitive arrays (by index). */
112
+ autocomplete<K extends ArrayKeys<O>>(arrayKey: K, index: number): ItemAutocompleteProps;
113
+ /** Registers an object array element's field using composite syntax "array.field". */
114
+ autocomplete<P extends ObjectArrayFieldPaths<O>>(compositePath: P, itemId: ItemIdType<O, GetArrayKeyFromPath<O, P>>): ItemAutocompleteProps;
110
115
  }
111
116
  type ArrayKeys<O extends StateType> = {
112
117
  [K in keyof O]: O[K] extends any[] ? K : never;
113
118
  }[keyof O];
119
+ /**
120
+ * Recursive type to find all paths to arrays in the state.
121
+ */
122
+ type ArrayPaths<T> = T extends object ? {
123
+ [K in keyof T & string]: NonNullable<T[K]> extends (infer E)[] ? K | (E extends object ? `${K}.${ArrayPaths<E>}` : never) : NonNullable<T[K]> extends object ? NonNullable<T[K]> extends Date ? never : `${K}.${ArrayPaths<NonNullable<T[K]>>}` : never;
124
+ }[keyof T & string] : never;
114
125
  /** Keys whose values are arrays of objects (not primitives). */
115
126
  type ObjectArrayKeys<O extends StateType> = {
116
127
  [K in keyof O]: O[K] extends Record<string, any>[] ? K : never;
117
128
  }[keyof O];
129
+ /**
130
+ * Helper to get paths for fields within object arrays.
131
+ * Returns paths like "arrayKey.fieldName".
132
+ */
133
+ type ObjectArrayFieldPaths<O extends StateType> = {
134
+ [K in keyof O]: O[K] extends Record<string, any>[] ? `${K & string}.${FieldPaths<ArrayElement<O[K]>>}` : never;
135
+ }[keyof O];
136
+ /**
137
+ * Helper to extract the array key from a path string like "arrayKey.field".
138
+ */
139
+ 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;
118
140
  type ArrayElement<T> = T extends (infer E)[] ? E : never;
119
141
  /** Resolves the type of the identifier field for an array element (defaults to "id"). */
120
142
  type ItemIdType<O extends StateType, K extends keyof O> = "id" extends keyof ArrayElement<O[K]> ? ArrayElement<O[K]>["id"] : string | number;
@@ -179,4 +201,4 @@ interface UseFormResponse<O extends StateType> {
179
201
 
180
202
  declare function useForm<O extends StateType>(initialState: O, { rules, messages, arrayIdentifiers }?: FormOptions<O>): UseFormResponse<O>;
181
203
 
182
- export { type BlurFunc, type ErrorsType, type FormOptions, type HelpersFunc, type NestedChangeProps, NextUIError, type OnMethods, type StateType, type TouchedType, type UXProps, type UseFormResponse, type Validator, type ValidatorErrorMessage, type ValidatorParams, type ValidatorRule, type ValidatorTypes, type ValueChangeFunc, useForm };
204
+ export { type BlurFunc, type ErrorsType, type FormOptions, type HelpersFunc, type NestedChangeProps, NextUIError, type OnMethods, type StateType, type TouchedType, type UseFormResponse, type Validator, type ValidatorErrorMessage, type ValidatorParams, type ValidatorRule, type ValidatorTypes, type ValueChangeFunc, useForm };