@juantroconisf/lib 5.3.0 → 6.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.mts +12 -31
- package/dist/index.d.ts +12 -31
- package/dist/index.js +97 -125
- package/dist/index.mjs +97 -125
- package/package.json +1 -1
package/dist/index.d.mts
CHANGED
|
@@ -43,46 +43,27 @@ type ValidatorErrorMessage = {
|
|
|
43
43
|
* @template O The state type.
|
|
44
44
|
* @template K The key of the array in the state.
|
|
45
45
|
*/
|
|
46
|
-
type
|
|
47
|
-
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
* Custom error messages for individual fields in an array item.
|
|
51
|
-
* @template O The state type.
|
|
52
|
-
* @template K The key of the array in the state.
|
|
53
|
-
*/
|
|
54
|
-
type ArrayMessages<O extends StateType, K extends keyof O = keyof O> = {
|
|
55
|
-
[F in FieldPaths<ArrayElement<O[K]>>]?: ValidatorErrorMessage;
|
|
56
|
-
};
|
|
46
|
+
type ValidatorRule<item = any> = ValidatorParams | ((item: item, ...args: any[]) => ValidatorParams);
|
|
47
|
+
type RulePath<T> = T extends object ? {
|
|
48
|
+
[K in keyof T & string]: NonNullable<T[K]> extends (infer E)[] ? K | (E extends object ? `${K}.${RulePath<E>}` : never) : NonNullable<T[K]> extends object ? NonNullable<T[K]> extends Date ? K : K | `${K}.${RulePath<NonNullable<T[K]>>}` : K;
|
|
49
|
+
}[keyof T & string] : never;
|
|
57
50
|
/**
|
|
58
51
|
* Options for the useForm hook.
|
|
59
52
|
* @template O The state type.
|
|
60
53
|
*/
|
|
61
54
|
interface FormOptions<O extends StateType> {
|
|
62
55
|
/** Validation rules for top-level fields. */
|
|
63
|
-
rules?:
|
|
64
|
-
[key in keyof O]?: ValidatorParams;
|
|
65
|
-
};
|
|
56
|
+
rules?: Partial<Record<RulePath<O>, ValidatorRule>>;
|
|
66
57
|
/** Custom error messages for top-level fields. */
|
|
67
|
-
messages?:
|
|
68
|
-
[key in keyof O]?: ValidatorErrorMessage;
|
|
69
|
-
};
|
|
70
|
-
/** Validation rules for items within arrays. */
|
|
71
|
-
arrayRules?: {
|
|
72
|
-
[K in ArrayKeys<O>]?: ArrayRules<O, K>;
|
|
73
|
-
};
|
|
74
|
-
/** Custom error messages for items within arrays. */
|
|
75
|
-
arrayMessages?: {
|
|
76
|
-
[K in ArrayKeys<O>]?: ArrayMessages<O, K>;
|
|
77
|
-
};
|
|
58
|
+
messages?: Partial<Record<RulePath<O>, ValidatorErrorMessage>>;
|
|
78
59
|
/**
|
|
79
60
|
* Custom property names used as unique identifiers for items in specific arrays.
|
|
80
61
|
* Default is "id".
|
|
81
62
|
*/
|
|
82
63
|
arrayIdentifiers?: Partial<Record<ArrayKeys<O>, string>>;
|
|
83
64
|
}
|
|
84
|
-
type TouchedType
|
|
85
|
-
type ErrorsType
|
|
65
|
+
type TouchedType = Map<string, boolean>;
|
|
66
|
+
type ErrorsType = Map<string, NextUIError>;
|
|
86
67
|
type ValueChangeFunc<O extends StateType, K extends keyof O> = (id: K, value: O[K]) => void;
|
|
87
68
|
type BlurFunc<O extends StateType> = (id: keyof O) => void;
|
|
88
69
|
interface ComponentInputProps<O extends StateType> {
|
|
@@ -181,8 +162,8 @@ interface UseFormResponse<O extends StateType> {
|
|
|
181
162
|
onSelectionChange: ValueChangeFunc<O, keyof O>;
|
|
182
163
|
state: O;
|
|
183
164
|
setState: React.Dispatch<React.SetStateAction<O>>;
|
|
184
|
-
touched: TouchedType
|
|
185
|
-
errors: ErrorsType
|
|
165
|
+
touched: TouchedType;
|
|
166
|
+
errors: ErrorsType;
|
|
186
167
|
/** Main object to bind form elements to the state. */
|
|
187
168
|
on: OnMethods<O>;
|
|
188
169
|
/** Array manipulation helpers. */
|
|
@@ -196,6 +177,6 @@ interface UseFormResponse<O extends StateType> {
|
|
|
196
177
|
resetTouched: (preservedKeys?: (keyof O)[]) => void;
|
|
197
178
|
}
|
|
198
179
|
|
|
199
|
-
declare function useForm<O extends StateType>(initialState: O, { rules, messages,
|
|
180
|
+
declare function useForm<O extends StateType>(initialState: O, { rules, messages, arrayIdentifiers }?: FormOptions<O>): UseFormResponse<O>;
|
|
200
181
|
|
|
201
|
-
export { type
|
|
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 };
|
package/dist/index.d.ts
CHANGED
|
@@ -43,46 +43,27 @@ type ValidatorErrorMessage = {
|
|
|
43
43
|
* @template O The state type.
|
|
44
44
|
* @template K The key of the array in the state.
|
|
45
45
|
*/
|
|
46
|
-
type
|
|
47
|
-
|
|
48
|
-
};
|
|
49
|
-
|
|
50
|
-
* Custom error messages for individual fields in an array item.
|
|
51
|
-
* @template O The state type.
|
|
52
|
-
* @template K The key of the array in the state.
|
|
53
|
-
*/
|
|
54
|
-
type ArrayMessages<O extends StateType, K extends keyof O = keyof O> = {
|
|
55
|
-
[F in FieldPaths<ArrayElement<O[K]>>]?: ValidatorErrorMessage;
|
|
56
|
-
};
|
|
46
|
+
type ValidatorRule<item = any> = ValidatorParams | ((item: item, ...args: any[]) => ValidatorParams);
|
|
47
|
+
type RulePath<T> = T extends object ? {
|
|
48
|
+
[K in keyof T & string]: NonNullable<T[K]> extends (infer E)[] ? K | (E extends object ? `${K}.${RulePath<E>}` : never) : NonNullable<T[K]> extends object ? NonNullable<T[K]> extends Date ? K : K | `${K}.${RulePath<NonNullable<T[K]>>}` : K;
|
|
49
|
+
}[keyof T & string] : never;
|
|
57
50
|
/**
|
|
58
51
|
* Options for the useForm hook.
|
|
59
52
|
* @template O The state type.
|
|
60
53
|
*/
|
|
61
54
|
interface FormOptions<O extends StateType> {
|
|
62
55
|
/** Validation rules for top-level fields. */
|
|
63
|
-
rules?:
|
|
64
|
-
[key in keyof O]?: ValidatorParams;
|
|
65
|
-
};
|
|
56
|
+
rules?: Partial<Record<RulePath<O>, ValidatorRule>>;
|
|
66
57
|
/** Custom error messages for top-level fields. */
|
|
67
|
-
messages?:
|
|
68
|
-
[key in keyof O]?: ValidatorErrorMessage;
|
|
69
|
-
};
|
|
70
|
-
/** Validation rules for items within arrays. */
|
|
71
|
-
arrayRules?: {
|
|
72
|
-
[K in ArrayKeys<O>]?: ArrayRules<O, K>;
|
|
73
|
-
};
|
|
74
|
-
/** Custom error messages for items within arrays. */
|
|
75
|
-
arrayMessages?: {
|
|
76
|
-
[K in ArrayKeys<O>]?: ArrayMessages<O, K>;
|
|
77
|
-
};
|
|
58
|
+
messages?: Partial<Record<RulePath<O>, ValidatorErrorMessage>>;
|
|
78
59
|
/**
|
|
79
60
|
* Custom property names used as unique identifiers for items in specific arrays.
|
|
80
61
|
* Default is "id".
|
|
81
62
|
*/
|
|
82
63
|
arrayIdentifiers?: Partial<Record<ArrayKeys<O>, string>>;
|
|
83
64
|
}
|
|
84
|
-
type TouchedType
|
|
85
|
-
type ErrorsType
|
|
65
|
+
type TouchedType = Map<string, boolean>;
|
|
66
|
+
type ErrorsType = Map<string, NextUIError>;
|
|
86
67
|
type ValueChangeFunc<O extends StateType, K extends keyof O> = (id: K, value: O[K]) => void;
|
|
87
68
|
type BlurFunc<O extends StateType> = (id: keyof O) => void;
|
|
88
69
|
interface ComponentInputProps<O extends StateType> {
|
|
@@ -181,8 +162,8 @@ interface UseFormResponse<O extends StateType> {
|
|
|
181
162
|
onSelectionChange: ValueChangeFunc<O, keyof O>;
|
|
182
163
|
state: O;
|
|
183
164
|
setState: React.Dispatch<React.SetStateAction<O>>;
|
|
184
|
-
touched: TouchedType
|
|
185
|
-
errors: ErrorsType
|
|
165
|
+
touched: TouchedType;
|
|
166
|
+
errors: ErrorsType;
|
|
186
167
|
/** Main object to bind form elements to the state. */
|
|
187
168
|
on: OnMethods<O>;
|
|
188
169
|
/** Array manipulation helpers. */
|
|
@@ -196,6 +177,6 @@ interface UseFormResponse<O extends StateType> {
|
|
|
196
177
|
resetTouched: (preservedKeys?: (keyof O)[]) => void;
|
|
197
178
|
}
|
|
198
179
|
|
|
199
|
-
declare function useForm<O extends StateType>(initialState: O, { rules, messages,
|
|
180
|
+
declare function useForm<O extends StateType>(initialState: O, { rules, messages, arrayIdentifiers }?: FormOptions<O>): UseFormResponse<O>;
|
|
200
181
|
|
|
201
|
-
export { type
|
|
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 };
|
package/dist/index.js
CHANGED
|
@@ -82,10 +82,10 @@ function getNestedValue(obj, path) {
|
|
|
82
82
|
return path.split(".").reduce((acc, key) => acc?.[key], obj);
|
|
83
83
|
}
|
|
84
84
|
function removeCompositeKeysByPrefix(map2, prefix) {
|
|
85
|
-
const result =
|
|
86
|
-
for (const
|
|
87
|
-
if (
|
|
88
|
-
result
|
|
85
|
+
const result = new Map(map2);
|
|
86
|
+
for (const key of map2.keys()) {
|
|
87
|
+
if (key.startsWith(prefix)) {
|
|
88
|
+
result.delete(key);
|
|
89
89
|
}
|
|
90
90
|
}
|
|
91
91
|
return result;
|
|
@@ -101,13 +101,6 @@ function setNestedValue(state, dotPath, value) {
|
|
|
101
101
|
current[keys[keys.length - 1]] = value;
|
|
102
102
|
return copy;
|
|
103
103
|
}
|
|
104
|
-
var allToValue = (obj, value) => Object.keys(obj).reduce(
|
|
105
|
-
(acc, key) => {
|
|
106
|
-
acc[key] = value;
|
|
107
|
-
return acc;
|
|
108
|
-
},
|
|
109
|
-
{}
|
|
110
|
-
);
|
|
111
104
|
var regex = {
|
|
112
105
|
email: /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/,
|
|
113
106
|
password: /^(?!.*\s)(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[~`!@#$%^&*()--+={}[\]|:;"'<>,.?/_₹]).{8,24}$/
|
|
@@ -226,21 +219,8 @@ function useValidate() {
|
|
|
226
219
|
}
|
|
227
220
|
|
|
228
221
|
// src/hooks/useForm.tsx
|
|
229
|
-
function useForm(initialState, {
|
|
230
|
-
|
|
231
|
-
messages,
|
|
232
|
-
arrayRules,
|
|
233
|
-
arrayMessages,
|
|
234
|
-
arrayIdentifiers
|
|
235
|
-
} = {}) {
|
|
236
|
-
const initial = {
|
|
237
|
-
touched: allToValue(initialState, false),
|
|
238
|
-
errors: allToValue(initialState, {
|
|
239
|
-
isInvalid: false,
|
|
240
|
-
errorMessage: ""
|
|
241
|
-
})
|
|
242
|
-
};
|
|
243
|
-
const [state, setState] = (0, import_react.useState)(initialState), [touched, setTouched] = (0, import_react.useState)(initial.touched), [errors2, setErrors] = (0, import_react.useState)(initial.errors), [itemTouched, setItemTouched] = (0, import_react.useState)({}), [itemErrors, setItemErrors] = (0, import_react.useState)({}), [nestedTouched, setNestedTouched] = (0, import_react.useState)({}), [nestedErrors, setNestedErrors] = (0, import_react.useState)({}), { performValidations } = useValidate();
|
|
222
|
+
function useForm(initialState, { rules, messages, arrayIdentifiers } = {}) {
|
|
223
|
+
const [state, setState] = (0, import_react.useState)(initialState), [touched, setTouched] = (0, import_react.useState)(/* @__PURE__ */ new Map()), [errors2, setErrors] = (0, import_react.useState)(/* @__PURE__ */ new Map()), { performValidations } = useValidate();
|
|
244
224
|
const indexMap = (0, import_react.useMemo)(() => {
|
|
245
225
|
const map2 = /* @__PURE__ */ new Map();
|
|
246
226
|
for (const key in state) {
|
|
@@ -266,39 +246,43 @@ function useForm(initialState, {
|
|
|
266
246
|
},
|
|
267
247
|
[indexMap]
|
|
268
248
|
);
|
|
269
|
-
const
|
|
270
|
-
(
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
249
|
+
const getRule = (path) => {
|
|
250
|
+
if (rules?.[path]) return rules[path];
|
|
251
|
+
const genericPath = path.replace(/\.\d+\./g, ".").replace(/\.\d+$/, "");
|
|
252
|
+
return rules?.[genericPath];
|
|
253
|
+
};
|
|
254
|
+
const getMessage = (path) => {
|
|
255
|
+
if (messages?.[path]) return messages[path];
|
|
256
|
+
const genericPath = path.replace(/\.\d+\./g, ".").replace(/\.\d+$/, "");
|
|
257
|
+
return messages?.[genericPath];
|
|
258
|
+
};
|
|
259
|
+
const validateInput = (compositeKey, value, ruleKey) => {
|
|
260
|
+
const ruleDef = getRule(ruleKey);
|
|
261
|
+
const rule = typeof ruleDef === "function" ? ruleDef(value, state) : ruleDef;
|
|
262
|
+
const message = getMessage(ruleKey);
|
|
263
|
+
const error = performValidations(value, rule, message);
|
|
264
|
+
setErrors((prev) => new Map(prev).set(compositeKey, error));
|
|
265
|
+
};
|
|
276
266
|
const getUXProps = (0, import_react.useCallback)(
|
|
277
|
-
(
|
|
278
|
-
const inputError = errors2
|
|
279
|
-
const isTouched = touched
|
|
267
|
+
(compositeKey) => {
|
|
268
|
+
const inputError = errors2.get(compositeKey);
|
|
269
|
+
const isTouched = touched.get(compositeKey);
|
|
280
270
|
return {
|
|
281
271
|
isInvalid: Boolean(isTouched && inputError?.isInvalid),
|
|
282
272
|
errorMessage: isTouched ? inputError?.errorMessage || "" : ""
|
|
283
273
|
};
|
|
284
274
|
},
|
|
285
|
-
[errors2, touched
|
|
275
|
+
[errors2, touched]
|
|
286
276
|
);
|
|
287
277
|
const onBlur = (id) => {
|
|
288
|
-
validateInput(id, state[id]);
|
|
289
|
-
if (touched
|
|
290
|
-
setTouched(
|
|
291
|
-
(prev) => handleNestedChange({
|
|
292
|
-
state: prev,
|
|
293
|
-
id,
|
|
294
|
-
value: true
|
|
295
|
-
})
|
|
296
|
-
);
|
|
278
|
+
validateInput(String(id), state[id], String(id));
|
|
279
|
+
if (touched.get(String(id))) return;
|
|
280
|
+
setTouched((prev) => new Map(prev).set(String(id), true));
|
|
297
281
|
}, onValueChange = ((...args) => {
|
|
298
282
|
if (args.length === 2) {
|
|
299
283
|
const [id, value] = args;
|
|
300
284
|
setState((prev) => handleNestedChange({ state: prev, id, value }));
|
|
301
|
-
validateInput(id, value);
|
|
285
|
+
validateInput(String(id), value, String(id));
|
|
302
286
|
return;
|
|
303
287
|
}
|
|
304
288
|
if (args.length === 3) {
|
|
@@ -344,7 +328,7 @@ function useForm(initialState, {
|
|
|
344
328
|
value: fixedValue
|
|
345
329
|
})
|
|
346
330
|
);
|
|
347
|
-
validateInput(id, fixedValue);
|
|
331
|
+
validateInput(String(id), fixedValue, String(id));
|
|
348
332
|
};
|
|
349
333
|
const getItemCompositeKey = (arrayKey, itemId, field) => `${arrayKey}.${itemId}.${field}`;
|
|
350
334
|
const getPrimitiveCompositeKey = (arrayKey, index) => `${arrayKey}.@${index}`;
|
|
@@ -352,27 +336,33 @@ function useForm(initialState, {
|
|
|
352
336
|
const validateItemInput = (arrayKey, itemId, field, value) => {
|
|
353
337
|
const index = getIndex(String(arrayKey), itemId);
|
|
354
338
|
if (index === void 0) return;
|
|
355
|
-
const arrayRuleDef = arrayRules?.[arrayKey]?.[field];
|
|
356
339
|
const item = state[arrayKey][index];
|
|
357
|
-
const fieldRules = typeof arrayRuleDef === "function" ? arrayRuleDef(item, index) : arrayRuleDef;
|
|
358
|
-
const fieldMessages = arrayMessages?.[arrayKey]?.[field];
|
|
359
340
|
const compositeKey = getItemCompositeKey(String(arrayKey), itemId, field);
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
}
|
|
341
|
+
let genericField = field.replace(/\.@\d+/, "");
|
|
342
|
+
if (genericField === "")
|
|
343
|
+
genericField = String(arrayKey);
|
|
344
|
+
else genericField = `${String(arrayKey)}.${genericField}`;
|
|
345
|
+
let effectivePath = `${String(arrayKey)}.${field}`;
|
|
346
|
+
if (field === "") effectivePath = String(arrayKey);
|
|
347
|
+
effectivePath = effectivePath.replace(/\.@\d+/g, "").replace(/\.@\d+$/, "");
|
|
348
|
+
const ruleDef = getRule(effectivePath);
|
|
349
|
+
const rule = typeof ruleDef === "function" ? ruleDef(value, state, item, index) : ruleDef;
|
|
350
|
+
const message = getMessage(effectivePath);
|
|
351
|
+
setErrors(
|
|
352
|
+
(prev) => new Map(prev).set(compositeKey, performValidations(value, rule, message))
|
|
353
|
+
);
|
|
364
354
|
};
|
|
365
355
|
const getItemUXProps = (0, import_react.useCallback)(
|
|
366
356
|
(arrayKey, itemId, field) => {
|
|
367
357
|
const compositeKey = getItemCompositeKey(arrayKey, itemId, field);
|
|
368
|
-
const inputError =
|
|
369
|
-
const isTouched =
|
|
358
|
+
const inputError = errors2.get(compositeKey);
|
|
359
|
+
const isTouched = touched.get(compositeKey);
|
|
370
360
|
return {
|
|
371
361
|
isInvalid: Boolean(isTouched && inputError?.isInvalid),
|
|
372
362
|
errorMessage: isTouched ? inputError?.errorMessage || "" : ""
|
|
373
363
|
};
|
|
374
364
|
},
|
|
375
|
-
[
|
|
365
|
+
[errors2, touched]
|
|
376
366
|
);
|
|
377
367
|
const onItemBlur = (arrayKey, itemId, field) => {
|
|
378
368
|
const index = getIndex(String(arrayKey), itemId);
|
|
@@ -381,8 +371,8 @@ function useForm(initialState, {
|
|
|
381
371
|
const value = getNestedValue(arr[index], field);
|
|
382
372
|
validateItemInput(arrayKey, itemId, field, value);
|
|
383
373
|
const compositeKey = getItemCompositeKey(String(arrayKey), itemId, field);
|
|
384
|
-
if (
|
|
385
|
-
|
|
374
|
+
if (touched.get(compositeKey)) return;
|
|
375
|
+
setTouched((prev) => new Map(prev).set(compositeKey, true));
|
|
386
376
|
};
|
|
387
377
|
const onItemValueChange = (arrayKey, itemId, field, value) => {
|
|
388
378
|
const index = getIndex(String(arrayKey), itemId);
|
|
@@ -411,17 +401,18 @@ function useForm(initialState, {
|
|
|
411
401
|
validateItemInput(arrayKey, itemId, field, fixedValue);
|
|
412
402
|
};
|
|
413
403
|
const validateNestedInput = (dotPath, value) => {
|
|
414
|
-
const
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
404
|
+
const ruleDef = getRule(dotPath);
|
|
405
|
+
const rule = typeof ruleDef === "function" ? ruleDef(value, state) : ruleDef;
|
|
406
|
+
const message = getMessage(dotPath);
|
|
407
|
+
setErrors(
|
|
408
|
+
(prev) => new Map(prev).set(dotPath, performValidations(value, rule, message))
|
|
409
|
+
);
|
|
419
410
|
};
|
|
420
411
|
const onNestedBlur = (dotPath) => {
|
|
421
412
|
const value = getNestedValue(state, dotPath);
|
|
422
413
|
validateNestedInput(dotPath, value);
|
|
423
|
-
if (
|
|
424
|
-
|
|
414
|
+
if (touched.get(dotPath)) return;
|
|
415
|
+
setTouched((prev) => new Map(prev).set(dotPath, true));
|
|
425
416
|
};
|
|
426
417
|
const onNestedValueChange = (dotPath, value) => {
|
|
427
418
|
setState((prev) => setNestedValue(prev, dotPath, value));
|
|
@@ -466,12 +457,8 @@ function useForm(initialState, {
|
|
|
466
457
|
...getItemUXProps(String(arrayKey2), `@${index2}`, ""),
|
|
467
458
|
id: compositeKey2,
|
|
468
459
|
onBlur: () => {
|
|
469
|
-
|
|
470
|
-
|
|
471
|
-
index2
|
|
472
|
-
);
|
|
473
|
-
if (itemTouched[compositeKey3]) return;
|
|
474
|
-
setItemTouched((prev) => ({ ...prev, [compositeKey3]: true }));
|
|
460
|
+
if (touched.get(compositeKey2)) return;
|
|
461
|
+
setTouched((prev) => new Map(prev).set(compositeKey2, true));
|
|
475
462
|
},
|
|
476
463
|
onValueChange: (v) => {
|
|
477
464
|
setState((prev) => {
|
|
@@ -479,6 +466,7 @@ function useForm(initialState, {
|
|
|
479
466
|
arr3[index2] = v;
|
|
480
467
|
return { ...prev, [arrayKey2]: arr3 };
|
|
481
468
|
});
|
|
469
|
+
validateItemInput(arrayKey2, `@${index2}`, "", v);
|
|
482
470
|
},
|
|
483
471
|
value: value2
|
|
484
472
|
};
|
|
@@ -499,8 +487,8 @@ function useForm(initialState, {
|
|
|
499
487
|
...getItemUXProps(String(parentKey), parentId, `${field2}.@${index2}`),
|
|
500
488
|
id: compositeKey2,
|
|
501
489
|
onBlur: () => {
|
|
502
|
-
if (
|
|
503
|
-
|
|
490
|
+
if (touched.get(compositeKey2)) return;
|
|
491
|
+
setTouched((prev) => new Map(prev).set(compositeKey2, true));
|
|
504
492
|
},
|
|
505
493
|
onValueChange: (v) => {
|
|
506
494
|
if (parentIndex === void 0) return;
|
|
@@ -512,6 +500,8 @@ function useForm(initialState, {
|
|
|
512
500
|
parentArr[parentIndex] = setNestedValue(item, field2, nestedArr2);
|
|
513
501
|
return { ...prev, [parentKey]: parentArr };
|
|
514
502
|
});
|
|
503
|
+
const fieldPath = `${field2}.@${index2}`;
|
|
504
|
+
validateItemInput(parentKey, parentId, fieldPath, v);
|
|
515
505
|
},
|
|
516
506
|
value: value2
|
|
517
507
|
};
|
|
@@ -566,8 +556,8 @@ function useForm(initialState, {
|
|
|
566
556
|
...getItemUXProps(String(arrayKey2), `@${index2}`, ""),
|
|
567
557
|
id: compositeKey2,
|
|
568
558
|
onBlur: () => {
|
|
569
|
-
if (
|
|
570
|
-
|
|
559
|
+
if (touched.get(compositeKey2)) return;
|
|
560
|
+
setTouched((prev) => new Map(prev).set(compositeKey2, true));
|
|
571
561
|
},
|
|
572
562
|
onSelectionChange: (v) => {
|
|
573
563
|
const fixedValue = typeof v === "string" || v === null ? v : Array.from(v)[0] || null;
|
|
@@ -576,6 +566,7 @@ function useForm(initialState, {
|
|
|
576
566
|
arr3[index2] = fixedValue;
|
|
577
567
|
return { ...prev, [arrayKey2]: arr3 };
|
|
578
568
|
});
|
|
569
|
+
validateItemInput(arrayKey2, `@${index2}`, "", fixedValue);
|
|
579
570
|
},
|
|
580
571
|
selectedKeys: value2 === null ? [] : [value2]
|
|
581
572
|
};
|
|
@@ -596,8 +587,8 @@ function useForm(initialState, {
|
|
|
596
587
|
...getItemUXProps(String(parentKey), parentId, `${field2}.@${index2}`),
|
|
597
588
|
id: compositeKey2,
|
|
598
589
|
onBlur: () => {
|
|
599
|
-
if (
|
|
600
|
-
|
|
590
|
+
if (touched.get(compositeKey2)) return;
|
|
591
|
+
setTouched((prev) => new Map(prev).set(compositeKey2, true));
|
|
601
592
|
},
|
|
602
593
|
onSelectionChange: (v) => {
|
|
603
594
|
if (parentIndex === void 0) return;
|
|
@@ -610,6 +601,8 @@ function useForm(initialState, {
|
|
|
610
601
|
parentArr[parentIndex] = setNestedValue(item, field2, nestedArr2);
|
|
611
602
|
return { ...prev, [parentKey]: parentArr };
|
|
612
603
|
});
|
|
604
|
+
const fieldPath = `${field2}.@${index2}`;
|
|
605
|
+
validateItemInput(parentKey, parentId, fieldPath, fixedValue);
|
|
613
606
|
},
|
|
614
607
|
selectedKeys: value2 === null ? [] : [value2]
|
|
615
608
|
};
|
|
@@ -659,15 +652,17 @@ function useForm(initialState, {
|
|
|
659
652
|
...getItemUXProps(String(arrayKey2), `@${index2}`, ""),
|
|
660
653
|
id: compositeKey2,
|
|
661
654
|
onBlur: () => {
|
|
662
|
-
if (
|
|
663
|
-
|
|
655
|
+
if (touched.get(compositeKey2)) return;
|
|
656
|
+
setTouched((prev) => new Map(prev).set(compositeKey2, true));
|
|
664
657
|
},
|
|
665
658
|
onSelectionChange: (v) => {
|
|
659
|
+
const fixedValue = typeof v === "string" || v === null ? v : String(v);
|
|
666
660
|
setState((prev) => {
|
|
667
661
|
const arr3 = [...prev[arrayKey2]];
|
|
668
|
-
arr3[index2] =
|
|
662
|
+
arr3[index2] = fixedValue;
|
|
669
663
|
return { ...prev, [arrayKey2]: arr3 };
|
|
670
664
|
});
|
|
665
|
+
validateItemInput(arrayKey2, `@${index2}`, "", fixedValue);
|
|
671
666
|
},
|
|
672
667
|
selectedKey: value2
|
|
673
668
|
};
|
|
@@ -688,19 +683,22 @@ function useForm(initialState, {
|
|
|
688
683
|
...getItemUXProps(String(parentKey), parentId, `${field2}.@${index2}`),
|
|
689
684
|
id: compositeKey2,
|
|
690
685
|
onBlur: () => {
|
|
691
|
-
if (
|
|
692
|
-
|
|
686
|
+
if (touched.get(compositeKey2)) return;
|
|
687
|
+
setTouched((prev) => new Map(prev).set(compositeKey2, true));
|
|
693
688
|
},
|
|
694
689
|
onSelectionChange: (v) => {
|
|
695
690
|
if (parentIndex === void 0) return;
|
|
691
|
+
const fixedValue = typeof v === "string" || v === null ? v : String(v);
|
|
696
692
|
setState((prev) => {
|
|
697
693
|
const parentArr = [...prev[parentKey]];
|
|
698
694
|
const item = { ...parentArr[parentIndex] };
|
|
699
695
|
const nestedArr2 = [...getNestedValue(item, field2) || []];
|
|
700
|
-
nestedArr2[index2] =
|
|
696
|
+
nestedArr2[index2] = fixedValue;
|
|
701
697
|
parentArr[parentIndex] = setNestedValue(item, field2, nestedArr2);
|
|
702
698
|
return { ...prev, [parentKey]: parentArr };
|
|
703
699
|
});
|
|
700
|
+
const fieldPath = `${field2}.@${index2}`;
|
|
701
|
+
validateItemInput(parentKey, parentId, fieldPath, fixedValue);
|
|
704
702
|
},
|
|
705
703
|
selectedKey: value2
|
|
706
704
|
};
|
|
@@ -751,8 +749,8 @@ function useForm(initialState, {
|
|
|
751
749
|
});
|
|
752
750
|
if (itemId !== void 0) {
|
|
753
751
|
const prefix = `${String(arrayKey)}.${itemId}.`;
|
|
754
|
-
|
|
755
|
-
|
|
752
|
+
setTouched((prev) => removeCompositeKeysByPrefix(prev, prefix));
|
|
753
|
+
setErrors((prev) => removeCompositeKeysByPrefix(prev, prefix));
|
|
756
754
|
}
|
|
757
755
|
},
|
|
758
756
|
removeById: (arrayKey, itemId) => {
|
|
@@ -762,8 +760,8 @@ function useForm(initialState, {
|
|
|
762
760
|
arr.splice(index, 1);
|
|
763
761
|
setState((prev) => ({ ...prev, [arrayKey]: arr }));
|
|
764
762
|
const prefix = `${String(arrayKey)}.${itemId}.`;
|
|
765
|
-
|
|
766
|
-
|
|
763
|
+
setTouched((prev) => removeCompositeKeysByPrefix(prev, prefix));
|
|
764
|
+
setErrors((prev) => removeCompositeKeysByPrefix(prev, prefix));
|
|
767
765
|
}
|
|
768
766
|
},
|
|
769
767
|
moveItem: (arrayKey, from, to) => {
|
|
@@ -803,35 +801,12 @@ function useForm(initialState, {
|
|
|
803
801
|
},
|
|
804
802
|
isDirty: JSON.stringify(state) !== JSON.stringify(initialState),
|
|
805
803
|
hasInvalidValues: () => {
|
|
806
|
-
|
|
807
|
-
|
|
808
|
-
(prev) => Object.keys(prev).reduce(
|
|
809
|
-
(acc, key) => ({ ...acc, [key]: true }),
|
|
810
|
-
{}
|
|
811
|
-
)
|
|
812
|
-
);
|
|
813
|
-
setNestedTouched(
|
|
814
|
-
(prev) => Object.keys(prev).reduce(
|
|
815
|
-
(acc, key) => ({ ...acc, [key]: true }),
|
|
816
|
-
{}
|
|
817
|
-
)
|
|
818
|
-
);
|
|
819
|
-
const topLevelInvalid = JSON.stringify(errors2).includes(":true");
|
|
820
|
-
const itemLevelInvalid = Object.values(itemErrors).some(
|
|
821
|
-
(e) => e?.isInvalid
|
|
822
|
-
);
|
|
823
|
-
const nestedLevelInvalid = Object.values(nestedErrors).some(
|
|
824
|
-
(e) => e?.isInvalid
|
|
825
|
-
);
|
|
826
|
-
return topLevelInvalid || itemLevelInvalid || nestedLevelInvalid;
|
|
804
|
+
const isInvalid = Array.from(errors2.values()).some((e) => e?.isInvalid);
|
|
805
|
+
return isInvalid;
|
|
827
806
|
},
|
|
828
807
|
resetForm: (preservedKeys) => {
|
|
829
|
-
setTouched(
|
|
830
|
-
setErrors(
|
|
831
|
-
setItemTouched({});
|
|
832
|
-
setItemErrors({});
|
|
833
|
-
setNestedTouched({});
|
|
834
|
-
setNestedErrors({});
|
|
808
|
+
setTouched(/* @__PURE__ */ new Map());
|
|
809
|
+
setErrors(/* @__PURE__ */ new Map());
|
|
835
810
|
setState(
|
|
836
811
|
(prev) => preservedKeys === void 0 ? initialState : preservedKeys.reduce(
|
|
837
812
|
(acc, key) => ({
|
|
@@ -843,16 +818,13 @@ function useForm(initialState, {
|
|
|
843
818
|
);
|
|
844
819
|
},
|
|
845
820
|
resetTouched: (preservedKeys) => {
|
|
846
|
-
setItemTouched({});
|
|
847
|
-
setNestedTouched({});
|
|
848
821
|
setTouched(
|
|
849
|
-
(prev) => preservedKeys === void 0 ?
|
|
850
|
-
(
|
|
851
|
-
|
|
852
|
-
|
|
853
|
-
|
|
854
|
-
|
|
855
|
-
)
|
|
822
|
+
(prev) => preservedKeys === void 0 ? /* @__PURE__ */ new Map() : preservedKeys.reduce((acc, key) => {
|
|
823
|
+
if (prev.has(String(key))) {
|
|
824
|
+
acc.set(String(key), prev.get(String(key)));
|
|
825
|
+
}
|
|
826
|
+
return acc;
|
|
827
|
+
}, /* @__PURE__ */ new Map())
|
|
856
828
|
);
|
|
857
829
|
}
|
|
858
830
|
};
|
package/dist/index.mjs
CHANGED
|
@@ -63,10 +63,10 @@ function getNestedValue(obj, path) {
|
|
|
63
63
|
return path.split(".").reduce((acc, key) => acc?.[key], obj);
|
|
64
64
|
}
|
|
65
65
|
function removeCompositeKeysByPrefix(map2, prefix) {
|
|
66
|
-
const result =
|
|
67
|
-
for (const
|
|
68
|
-
if (
|
|
69
|
-
result
|
|
66
|
+
const result = new Map(map2);
|
|
67
|
+
for (const key of map2.keys()) {
|
|
68
|
+
if (key.startsWith(prefix)) {
|
|
69
|
+
result.delete(key);
|
|
70
70
|
}
|
|
71
71
|
}
|
|
72
72
|
return result;
|
|
@@ -82,13 +82,6 @@ function setNestedValue(state, dotPath, value) {
|
|
|
82
82
|
current[keys[keys.length - 1]] = value;
|
|
83
83
|
return copy;
|
|
84
84
|
}
|
|
85
|
-
var allToValue = (obj, value) => Object.keys(obj).reduce(
|
|
86
|
-
(acc, key) => {
|
|
87
|
-
acc[key] = value;
|
|
88
|
-
return acc;
|
|
89
|
-
},
|
|
90
|
-
{}
|
|
91
|
-
);
|
|
92
85
|
var regex = {
|
|
93
86
|
email: /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/,
|
|
94
87
|
password: /^(?!.*\s)(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=.*[~`!@#$%^&*()--+={}[\]|:;"'<>,.?/_₹]).{8,24}$/
|
|
@@ -207,21 +200,8 @@ function useValidate() {
|
|
|
207
200
|
}
|
|
208
201
|
|
|
209
202
|
// src/hooks/useForm.tsx
|
|
210
|
-
function useForm(initialState, {
|
|
211
|
-
|
|
212
|
-
messages,
|
|
213
|
-
arrayRules,
|
|
214
|
-
arrayMessages,
|
|
215
|
-
arrayIdentifiers
|
|
216
|
-
} = {}) {
|
|
217
|
-
const initial = {
|
|
218
|
-
touched: allToValue(initialState, false),
|
|
219
|
-
errors: allToValue(initialState, {
|
|
220
|
-
isInvalid: false,
|
|
221
|
-
errorMessage: ""
|
|
222
|
-
})
|
|
223
|
-
};
|
|
224
|
-
const [state, setState] = useState(initialState), [touched, setTouched] = useState(initial.touched), [errors2, setErrors] = useState(initial.errors), [itemTouched, setItemTouched] = useState({}), [itemErrors, setItemErrors] = useState({}), [nestedTouched, setNestedTouched] = useState({}), [nestedErrors, setNestedErrors] = useState({}), { performValidations } = useValidate();
|
|
203
|
+
function useForm(initialState, { rules, messages, arrayIdentifiers } = {}) {
|
|
204
|
+
const [state, setState] = useState(initialState), [touched, setTouched] = useState(/* @__PURE__ */ new Map()), [errors2, setErrors] = useState(/* @__PURE__ */ new Map()), { performValidations } = useValidate();
|
|
225
205
|
const indexMap = useMemo(() => {
|
|
226
206
|
const map2 = /* @__PURE__ */ new Map();
|
|
227
207
|
for (const key in state) {
|
|
@@ -247,39 +227,43 @@ function useForm(initialState, {
|
|
|
247
227
|
},
|
|
248
228
|
[indexMap]
|
|
249
229
|
);
|
|
250
|
-
const
|
|
251
|
-
(
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
230
|
+
const getRule = (path) => {
|
|
231
|
+
if (rules?.[path]) return rules[path];
|
|
232
|
+
const genericPath = path.replace(/\.\d+\./g, ".").replace(/\.\d+$/, "");
|
|
233
|
+
return rules?.[genericPath];
|
|
234
|
+
};
|
|
235
|
+
const getMessage = (path) => {
|
|
236
|
+
if (messages?.[path]) return messages[path];
|
|
237
|
+
const genericPath = path.replace(/\.\d+\./g, ".").replace(/\.\d+$/, "");
|
|
238
|
+
return messages?.[genericPath];
|
|
239
|
+
};
|
|
240
|
+
const validateInput = (compositeKey, value, ruleKey) => {
|
|
241
|
+
const ruleDef = getRule(ruleKey);
|
|
242
|
+
const rule = typeof ruleDef === "function" ? ruleDef(value, state) : ruleDef;
|
|
243
|
+
const message = getMessage(ruleKey);
|
|
244
|
+
const error = performValidations(value, rule, message);
|
|
245
|
+
setErrors((prev) => new Map(prev).set(compositeKey, error));
|
|
246
|
+
};
|
|
257
247
|
const getUXProps = useCallback(
|
|
258
|
-
(
|
|
259
|
-
const inputError = errors2
|
|
260
|
-
const isTouched = touched
|
|
248
|
+
(compositeKey) => {
|
|
249
|
+
const inputError = errors2.get(compositeKey);
|
|
250
|
+
const isTouched = touched.get(compositeKey);
|
|
261
251
|
return {
|
|
262
252
|
isInvalid: Boolean(isTouched && inputError?.isInvalid),
|
|
263
253
|
errorMessage: isTouched ? inputError?.errorMessage || "" : ""
|
|
264
254
|
};
|
|
265
255
|
},
|
|
266
|
-
[errors2, touched
|
|
256
|
+
[errors2, touched]
|
|
267
257
|
);
|
|
268
258
|
const onBlur = (id) => {
|
|
269
|
-
validateInput(id, state[id]);
|
|
270
|
-
if (touched
|
|
271
|
-
setTouched(
|
|
272
|
-
(prev) => handleNestedChange({
|
|
273
|
-
state: prev,
|
|
274
|
-
id,
|
|
275
|
-
value: true
|
|
276
|
-
})
|
|
277
|
-
);
|
|
259
|
+
validateInput(String(id), state[id], String(id));
|
|
260
|
+
if (touched.get(String(id))) return;
|
|
261
|
+
setTouched((prev) => new Map(prev).set(String(id), true));
|
|
278
262
|
}, onValueChange = ((...args) => {
|
|
279
263
|
if (args.length === 2) {
|
|
280
264
|
const [id, value] = args;
|
|
281
265
|
setState((prev) => handleNestedChange({ state: prev, id, value }));
|
|
282
|
-
validateInput(id, value);
|
|
266
|
+
validateInput(String(id), value, String(id));
|
|
283
267
|
return;
|
|
284
268
|
}
|
|
285
269
|
if (args.length === 3) {
|
|
@@ -325,7 +309,7 @@ function useForm(initialState, {
|
|
|
325
309
|
value: fixedValue
|
|
326
310
|
})
|
|
327
311
|
);
|
|
328
|
-
validateInput(id, fixedValue);
|
|
312
|
+
validateInput(String(id), fixedValue, String(id));
|
|
329
313
|
};
|
|
330
314
|
const getItemCompositeKey = (arrayKey, itemId, field) => `${arrayKey}.${itemId}.${field}`;
|
|
331
315
|
const getPrimitiveCompositeKey = (arrayKey, index) => `${arrayKey}.@${index}`;
|
|
@@ -333,27 +317,33 @@ function useForm(initialState, {
|
|
|
333
317
|
const validateItemInput = (arrayKey, itemId, field, value) => {
|
|
334
318
|
const index = getIndex(String(arrayKey), itemId);
|
|
335
319
|
if (index === void 0) return;
|
|
336
|
-
const arrayRuleDef = arrayRules?.[arrayKey]?.[field];
|
|
337
320
|
const item = state[arrayKey][index];
|
|
338
|
-
const fieldRules = typeof arrayRuleDef === "function" ? arrayRuleDef(item, index) : arrayRuleDef;
|
|
339
|
-
const fieldMessages = arrayMessages?.[arrayKey]?.[field];
|
|
340
321
|
const compositeKey = getItemCompositeKey(String(arrayKey), itemId, field);
|
|
341
|
-
|
|
342
|
-
|
|
343
|
-
|
|
344
|
-
}
|
|
322
|
+
let genericField = field.replace(/\.@\d+/, "");
|
|
323
|
+
if (genericField === "")
|
|
324
|
+
genericField = String(arrayKey);
|
|
325
|
+
else genericField = `${String(arrayKey)}.${genericField}`;
|
|
326
|
+
let effectivePath = `${String(arrayKey)}.${field}`;
|
|
327
|
+
if (field === "") effectivePath = String(arrayKey);
|
|
328
|
+
effectivePath = effectivePath.replace(/\.@\d+/g, "").replace(/\.@\d+$/, "");
|
|
329
|
+
const ruleDef = getRule(effectivePath);
|
|
330
|
+
const rule = typeof ruleDef === "function" ? ruleDef(value, state, item, index) : ruleDef;
|
|
331
|
+
const message = getMessage(effectivePath);
|
|
332
|
+
setErrors(
|
|
333
|
+
(prev) => new Map(prev).set(compositeKey, performValidations(value, rule, message))
|
|
334
|
+
);
|
|
345
335
|
};
|
|
346
336
|
const getItemUXProps = useCallback(
|
|
347
337
|
(arrayKey, itemId, field) => {
|
|
348
338
|
const compositeKey = getItemCompositeKey(arrayKey, itemId, field);
|
|
349
|
-
const inputError =
|
|
350
|
-
const isTouched =
|
|
339
|
+
const inputError = errors2.get(compositeKey);
|
|
340
|
+
const isTouched = touched.get(compositeKey);
|
|
351
341
|
return {
|
|
352
342
|
isInvalid: Boolean(isTouched && inputError?.isInvalid),
|
|
353
343
|
errorMessage: isTouched ? inputError?.errorMessage || "" : ""
|
|
354
344
|
};
|
|
355
345
|
},
|
|
356
|
-
[
|
|
346
|
+
[errors2, touched]
|
|
357
347
|
);
|
|
358
348
|
const onItemBlur = (arrayKey, itemId, field) => {
|
|
359
349
|
const index = getIndex(String(arrayKey), itemId);
|
|
@@ -362,8 +352,8 @@ function useForm(initialState, {
|
|
|
362
352
|
const value = getNestedValue(arr[index], field);
|
|
363
353
|
validateItemInput(arrayKey, itemId, field, value);
|
|
364
354
|
const compositeKey = getItemCompositeKey(String(arrayKey), itemId, field);
|
|
365
|
-
if (
|
|
366
|
-
|
|
355
|
+
if (touched.get(compositeKey)) return;
|
|
356
|
+
setTouched((prev) => new Map(prev).set(compositeKey, true));
|
|
367
357
|
};
|
|
368
358
|
const onItemValueChange = (arrayKey, itemId, field, value) => {
|
|
369
359
|
const index = getIndex(String(arrayKey), itemId);
|
|
@@ -392,17 +382,18 @@ function useForm(initialState, {
|
|
|
392
382
|
validateItemInput(arrayKey, itemId, field, fixedValue);
|
|
393
383
|
};
|
|
394
384
|
const validateNestedInput = (dotPath, value) => {
|
|
395
|
-
const
|
|
396
|
-
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
385
|
+
const ruleDef = getRule(dotPath);
|
|
386
|
+
const rule = typeof ruleDef === "function" ? ruleDef(value, state) : ruleDef;
|
|
387
|
+
const message = getMessage(dotPath);
|
|
388
|
+
setErrors(
|
|
389
|
+
(prev) => new Map(prev).set(dotPath, performValidations(value, rule, message))
|
|
390
|
+
);
|
|
400
391
|
};
|
|
401
392
|
const onNestedBlur = (dotPath) => {
|
|
402
393
|
const value = getNestedValue(state, dotPath);
|
|
403
394
|
validateNestedInput(dotPath, value);
|
|
404
|
-
if (
|
|
405
|
-
|
|
395
|
+
if (touched.get(dotPath)) return;
|
|
396
|
+
setTouched((prev) => new Map(prev).set(dotPath, true));
|
|
406
397
|
};
|
|
407
398
|
const onNestedValueChange = (dotPath, value) => {
|
|
408
399
|
setState((prev) => setNestedValue(prev, dotPath, value));
|
|
@@ -447,12 +438,8 @@ function useForm(initialState, {
|
|
|
447
438
|
...getItemUXProps(String(arrayKey2), `@${index2}`, ""),
|
|
448
439
|
id: compositeKey2,
|
|
449
440
|
onBlur: () => {
|
|
450
|
-
|
|
451
|
-
|
|
452
|
-
index2
|
|
453
|
-
);
|
|
454
|
-
if (itemTouched[compositeKey3]) return;
|
|
455
|
-
setItemTouched((prev) => ({ ...prev, [compositeKey3]: true }));
|
|
441
|
+
if (touched.get(compositeKey2)) return;
|
|
442
|
+
setTouched((prev) => new Map(prev).set(compositeKey2, true));
|
|
456
443
|
},
|
|
457
444
|
onValueChange: (v) => {
|
|
458
445
|
setState((prev) => {
|
|
@@ -460,6 +447,7 @@ function useForm(initialState, {
|
|
|
460
447
|
arr3[index2] = v;
|
|
461
448
|
return { ...prev, [arrayKey2]: arr3 };
|
|
462
449
|
});
|
|
450
|
+
validateItemInput(arrayKey2, `@${index2}`, "", v);
|
|
463
451
|
},
|
|
464
452
|
value: value2
|
|
465
453
|
};
|
|
@@ -480,8 +468,8 @@ function useForm(initialState, {
|
|
|
480
468
|
...getItemUXProps(String(parentKey), parentId, `${field2}.@${index2}`),
|
|
481
469
|
id: compositeKey2,
|
|
482
470
|
onBlur: () => {
|
|
483
|
-
if (
|
|
484
|
-
|
|
471
|
+
if (touched.get(compositeKey2)) return;
|
|
472
|
+
setTouched((prev) => new Map(prev).set(compositeKey2, true));
|
|
485
473
|
},
|
|
486
474
|
onValueChange: (v) => {
|
|
487
475
|
if (parentIndex === void 0) return;
|
|
@@ -493,6 +481,8 @@ function useForm(initialState, {
|
|
|
493
481
|
parentArr[parentIndex] = setNestedValue(item, field2, nestedArr2);
|
|
494
482
|
return { ...prev, [parentKey]: parentArr };
|
|
495
483
|
});
|
|
484
|
+
const fieldPath = `${field2}.@${index2}`;
|
|
485
|
+
validateItemInput(parentKey, parentId, fieldPath, v);
|
|
496
486
|
},
|
|
497
487
|
value: value2
|
|
498
488
|
};
|
|
@@ -547,8 +537,8 @@ function useForm(initialState, {
|
|
|
547
537
|
...getItemUXProps(String(arrayKey2), `@${index2}`, ""),
|
|
548
538
|
id: compositeKey2,
|
|
549
539
|
onBlur: () => {
|
|
550
|
-
if (
|
|
551
|
-
|
|
540
|
+
if (touched.get(compositeKey2)) return;
|
|
541
|
+
setTouched((prev) => new Map(prev).set(compositeKey2, true));
|
|
552
542
|
},
|
|
553
543
|
onSelectionChange: (v) => {
|
|
554
544
|
const fixedValue = typeof v === "string" || v === null ? v : Array.from(v)[0] || null;
|
|
@@ -557,6 +547,7 @@ function useForm(initialState, {
|
|
|
557
547
|
arr3[index2] = fixedValue;
|
|
558
548
|
return { ...prev, [arrayKey2]: arr3 };
|
|
559
549
|
});
|
|
550
|
+
validateItemInput(arrayKey2, `@${index2}`, "", fixedValue);
|
|
560
551
|
},
|
|
561
552
|
selectedKeys: value2 === null ? [] : [value2]
|
|
562
553
|
};
|
|
@@ -577,8 +568,8 @@ function useForm(initialState, {
|
|
|
577
568
|
...getItemUXProps(String(parentKey), parentId, `${field2}.@${index2}`),
|
|
578
569
|
id: compositeKey2,
|
|
579
570
|
onBlur: () => {
|
|
580
|
-
if (
|
|
581
|
-
|
|
571
|
+
if (touched.get(compositeKey2)) return;
|
|
572
|
+
setTouched((prev) => new Map(prev).set(compositeKey2, true));
|
|
582
573
|
},
|
|
583
574
|
onSelectionChange: (v) => {
|
|
584
575
|
if (parentIndex === void 0) return;
|
|
@@ -591,6 +582,8 @@ function useForm(initialState, {
|
|
|
591
582
|
parentArr[parentIndex] = setNestedValue(item, field2, nestedArr2);
|
|
592
583
|
return { ...prev, [parentKey]: parentArr };
|
|
593
584
|
});
|
|
585
|
+
const fieldPath = `${field2}.@${index2}`;
|
|
586
|
+
validateItemInput(parentKey, parentId, fieldPath, fixedValue);
|
|
594
587
|
},
|
|
595
588
|
selectedKeys: value2 === null ? [] : [value2]
|
|
596
589
|
};
|
|
@@ -640,15 +633,17 @@ function useForm(initialState, {
|
|
|
640
633
|
...getItemUXProps(String(arrayKey2), `@${index2}`, ""),
|
|
641
634
|
id: compositeKey2,
|
|
642
635
|
onBlur: () => {
|
|
643
|
-
if (
|
|
644
|
-
|
|
636
|
+
if (touched.get(compositeKey2)) return;
|
|
637
|
+
setTouched((prev) => new Map(prev).set(compositeKey2, true));
|
|
645
638
|
},
|
|
646
639
|
onSelectionChange: (v) => {
|
|
640
|
+
const fixedValue = typeof v === "string" || v === null ? v : String(v);
|
|
647
641
|
setState((prev) => {
|
|
648
642
|
const arr3 = [...prev[arrayKey2]];
|
|
649
|
-
arr3[index2] =
|
|
643
|
+
arr3[index2] = fixedValue;
|
|
650
644
|
return { ...prev, [arrayKey2]: arr3 };
|
|
651
645
|
});
|
|
646
|
+
validateItemInput(arrayKey2, `@${index2}`, "", fixedValue);
|
|
652
647
|
},
|
|
653
648
|
selectedKey: value2
|
|
654
649
|
};
|
|
@@ -669,19 +664,22 @@ function useForm(initialState, {
|
|
|
669
664
|
...getItemUXProps(String(parentKey), parentId, `${field2}.@${index2}`),
|
|
670
665
|
id: compositeKey2,
|
|
671
666
|
onBlur: () => {
|
|
672
|
-
if (
|
|
673
|
-
|
|
667
|
+
if (touched.get(compositeKey2)) return;
|
|
668
|
+
setTouched((prev) => new Map(prev).set(compositeKey2, true));
|
|
674
669
|
},
|
|
675
670
|
onSelectionChange: (v) => {
|
|
676
671
|
if (parentIndex === void 0) return;
|
|
672
|
+
const fixedValue = typeof v === "string" || v === null ? v : String(v);
|
|
677
673
|
setState((prev) => {
|
|
678
674
|
const parentArr = [...prev[parentKey]];
|
|
679
675
|
const item = { ...parentArr[parentIndex] };
|
|
680
676
|
const nestedArr2 = [...getNestedValue(item, field2) || []];
|
|
681
|
-
nestedArr2[index2] =
|
|
677
|
+
nestedArr2[index2] = fixedValue;
|
|
682
678
|
parentArr[parentIndex] = setNestedValue(item, field2, nestedArr2);
|
|
683
679
|
return { ...prev, [parentKey]: parentArr };
|
|
684
680
|
});
|
|
681
|
+
const fieldPath = `${field2}.@${index2}`;
|
|
682
|
+
validateItemInput(parentKey, parentId, fieldPath, fixedValue);
|
|
685
683
|
},
|
|
686
684
|
selectedKey: value2
|
|
687
685
|
};
|
|
@@ -732,8 +730,8 @@ function useForm(initialState, {
|
|
|
732
730
|
});
|
|
733
731
|
if (itemId !== void 0) {
|
|
734
732
|
const prefix = `${String(arrayKey)}.${itemId}.`;
|
|
735
|
-
|
|
736
|
-
|
|
733
|
+
setTouched((prev) => removeCompositeKeysByPrefix(prev, prefix));
|
|
734
|
+
setErrors((prev) => removeCompositeKeysByPrefix(prev, prefix));
|
|
737
735
|
}
|
|
738
736
|
},
|
|
739
737
|
removeById: (arrayKey, itemId) => {
|
|
@@ -743,8 +741,8 @@ function useForm(initialState, {
|
|
|
743
741
|
arr.splice(index, 1);
|
|
744
742
|
setState((prev) => ({ ...prev, [arrayKey]: arr }));
|
|
745
743
|
const prefix = `${String(arrayKey)}.${itemId}.`;
|
|
746
|
-
|
|
747
|
-
|
|
744
|
+
setTouched((prev) => removeCompositeKeysByPrefix(prev, prefix));
|
|
745
|
+
setErrors((prev) => removeCompositeKeysByPrefix(prev, prefix));
|
|
748
746
|
}
|
|
749
747
|
},
|
|
750
748
|
moveItem: (arrayKey, from, to) => {
|
|
@@ -784,35 +782,12 @@ function useForm(initialState, {
|
|
|
784
782
|
},
|
|
785
783
|
isDirty: JSON.stringify(state) !== JSON.stringify(initialState),
|
|
786
784
|
hasInvalidValues: () => {
|
|
787
|
-
|
|
788
|
-
|
|
789
|
-
(prev) => Object.keys(prev).reduce(
|
|
790
|
-
(acc, key) => ({ ...acc, [key]: true }),
|
|
791
|
-
{}
|
|
792
|
-
)
|
|
793
|
-
);
|
|
794
|
-
setNestedTouched(
|
|
795
|
-
(prev) => Object.keys(prev).reduce(
|
|
796
|
-
(acc, key) => ({ ...acc, [key]: true }),
|
|
797
|
-
{}
|
|
798
|
-
)
|
|
799
|
-
);
|
|
800
|
-
const topLevelInvalid = JSON.stringify(errors2).includes(":true");
|
|
801
|
-
const itemLevelInvalid = Object.values(itemErrors).some(
|
|
802
|
-
(e) => e?.isInvalid
|
|
803
|
-
);
|
|
804
|
-
const nestedLevelInvalid = Object.values(nestedErrors).some(
|
|
805
|
-
(e) => e?.isInvalid
|
|
806
|
-
);
|
|
807
|
-
return topLevelInvalid || itemLevelInvalid || nestedLevelInvalid;
|
|
785
|
+
const isInvalid = Array.from(errors2.values()).some((e) => e?.isInvalid);
|
|
786
|
+
return isInvalid;
|
|
808
787
|
},
|
|
809
788
|
resetForm: (preservedKeys) => {
|
|
810
|
-
setTouched(
|
|
811
|
-
setErrors(
|
|
812
|
-
setItemTouched({});
|
|
813
|
-
setItemErrors({});
|
|
814
|
-
setNestedTouched({});
|
|
815
|
-
setNestedErrors({});
|
|
789
|
+
setTouched(/* @__PURE__ */ new Map());
|
|
790
|
+
setErrors(/* @__PURE__ */ new Map());
|
|
816
791
|
setState(
|
|
817
792
|
(prev) => preservedKeys === void 0 ? initialState : preservedKeys.reduce(
|
|
818
793
|
(acc, key) => ({
|
|
@@ -824,16 +799,13 @@ function useForm(initialState, {
|
|
|
824
799
|
);
|
|
825
800
|
},
|
|
826
801
|
resetTouched: (preservedKeys) => {
|
|
827
|
-
setItemTouched({});
|
|
828
|
-
setNestedTouched({});
|
|
829
802
|
setTouched(
|
|
830
|
-
(prev) => preservedKeys === void 0 ?
|
|
831
|
-
(
|
|
832
|
-
|
|
833
|
-
|
|
834
|
-
|
|
835
|
-
|
|
836
|
-
)
|
|
803
|
+
(prev) => preservedKeys === void 0 ? /* @__PURE__ */ new Map() : preservedKeys.reduce((acc, key) => {
|
|
804
|
+
if (prev.has(String(key))) {
|
|
805
|
+
acc.set(String(key), prev.get(String(key)));
|
|
806
|
+
}
|
|
807
|
+
return acc;
|
|
808
|
+
}, /* @__PURE__ */ new Map())
|
|
837
809
|
);
|
|
838
810
|
}
|
|
839
811
|
};
|