solid-hook-form 2.3.0 → 2.5.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/main.d.ts CHANGED
@@ -29,6 +29,11 @@ type FieldError = {
29
29
  message?: Message;
30
30
  };
31
31
  type FieldErrors<F extends FormValues = FormValues> = Partial<Record<Path<F>, FieldError>>;
32
+ type SetErrorOptions = {
33
+ shouldFocus?: boolean;
34
+ };
35
+ type SetError<F extends FormValues = FormValues> = (name: Path<F>, error: FieldError, options?: SetErrorOptions) => void;
36
+ type ClearErrors<F extends FormValues = FormValues> = (name?: Path<F> | Path<F>[]) => void;
32
37
 
33
38
  type Ref = HTMLElement | null;
34
39
  type RegisterReturn<F extends FormValues> = {
@@ -99,7 +104,8 @@ type SubmitErrorHandler<F extends FormValues> = (errors: FieldErrors<F>) => void
99
104
  type HandleSubmit<F extends FormValues> = (onSubmit: SubmitHandler<F>, onError?: SubmitErrorHandler<F>) => (event: SubmitEvent) => void;
100
105
  type CreateFormArg<F extends FormValues> = {
101
106
  defaultValues: F;
102
- mode?: "onChange" | "onSubmit" | "onBlur";
107
+ mode?: "onChange" | "onSubmit" | "onBlur" | "onTouched";
108
+ shouldFocusError?: boolean;
103
109
  resolver?: Resolver<F>;
104
110
  };
105
111
  type CreateFormReturn<F extends FormValues = FormValues> = {
@@ -120,6 +126,8 @@ type CreateFormReturn<F extends FormValues = FormValues> = {
120
126
  setValue: SetValue<F>;
121
127
  handleSubmit: HandleSubmit<F>;
122
128
  reset: Reset<F>;
129
+ setError: SetError<F>;
130
+ clearErrors: ClearErrors<F>;
123
131
  trigger: Trigger<F>;
124
132
  };
125
133
  type CreateForm = <F extends FormValues>(arg: CreateFormArg<F>) => CreateFormReturn<F>;
package/dist/main.js CHANGED
@@ -1,5 +1,5 @@
1
1
  import { createContext, createSignal, createMemo, useContext } from 'solid-js';
2
- import { createStore, reconcile, produce } from 'solid-js/store';
2
+ import { createStore, produce, reconcile } from 'solid-js/store';
3
3
  import { memo, createComponent } from 'solid-js/web';
4
4
 
5
5
  // src/create_form.ts
@@ -88,7 +88,7 @@ var createErrors = () => {
88
88
  })
89
89
  );
90
90
  };
91
- const removeError = (name) => {
91
+ const clearError = (name) => {
92
92
  setErrors(
93
93
  produce((prevState) => {
94
94
  delete prevState[name];
@@ -101,12 +101,30 @@ var createErrors = () => {
101
101
  }
102
102
  setErrors(reconcile({}));
103
103
  };
104
+ const clearErrors = (name) => {
105
+ if (!name) {
106
+ resetErrors();
107
+ return;
108
+ }
109
+ if (typeof name === "string") {
110
+ clearError(name);
111
+ return;
112
+ }
113
+ setErrors(
114
+ produce((prevState) => {
115
+ name.forEach((name2) => {
116
+ delete prevState[name2];
117
+ });
118
+ })
119
+ );
120
+ };
104
121
  return {
105
122
  errors,
106
123
  appendError,
107
- removeError,
124
+ clearError,
108
125
  resetErrors,
109
- getError
126
+ getError,
127
+ clearErrors
110
128
  };
111
129
  };
112
130
 
@@ -119,10 +137,14 @@ var createFields = () => {
119
137
  const setField = (name, element) => {
120
138
  fields[name] = element;
121
139
  };
140
+ const focusField = (name) => {
141
+ getField(name)?.focus();
142
+ };
122
143
  return {
123
144
  fields,
124
145
  getField,
125
- setField
146
+ setField,
147
+ focusField
126
148
  };
127
149
  };
128
150
 
@@ -293,26 +315,36 @@ var getResolverFields = (fields) => {
293
315
 
294
316
  // src/create_form.ts
295
317
  var createForm = (arg) => {
296
- const { defaultValues, mode = "onChange", resolver } = arg;
297
- const { fields, getField, setField } = createFields();
318
+ const { defaultValues, mode = "onChange", shouldFocusError = true, resolver } = arg;
319
+ const { fields, getField, setField, focusField } = createFields();
298
320
  const { rules, addRule, getRule } = createRules();
299
321
  const [values, setValues] = createSignal(structuredClone(defaultValues));
300
- const { errors, appendError, removeError, resetErrors, getError } = createErrors();
322
+ const { errors, appendError, clearError, resetErrors, clearErrors, getError } = createErrors();
301
323
  const { touchedFields, addTouched, resetTouched } = createTouchedFields();
302
324
  const { dirtyFields, isDirty, checkDirty, resetDirty } = createDirtyFields(defaultValues);
303
325
  const { isSubmitted, submitCount, logSubmit, resetSubmit } = createSubmit();
304
326
  const isValid = createMemo(() => {
305
327
  return !Object.keys(errors).length;
306
328
  });
307
- const setFieldError = (name, error) => {
329
+ const isTouched = (name) => {
330
+ return get(touchedFields(), name);
331
+ };
332
+ const setError = (name, error, options) => {
308
333
  const field = getField(name);
309
334
  if (field) {
310
335
  error.ref = field;
311
336
  }
312
337
  appendError(name, error);
338
+ if (options?.shouldFocus) {
339
+ focusField(name);
340
+ }
313
341
  };
314
- const clearFieldError = (name) => {
315
- removeError(name);
342
+ const renderError = (name, error) => {
343
+ if (error) {
344
+ setError(name, error);
345
+ } else {
346
+ clearError(name);
347
+ }
316
348
  };
317
349
  const runSchema = async (names) => {
318
350
  if (!resolver) {
@@ -324,25 +356,17 @@ var createForm = (arg) => {
324
356
  });
325
357
  for (const name of names) {
326
358
  const error = get(result.errors, name);
327
- if (error) {
328
- setFieldError(name, error);
329
- } else {
330
- clearFieldError(name);
331
- }
359
+ renderError(name, error);
332
360
  }
333
361
  };
334
- const validateField = (name) => {
362
+ const validateField = async (name) => {
335
363
  if (resolver) {
336
- runSchema([name]);
364
+ await runSchema([name]);
337
365
  return;
338
366
  }
339
367
  const rule = getRule(name);
340
368
  const error = validate(values(), name, rule);
341
- if (error) {
342
- setFieldError(name, error);
343
- } else {
344
- clearFieldError(name);
345
- }
369
+ renderError(name, error);
346
370
  };
347
371
  const validateAllFields = async () => {
348
372
  if (resolver) {
@@ -371,7 +395,6 @@ var createForm = (arg) => {
371
395
  set(newState, name, value);
372
396
  return newState;
373
397
  });
374
- validateField(name);
375
398
  checkDirty(name, value);
376
399
  };
377
400
  const register = (name, options = {}) => {
@@ -379,18 +402,21 @@ var createForm = (arg) => {
379
402
  return {
380
403
  name,
381
404
  onInput(event) {
382
- if (mode === "onChange") {
383
- onFieldChange(event, name);
405
+ onFieldChange(event, name);
406
+ if (mode === "onChange" || mode === "onTouched" && isTouched(name)) {
407
+ validateField(name);
384
408
  }
385
409
  },
386
410
  onChange(event) {
387
- if (mode === "onChange") {
388
- onFieldChange(event, name);
411
+ onFieldChange(event, name);
412
+ if (mode === "onChange" || mode === "onTouched" && isTouched(name)) {
413
+ validateField(name);
389
414
  }
390
415
  },
391
416
  onBlur(event) {
392
- if (mode === "onBlur") {
393
- onFieldChange(event, name);
417
+ onFieldChange(event, name);
418
+ if (mode === "onBlur" || mode === "onTouched" && !isTouched(name)) {
419
+ validateField(name);
394
420
  }
395
421
  addTouched(name);
396
422
  },
@@ -443,7 +469,9 @@ var createForm = (arg) => {
443
469
  return;
444
470
  }
445
471
  onError?.(errors);
446
- focusFirstError();
472
+ if (shouldFocusError) {
473
+ focusFirstError();
474
+ }
447
475
  };
448
476
  };
449
477
  const reset = (values2, options = {}) => {
@@ -489,6 +517,8 @@ var createForm = (arg) => {
489
517
  setValue,
490
518
  handleSubmit,
491
519
  reset,
520
+ setError,
521
+ clearErrors,
492
522
  trigger
493
523
  };
494
524
  };
package/dist/main.jsx CHANGED
@@ -91,7 +91,7 @@ var createErrors = () => {
91
91
  })
92
92
  );
93
93
  };
94
- const removeError = (name) => {
94
+ const clearError = (name) => {
95
95
  setErrors(
96
96
  produce((prevState) => {
97
97
  delete prevState[name];
@@ -104,12 +104,30 @@ var createErrors = () => {
104
104
  }
105
105
  setErrors(reconcile({}));
106
106
  };
107
+ const clearErrors = (name) => {
108
+ if (!name) {
109
+ resetErrors();
110
+ return;
111
+ }
112
+ if (typeof name === "string") {
113
+ clearError(name);
114
+ return;
115
+ }
116
+ setErrors(
117
+ produce((prevState) => {
118
+ name.forEach((name2) => {
119
+ delete prevState[name2];
120
+ });
121
+ })
122
+ );
123
+ };
107
124
  return {
108
125
  errors,
109
126
  appendError,
110
- removeError,
127
+ clearError,
111
128
  resetErrors,
112
- getError
129
+ getError,
130
+ clearErrors
113
131
  };
114
132
  };
115
133
 
@@ -122,10 +140,14 @@ var createFields = () => {
122
140
  const setField = (name, element) => {
123
141
  fields[name] = element;
124
142
  };
143
+ const focusField = (name) => {
144
+ getField(name)?.focus();
145
+ };
125
146
  return {
126
147
  fields,
127
148
  getField,
128
- setField
149
+ setField,
150
+ focusField
129
151
  };
130
152
  };
131
153
 
@@ -302,26 +324,36 @@ var getResolverFields = (fields) => {
302
324
 
303
325
  // src/create_form.ts
304
326
  var createForm = (arg) => {
305
- const { defaultValues, mode = "onChange", resolver } = arg;
306
- const { fields, getField, setField } = createFields();
327
+ const { defaultValues, mode = "onChange", shouldFocusError = true, resolver } = arg;
328
+ const { fields, getField, setField, focusField } = createFields();
307
329
  const { rules, addRule, getRule } = createRules();
308
330
  const [values, setValues] = createSignal4(structuredClone(defaultValues));
309
- const { errors, appendError, removeError, resetErrors, getError } = createErrors();
331
+ const { errors, appendError, clearError, resetErrors, clearErrors, getError } = createErrors();
310
332
  const { touchedFields, addTouched, resetTouched } = createTouchedFields();
311
333
  const { dirtyFields, isDirty, checkDirty, resetDirty } = createDirtyFields(defaultValues);
312
334
  const { isSubmitted, submitCount, logSubmit, resetSubmit } = createSubmit();
313
335
  const isValid = createMemo2(() => {
314
336
  return !Object.keys(errors).length;
315
337
  });
316
- const setFieldError = (name, error) => {
338
+ const isTouched = (name) => {
339
+ return get(touchedFields(), name);
340
+ };
341
+ const setError = (name, error, options) => {
317
342
  const field = getField(name);
318
343
  if (field) {
319
344
  error.ref = field;
320
345
  }
321
346
  appendError(name, error);
347
+ if (options?.shouldFocus) {
348
+ focusField(name);
349
+ }
322
350
  };
323
- const clearFieldError = (name) => {
324
- removeError(name);
351
+ const renderError = (name, error) => {
352
+ if (error) {
353
+ setError(name, error);
354
+ } else {
355
+ clearError(name);
356
+ }
325
357
  };
326
358
  const runSchema = async (names) => {
327
359
  if (!resolver) {
@@ -333,25 +365,17 @@ var createForm = (arg) => {
333
365
  });
334
366
  for (const name of names) {
335
367
  const error = get(result.errors, name);
336
- if (error) {
337
- setFieldError(name, error);
338
- } else {
339
- clearFieldError(name);
340
- }
368
+ renderError(name, error);
341
369
  }
342
370
  };
343
- const validateField = (name) => {
371
+ const validateField = async (name) => {
344
372
  if (resolver) {
345
- runSchema([name]);
373
+ await runSchema([name]);
346
374
  return;
347
375
  }
348
376
  const rule = getRule(name);
349
377
  const error = validate(values(), name, rule);
350
- if (error) {
351
- setFieldError(name, error);
352
- } else {
353
- clearFieldError(name);
354
- }
378
+ renderError(name, error);
355
379
  };
356
380
  const validateAllFields = async () => {
357
381
  if (resolver) {
@@ -380,7 +404,6 @@ var createForm = (arg) => {
380
404
  set(newState, name, value);
381
405
  return newState;
382
406
  });
383
- validateField(name);
384
407
  checkDirty(name, value);
385
408
  };
386
409
  const register = (name, options = {}) => {
@@ -388,18 +411,21 @@ var createForm = (arg) => {
388
411
  return {
389
412
  name,
390
413
  onInput(event) {
391
- if (mode === "onChange") {
392
- onFieldChange(event, name);
414
+ onFieldChange(event, name);
415
+ if (mode === "onChange" || mode === "onTouched" && isTouched(name)) {
416
+ validateField(name);
393
417
  }
394
418
  },
395
419
  onChange(event) {
396
- if (mode === "onChange") {
397
- onFieldChange(event, name);
420
+ onFieldChange(event, name);
421
+ if (mode === "onChange" || mode === "onTouched" && isTouched(name)) {
422
+ validateField(name);
398
423
  }
399
424
  },
400
425
  onBlur(event) {
401
- if (mode === "onBlur") {
402
- onFieldChange(event, name);
426
+ onFieldChange(event, name);
427
+ if (mode === "onBlur" || mode === "onTouched" && !isTouched(name)) {
428
+ validateField(name);
403
429
  }
404
430
  addTouched(name);
405
431
  },
@@ -452,7 +478,9 @@ var createForm = (arg) => {
452
478
  return;
453
479
  }
454
480
  onError?.(errors);
455
- focusFirstError();
481
+ if (shouldFocusError) {
482
+ focusFirstError();
483
+ }
456
484
  };
457
485
  };
458
486
  const reset = (values2, options = {}) => {
@@ -498,6 +526,8 @@ var createForm = (arg) => {
498
526
  setValue,
499
527
  handleSubmit,
500
528
  reset,
529
+ setError,
530
+ clearErrors,
501
531
  trigger
502
532
  };
503
533
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "solid-hook-form",
3
- "version": "2.3.0",
3
+ "version": "2.5.0",
4
4
  "type": "module",
5
5
  "main": "./dist/main.js",
6
6
  "module": "./dist/main.js",