@rolster/react-forms 19.0.0 → 19.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/cjs/index.js CHANGED
@@ -10,8 +10,8 @@ var react = require('react');
10
10
  class RolsterArrayControl {
11
11
  constructor(options) {
12
12
  this.uuid = options.uuid;
13
+ this.defaultValue = options.defaultValue;
13
14
  this.value = options.value;
14
- this.initialValue = options.initialValue;
15
15
  this.focused = !!options.focused;
16
16
  this.unfocused = !this.focused;
17
17
  this.touched = !!options.touched;
@@ -42,17 +42,20 @@ class RolsterArrayControl {
42
42
  touch() {
43
43
  this.untouched && this.refresh('touched', { touched: true });
44
44
  }
45
- setInitialValue(value) {
46
- if (value !== this.initialValue) {
45
+ setDefaultValue(value) {
46
+ if (value !== this.defaultValue) {
47
47
  const errors = this.validators
48
48
  ? helpers.controlIsValid({ value, validators: this.validators })
49
49
  : [];
50
- this.refresh('value', {
51
- dirty: false,
52
- errors,
53
- initialValue: value,
54
- value
55
- });
50
+ this.refresh('value', { errors, defaultValue: value, value });
51
+ }
52
+ }
53
+ setStartValue(value) {
54
+ if (value !== this.value) {
55
+ const errors = this.validators
56
+ ? helpers.controlIsValid({ value, validators: this.validators })
57
+ : [];
58
+ this.refresh('value', { errors, value });
56
59
  }
57
60
  }
58
61
  setValue(value) {
@@ -60,11 +63,7 @@ class RolsterArrayControl {
60
63
  const errors = this.validators
61
64
  ? helpers.controlIsValid({ value, validators: this.validators })
62
65
  : [];
63
- this.refresh('value', {
64
- dirty: true,
65
- errors,
66
- value
67
- });
66
+ this.refresh('value', { dirty: true, errors, value });
68
67
  }
69
68
  }
70
69
  setValidators(validators) {
@@ -85,7 +84,7 @@ class RolsterArrayControl {
85
84
  reset() {
86
85
  const errors = this.validators
87
86
  ? helpers.controlIsValid({
88
- value: this.initialValue,
87
+ value: this.defaultValue,
89
88
  validators: this.validators
90
89
  })
91
90
  : [];
@@ -93,7 +92,7 @@ class RolsterArrayControl {
93
92
  dirty: false,
94
93
  errors,
95
94
  touched: false,
96
- value: this.initialValue
95
+ value: this.defaultValue
97
96
  });
98
97
  }
99
98
  isValid(errors) {
@@ -117,7 +116,7 @@ function rolsterArrayControl(options, validators) {
117
116
  const formControl = _arguments.createFormControlOptions(options, validators);
118
117
  return new ReactRolsterArrayControl({
119
118
  ...formControl,
120
- initialValue: formControl.value,
119
+ defaultValue: formControl.value,
121
120
  uuid: uuid.v4()
122
121
  });
123
122
  }
@@ -233,12 +232,12 @@ class ReactRolsterArrayGroup extends RolsterArrayGroup {
233
232
  super({
234
233
  ...options,
235
234
  errors,
236
- value: helpers.controlsToValue(controls),
237
235
  dirties: helpers.controlsAllChecked(controls, 'dirty'),
238
236
  dirty: helpers.controlsPartialChecked(controls, 'dirty'),
239
237
  touched: helpers.controlsPartialChecked(controls, 'touched'),
240
238
  toucheds: helpers.controlsAllChecked(controls, 'touched'),
241
- valid: errors.length === 0 && helpers.controlsAllChecked(controls, 'valid')
239
+ valid: errors.length === 0 && helpers.controlsAllChecked(controls, 'valid'),
240
+ value: helpers.controlsToValue(controls)
242
241
  });
243
242
  }
244
243
  }
@@ -256,7 +255,7 @@ function formArrayGroup(options, validators) {
256
255
  class RolsterArrayList extends RolsterArrayControl {
257
256
  constructor(options) {
258
257
  const { controls, valueToControls, validators } = options;
259
- const value = controls.map((controls) => helpers.controlsToValue(controls));
258
+ const value = controls.map(helpers.controlsToValue);
260
259
  const errors = validators ? helpers.controlIsValid({ value, validators }) : [];
261
260
  super({ ...options, errors, value });
262
261
  this.valueToControls = valueToControls;
@@ -270,20 +269,28 @@ class RolsterArrayList extends RolsterArrayControl {
270
269
  this._subscribe(reactControls);
271
270
  });
272
271
  }
273
- setInitialValue(value) {
272
+ setDefaultValue(value) {
273
+ this.refresh('list', {
274
+ controls: value.map(this.valueToControls),
275
+ defaultValue: value
276
+ });
277
+ }
278
+ setStartValue(value) {
274
279
  this.refresh('list', {
275
- controls: value.map((value) => this.valueToControls(value)),
276
- initialValue: value
280
+ controls: value.map(this.valueToControls)
277
281
  });
278
282
  }
279
283
  setValue(value) {
280
284
  this.refresh('list', {
281
- controls: value.map((value) => this.valueToControls(value))
285
+ controls: value.map(this.valueToControls),
286
+ dirty: true
282
287
  });
283
288
  }
284
289
  reset() {
285
290
  this.refresh('list', {
286
- controls: this.initialValue.map((value) => this.valueToControls(value))
291
+ controls: this.defaultValue.map(this.valueToControls),
292
+ dirty: false,
293
+ touched: false
287
294
  });
288
295
  }
289
296
  push(controls) {
@@ -322,7 +329,7 @@ function formArrayList(options) {
322
329
  return new RolsterArrayList({
323
330
  ...options,
324
331
  controls: value.map((value) => options.valueToControls(value)),
325
- initialValue: value,
332
+ defaultValue: value,
326
333
  uuid: uuid.v4()
327
334
  });
328
335
  }
@@ -359,17 +366,19 @@ function useFormArray(options, validators) {
359
366
  const groups = formArray.groups || [];
360
367
  const value = react.useRef(groups);
361
368
  const formGroups = react.useRef(new Map());
362
- const [state, setState] = react.useState({
363
- ...refactorForValid$1(groups, formArray.validators),
364
- controls: groups.map(({ controls }) => controls),
365
- dirty: false,
366
- dirties: false,
367
- disabled: false,
368
- groups,
369
- touched: false,
370
- toucheds: false,
371
- value: groups.map(({ controls }) => helpers.controlsToValue(controls)),
372
- validators: formArray.validators
369
+ const [state, setState] = react.useState(() => {
370
+ return {
371
+ ...refactorForValid$1(groups, formArray.validators),
372
+ controls: groups.map(({ controls }) => controls),
373
+ dirty: false,
374
+ dirties: false,
375
+ disabled: false,
376
+ groups,
377
+ touched: false,
378
+ toucheds: false,
379
+ value: groups.map(({ controls }) => helpers.controlsToValue(controls)),
380
+ validators: formArray.validators
381
+ };
373
382
  });
374
383
  react.useEffect(() => {
375
384
  formGroups.current.clear();
@@ -380,8 +389,8 @@ function useFormArray(options, validators) {
380
389
  }, [state.groups]);
381
390
  const subscriber = react.useCallback((action, group) => {
382
391
  setState((state) => {
383
- const groups = state.groups.map((_group) => {
384
- return _group.uuid === group.uuid ? group : _group;
392
+ const groups = state.groups.map((currentGroup) => {
393
+ return currentGroup.uuid === group.uuid ? group : currentGroup;
385
394
  });
386
395
  return {
387
396
  ...state,
@@ -436,8 +445,12 @@ function useFormArray(options, validators) {
436
445
  validators
437
446
  }));
438
447
  }, []);
439
- const hasError = react.useCallback((key) => helpers.hasError(state.errors, key), [state.errors]);
440
- const someErrors = react.useCallback((keys) => helpers.someErrors(state.errors, keys), [state.errors]);
448
+ const hasError = react.useCallback((key) => {
449
+ return helpers.hasError(state.errors, key);
450
+ }, [state.errors]);
451
+ const someErrors = react.useCallback((keys) => {
452
+ return helpers.someErrors(state.errors, keys);
453
+ }, [state.errors]);
441
454
  const reset = react.useCallback(() => {
442
455
  setState((state) => ({
443
456
  ...state,
@@ -474,15 +487,17 @@ function errorsInControl(value, validators) {
474
487
  }
475
488
  function useControl(options, validators) {
476
489
  const formControl = _arguments.createFormControlOptions(options, validators);
477
- const initialValue = react.useRef(formControl.value);
478
- const [state, setState] = react.useState({
479
- dirty: false,
480
- disabled: false,
481
- errors: errorsInControl(formControl.value, formControl.validators),
482
- focused: false,
483
- touched: !!formControl.touched,
484
- value: formControl.value,
485
- validators: formControl.validators
490
+ const defaultValue = react.useRef(formControl.value);
491
+ const [state, setState] = react.useState(() => {
492
+ return {
493
+ dirty: false,
494
+ disabled: false,
495
+ errors: errorsInControl(formControl.value, formControl.validators),
496
+ focused: false,
497
+ touched: !!formControl.touched,
498
+ value: formControl.value,
499
+ validators: formControl.validators
500
+ };
486
501
  });
487
502
  const elementRef = react.useRef(null);
488
503
  const focus = react.useCallback(() => {
@@ -500,11 +515,17 @@ function useControl(options, validators) {
500
515
  const touch = react.useCallback(() => {
501
516
  setState((state) => ({ ...state, touched: true }));
502
517
  }, []);
503
- const setInitialValue = react.useCallback((value) => {
504
- initialValue.current = value;
518
+ const setDefaultValue = react.useCallback((value) => {
519
+ defaultValue.current = value;
520
+ setState((state) => ({
521
+ ...state,
522
+ errors: errorsInControl(value, state.validators),
523
+ value
524
+ }));
525
+ }, []);
526
+ const setStartValue = react.useCallback((value) => {
505
527
  setState((state) => ({
506
528
  ...state,
507
- dirty: true,
508
529
  errors: errorsInControl(value, state.validators),
509
530
  value
510
531
  }));
@@ -528,13 +549,17 @@ function useControl(options, validators) {
528
549
  setState((state) => ({
529
550
  ...state,
530
551
  dirty: false,
531
- errors: errorsInControl(initialValue.current, state.validators),
532
- value: initialValue.current,
552
+ errors: errorsInControl(defaultValue.current, state.validators),
553
+ value: defaultValue.current,
533
554
  touched: false
534
555
  }));
535
556
  }, []);
536
- const hasError = react.useCallback((key) => helpers.hasError(state.errors, key), [state.errors]);
537
- const someErrors = react.useCallback((keys) => helpers.someErrors(state.errors, keys), [state.errors]);
557
+ const hasError = react.useCallback((key) => {
558
+ return helpers.hasError(state.errors, key);
559
+ }, [state.errors]);
560
+ const someErrors = react.useCallback((keys) => {
561
+ return helpers.someErrors(state.errors, keys);
562
+ }, [state.errors]);
538
563
  const valid = state.errors.length === 0;
539
564
  return {
540
565
  ...state,
@@ -549,7 +574,8 @@ function useControl(options, validators) {
549
574
  invalid: !valid,
550
575
  pristine: !state.dirty,
551
576
  reset,
552
- setInitialValue,
577
+ setDefaultValue,
578
+ setStartValue,
553
579
  setValidators,
554
580
  setValue,
555
581
  someErrors,
@@ -577,26 +603,53 @@ function refactorForValid(controls, validators) {
577
603
  valid: errors.length === 0 && helpers.controlsAllChecked(controls, 'valid')
578
604
  };
579
605
  }
606
+ function checkAllSuccess(status) {
607
+ return status.reduce((success, status) => success && status, true);
608
+ }
609
+ function checkPartialSuccess(status) {
610
+ return status.reduce((success, status) => success || status, false);
611
+ }
580
612
  function useFormGroup(options, validators) {
581
613
  const formGroup = _arguments.createFormGroupOptions(options, validators);
582
- const firstEffects = react.useRef({
583
- dirty: true,
584
- disabledFocused: true,
585
- touched: true,
586
- value: true
614
+ const formInitialized = react.useRef({
615
+ dirty: false,
616
+ touched: false,
617
+ value: false,
618
+ visual: false
587
619
  });
588
- const [state, setState] = react.useState({
589
- ...refactorForValid(formGroup.controls, formGroup.validators),
590
- controls: formGroup.controls,
591
- dirties: helpers.controlsAllChecked(formGroup.controls, 'dirty'),
592
- dirty: helpers.controlsPartialChecked(formGroup.controls, 'dirty'),
593
- touched: helpers.controlsPartialChecked(formGroup.controls, 'touched'),
594
- toucheds: helpers.controlsAllChecked(formGroup.controls, 'touched'),
595
- value: helpers.controlsToValue(formGroup.controls),
596
- validators: formGroup.validators
620
+ const formGroupStatus = react.useMemo(() => {
621
+ const dirty = [];
622
+ const touched = [];
623
+ const value = [];
624
+ const visual = [];
625
+ Object.values(formGroup.controls).forEach((control) => {
626
+ dirty.push(control.dirty);
627
+ touched.push(control.touched);
628
+ value.push(control.value);
629
+ visual.push(control.disabled);
630
+ visual.push(control.focused);
631
+ });
632
+ return {
633
+ dirty,
634
+ touched,
635
+ value,
636
+ visual
637
+ };
638
+ }, [formGroup.controls]);
639
+ const [state, setState] = react.useState(() => {
640
+ return {
641
+ ...refactorForValid(formGroup.controls, formGroup.validators),
642
+ controls: formGroup.controls,
643
+ dirties: checkAllSuccess(formGroupStatus.dirty),
644
+ dirty: checkPartialSuccess(formGroupStatus.dirty),
645
+ touched: checkPartialSuccess(formGroupStatus.touched),
646
+ toucheds: checkAllSuccess(formGroupStatus.touched),
647
+ validators: formGroup.validators,
648
+ value: helpers.controlsToValue(formGroup.controls)
649
+ };
597
650
  });
598
651
  react.useEffect(() => {
599
- if (!firstEffects.current.value) {
652
+ if (formInitialized.current.value) {
600
653
  setState((state) => ({
601
654
  ...state,
602
655
  ...refactorForValid(formGroup.controls, state.validators),
@@ -605,49 +658,46 @@ function useFormGroup(options, validators) {
605
658
  }));
606
659
  }
607
660
  else {
608
- firstEffects.current.value = false;
661
+ formInitialized.current.value = true;
609
662
  }
610
- }, helpers.reduceControlsToArray(formGroup.controls, 'value'));
663
+ }, formGroupStatus.value);
611
664
  react.useEffect(() => {
612
- if (!firstEffects.current.disabledFocused) {
665
+ if (formInitialized.current.dirty) {
613
666
  setState((state) => ({
614
667
  ...state,
615
- controls: formGroup.controls
668
+ controls: formGroup.controls,
669
+ dirty: checkPartialSuccess(formGroupStatus.dirty),
670
+ dirties: checkAllSuccess(formGroupStatus.dirty)
616
671
  }));
617
672
  }
618
673
  else {
619
- firstEffects.current.disabledFocused = false;
674
+ formInitialized.current.dirty = true;
620
675
  }
621
- }, [
622
- ...helpers.reduceControlsToArray(formGroup.controls, 'disabled'),
623
- ...helpers.reduceControlsToArray(formGroup.controls, 'focused')
624
- ]);
676
+ }, formGroupStatus.dirty);
625
677
  react.useEffect(() => {
626
- if (!firstEffects.current.dirty) {
678
+ if (formInitialized.current.touched) {
627
679
  setState((state) => ({
628
680
  ...state,
629
681
  controls: formGroup.controls,
630
- dirty: helpers.controlsPartialChecked(formGroup.controls, 'dirty'),
631
- dirties: helpers.controlsAllChecked(formGroup.controls, 'dirty')
682
+ touched: checkPartialSuccess(formGroupStatus.touched),
683
+ toucheds: checkAllSuccess(formGroupStatus.touched)
632
684
  }));
633
685
  }
634
686
  else {
635
- firstEffects.current.dirty = false;
687
+ formInitialized.current.touched = true;
636
688
  }
637
- }, helpers.reduceControlsToArray(formGroup.controls, 'dirty'));
689
+ }, formGroupStatus.touched);
638
690
  react.useEffect(() => {
639
- if (!firstEffects.current.touched) {
691
+ if (formInitialized.current.visual) {
640
692
  setState((state) => ({
641
693
  ...state,
642
- controls: formGroup.controls,
643
- touched: helpers.controlsPartialChecked(formGroup.controls, 'touched'),
644
- toucheds: helpers.controlsAllChecked(formGroup.controls, 'touched')
694
+ controls: formGroup.controls
645
695
  }));
646
696
  }
647
697
  else {
648
- firstEffects.current.touched = false;
698
+ formInitialized.current.visual = true;
649
699
  }
650
- }, helpers.reduceControlsToArray(formGroup.controls, 'touched'));
700
+ }, formGroupStatus.visual);
651
701
  const setValidators = react.useCallback((validators) => {
652
702
  setState((state) => ({
653
703
  ...state,