@rolster/react-forms 18.14.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) {
@@ -114,10 +113,10 @@ class ReactRolsterArrayControl extends RolsterArrayControl {
114
113
  }
115
114
  }
116
115
  function rolsterArrayControl(options, validators) {
117
- const _options = _arguments.createFormControlOptions(options, validators);
116
+ const formControl = _arguments.createFormControlOptions(options, validators);
118
117
  return new ReactRolsterArrayControl({
119
- ..._options,
120
- initialValue: _options.value,
118
+ ...formControl,
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
  }
@@ -355,33 +362,35 @@ function refactorForControls(action, state, groups) {
355
362
  }
356
363
  }
357
364
  function useFormArray(options, validators) {
358
- const _options = _arguments.createFormArrayOptions(options, validators);
359
- const groups = _options.groups || [];
360
- const _value = react.useRef(groups);
361
- const mapGroups = react.useRef(new Map());
362
- const [state, setState] = react.useState({
363
- ...refactorForValid$1(groups, _options.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: _options.validators
365
+ const formArray = _arguments.createFormArrayOptions(options, validators);
366
+ const groups = formArray.groups || [];
367
+ const value = react.useRef(groups);
368
+ const formGroups = react.useRef(new Map());
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
- mapGroups.current.clear();
384
+ formGroups.current.clear();
376
385
  state.groups.forEach((group) => {
377
- mapGroups.current.set(group.uuid, group);
386
+ formGroups.current.set(group.uuid, group);
378
387
  group.subscribe(subscriber);
379
388
  });
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,
@@ -406,7 +415,7 @@ function useFormArray(options, validators) {
406
415
  ...state,
407
416
  ...refactorForGroups(groups, state.validators)
408
417
  }));
409
- _value.current = groups;
418
+ value.current = groups;
410
419
  }, []);
411
420
  const push = react.useCallback((group) => {
412
421
  setState((state) => ({
@@ -427,7 +436,7 @@ function useFormArray(options, validators) {
427
436
  }));
428
437
  }, []);
429
438
  const findByUuid = react.useCallback((uuid) => {
430
- return mapGroups.current.get(uuid);
439
+ return formGroups.current.get(uuid);
431
440
  }, [state.groups]);
432
441
  const setValidators = react.useCallback((validators) => {
433
442
  setState((state) => ({
@@ -436,12 +445,16 @@ 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,
444
- ...refactorForGroups(_value.current, state.validators)
457
+ ...refactorForGroups(value.current, state.validators)
445
458
  }));
446
459
  }, []);
447
460
  return {
@@ -473,16 +486,18 @@ function errorsInControl(value, validators) {
473
486
  return validators ? helpers.controlIsValid({ value, validators }) : [];
474
487
  }
475
488
  function useControl(options, validators) {
476
- const _options = _arguments.createFormControlOptions(options, validators);
477
- const initialValue = react.useRef(_options.value);
478
- const [state, setState] = react.useState({
479
- dirty: false,
480
- disabled: false,
481
- errors: errorsInControl(_options.value, _options.validators),
482
- focused: false,
483
- touched: !!_options.touched,
484
- value: _options.value,
485
- validators: _options.validators
489
+ const formControl = _arguments.createFormControlOptions(options, 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,78 +603,101 @@ 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
- const _options = _arguments.createFormGroupOptions(options, validators);
582
- const { controls } = _options;
583
- const firstEffects = react.useRef({
584
- dirty: true,
585
- disabledFocused: true,
586
- touched: true,
587
- value: true
613
+ const formGroup = _arguments.createFormGroupOptions(options, validators);
614
+ const formInitialized = react.useRef({
615
+ dirty: false,
616
+ touched: false,
617
+ value: false,
618
+ visual: false
588
619
  });
589
- const [state, setState] = react.useState({
590
- ...refactorForValid(controls, _options.validators),
591
- controls,
592
- dirties: helpers.controlsAllChecked(controls, 'dirty'),
593
- dirty: helpers.controlsPartialChecked(controls, 'dirty'),
594
- touched: helpers.controlsPartialChecked(controls, 'touched'),
595
- toucheds: helpers.controlsAllChecked(controls, 'touched'),
596
- value: helpers.controlsToValue(controls),
597
- validators: _options.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
+ };
598
650
  });
599
651
  react.useEffect(() => {
600
- if (!firstEffects.current.value) {
652
+ if (formInitialized.current.value) {
601
653
  setState((state) => ({
602
654
  ...state,
603
- ...refactorForValid(controls, state.validators),
604
- controls,
605
- value: helpers.controlsToValue(controls)
655
+ ...refactorForValid(formGroup.controls, state.validators),
656
+ controls: formGroup.controls,
657
+ value: helpers.controlsToValue(formGroup.controls)
606
658
  }));
607
659
  }
608
660
  else {
609
- firstEffects.current.value = false;
661
+ formInitialized.current.value = true;
610
662
  }
611
- }, helpers.reduceControlsToArray(controls, 'value'));
663
+ }, formGroupStatus.value);
612
664
  react.useEffect(() => {
613
- if (!firstEffects.current.disabledFocused) {
665
+ if (formInitialized.current.dirty) {
614
666
  setState((state) => ({
615
667
  ...state,
616
- controls
668
+ controls: formGroup.controls,
669
+ dirty: checkPartialSuccess(formGroupStatus.dirty),
670
+ dirties: checkAllSuccess(formGroupStatus.dirty)
617
671
  }));
618
672
  }
619
673
  else {
620
- firstEffects.current.disabledFocused = false;
674
+ formInitialized.current.dirty = true;
621
675
  }
622
- }, [
623
- ...helpers.reduceControlsToArray(controls, 'disabled'),
624
- ...helpers.reduceControlsToArray(controls, 'focused')
625
- ]);
676
+ }, formGroupStatus.dirty);
626
677
  react.useEffect(() => {
627
- if (!firstEffects.current.dirty) {
678
+ if (formInitialized.current.touched) {
628
679
  setState((state) => ({
629
680
  ...state,
630
- controls,
631
- dirty: helpers.controlsPartialChecked(controls, 'dirty'),
632
- dirties: helpers.controlsAllChecked(controls, 'dirty')
681
+ controls: formGroup.controls,
682
+ touched: checkPartialSuccess(formGroupStatus.touched),
683
+ toucheds: checkAllSuccess(formGroupStatus.touched)
633
684
  }));
634
685
  }
635
686
  else {
636
- firstEffects.current.dirty = false;
687
+ formInitialized.current.touched = true;
637
688
  }
638
- }, helpers.reduceControlsToArray(controls, 'dirty'));
689
+ }, formGroupStatus.touched);
639
690
  react.useEffect(() => {
640
- if (!firstEffects.current.touched) {
691
+ if (formInitialized.current.visual) {
641
692
  setState((state) => ({
642
693
  ...state,
643
- controls,
644
- touched: helpers.controlsPartialChecked(controls, 'touched'),
645
- toucheds: helpers.controlsAllChecked(controls, 'touched')
694
+ controls: formGroup.controls
646
695
  }));
647
696
  }
648
697
  else {
649
- firstEffects.current.touched = false;
698
+ formInitialized.current.visual = true;
650
699
  }
651
- }, helpers.reduceControlsToArray(controls, 'touched'));
700
+ }, formGroupStatus.visual);
652
701
  const setValidators = react.useCallback((validators) => {
653
702
  setState((state) => ({
654
703
  ...state,
@@ -656,7 +705,7 @@ function useFormGroup(options, validators) {
656
705
  }));
657
706
  }, []);
658
707
  const reset = react.useCallback(() => {
659
- Object.values(controls).forEach((control) => {
708
+ Object.values(formGroup.controls).forEach((control) => {
660
709
  control.reset();
661
710
  });
662
711
  }, []);