@strictly/react-form 0.0.25 → 0.0.27

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.js CHANGED
@@ -313,6 +313,7 @@ import {
313
313
  UnreachableError as UnreachableError2
314
314
  } from "@strictly/base";
315
315
  import {
316
+ equals,
316
317
  flattenAccessorsOfType,
317
318
  flattenTypesOfType,
318
319
  flattenValuesOfType,
@@ -332,8 +333,8 @@ var Validation = /* @__PURE__ */ ((Validation2) => {
332
333
  Validation2[Validation2["Always"] = 2] = "Always";
333
334
  return Validation2;
334
335
  })(Validation || {});
335
- var _accessors_dec, _knownFields_dec, _fields_dec, _validation_dec, _fieldOverrides_dec, _value_dec, _init, _value, _fieldOverrides, _validation;
336
- _value_dec = [observable.ref], _fieldOverrides_dec = [observable.shallow], _validation_dec = [observable.shallow], _fields_dec = [computed], _knownFields_dec = [computed], _accessors_dec = [computed];
336
+ var _dirty_dec, _accessors_dec, _knownFields_dec, _fields_dec, _validation_dec, _errorOverrides_dec, _fieldOverrides_dec, _value_dec, _init, _value, _fieldOverrides, _errorOverrides, _validation;
337
+ _value_dec = [observable.ref], _fieldOverrides_dec = [observable.shallow], _errorOverrides_dec = [observable.shallow], _validation_dec = [observable.shallow], _fields_dec = [computed], _knownFields_dec = [computed], _accessors_dec = [computed], _dirty_dec = [computed];
337
338
  var FormModel = class {
338
339
  constructor(type, originalValue, adapters, mode) {
339
340
  this.type = type;
@@ -342,7 +343,8 @@ var FormModel = class {
342
343
  __runInitializers(_init, 5, this);
343
344
  __privateAdd(this, _value, __runInitializers(_init, 8, this)), __runInitializers(_init, 11, this);
344
345
  __privateAdd(this, _fieldOverrides, __runInitializers(_init, 12, this)), __runInitializers(_init, 15, this);
345
- __privateAdd(this, _validation, __runInitializers(_init, 16, this, {})), __runInitializers(_init, 19, this);
346
+ __privateAdd(this, _errorOverrides, __runInitializers(_init, 16, this, {})), __runInitializers(_init, 19, this);
347
+ __privateAdd(this, _validation, __runInitializers(_init, 20, this, {})), __runInitializers(_init, 23, this);
346
348
  __publicField(this, "flattenedTypeDefs");
347
349
  // cannot be type safe
348
350
  // eslint-disable-next-line @typescript-eslint/no-explicit-any
@@ -489,34 +491,36 @@ var FormModel = class {
489
491
  defaultValue
490
492
  } = field;
491
493
  const validation = (_a = this.validation[valuePath]) != null ? _a : 0 /* None */;
492
- let error;
493
- switch (validation) {
494
- case 0 /* None */:
495
- break;
496
- case 1 /* Changed */:
497
- if (revert != null) {
498
- const originalValue = valuePath in this.originalValues ? this.originalValues[valuePath] : defaultValue;
499
- const { value: originalDisplayedValue } = convert(originalValue, valuePath, context);
500
- if (displayedValue !== originalDisplayedValue) {
501
- const revertResult = revert(displayedValue, valuePath, context);
494
+ let error = this.errorOverrides[valuePath];
495
+ if (error == null) {
496
+ switch (validation) {
497
+ case 0 /* None */:
498
+ break;
499
+ case 1 /* Changed */:
500
+ if (revert != null) {
501
+ const originalValue = valuePath in this.originalValues ? this.originalValues[valuePath] : defaultValue;
502
+ const { value: originalDisplayedValue } = convert(originalValue, valuePath, context);
503
+ if (displayedValue !== originalDisplayedValue) {
504
+ const revertResult = revert(displayedValue, valuePath, context);
505
+ if ((revertResult == null ? void 0 : revertResult.type) === 1 /* Failure */) {
506
+ ;
507
+ ({ error } = revertResult);
508
+ }
509
+ }
510
+ }
511
+ break;
512
+ case 2 /* Always */:
513
+ {
514
+ const revertResult = revert == null ? void 0 : revert(displayedValue, valuePath, context);
502
515
  if ((revertResult == null ? void 0 : revertResult.type) === 1 /* Failure */) {
503
516
  ;
504
517
  ({ error } = revertResult);
505
518
  }
506
519
  }
507
- }
508
- break;
509
- case 2 /* Always */:
510
- {
511
- const revertResult = revert == null ? void 0 : revert(displayedValue, valuePath, context);
512
- if ((revertResult == null ? void 0 : revertResult.type) === 1 /* Failure */) {
513
- ;
514
- ({ error } = revertResult);
515
- }
516
- }
517
- break;
518
- default:
519
- throw new UnreachableError2(validation);
520
+ break;
521
+ default:
522
+ throw new UnreachableError2(validation);
523
+ }
520
524
  }
521
525
  return {
522
526
  value: displayedValue,
@@ -549,6 +553,11 @@ var FormModel = class {
549
553
  valuePath
550
554
  );
551
555
  }
556
+ get dirty() {
557
+ return Object.keys(this.accessors).some((valuePath) => {
558
+ return this.isFieldDirty(valuePath);
559
+ });
560
+ }
552
561
  typePath(valuePath) {
553
562
  return valuePathToTypePath(this.type, valuePath, true);
554
563
  }
@@ -681,12 +690,17 @@ var FormModel = class {
681
690
  const validation = this.validation[fromJsonPath];
682
691
  delete this.validation[fromJsonPath];
683
692
  this.validation[toJsonPath] = validation;
693
+ this.moveListItem(fromJsonPath, toJsonPath);
684
694
  });
685
695
  accessor.set(newList);
686
696
  delete this.fieldOverrides[listValuePath];
687
697
  });
688
698
  });
689
699
  }
700
+ moveListItem(fromValuePath, toValuePath) {
701
+ fromValuePath;
702
+ toValuePath;
703
+ }
690
704
  internalSetFieldValue(valuePath, value, validation) {
691
705
  const { revert } = this.getAdapterForValuePath(valuePath);
692
706
  assertExists(revert, "setting value not supported {}", valuePath);
@@ -694,6 +708,7 @@ var FormModel = class {
694
708
  const accessor = this.getAccessorForValuePath(valuePath);
695
709
  return runInAction(() => {
696
710
  this.fieldOverrides[valuePath] = [value];
711
+ delete this.errorOverrides[valuePath];
697
712
  if (validation != null) {
698
713
  this.validation[valuePath] = validation;
699
714
  }
@@ -711,11 +726,26 @@ var FormModel = class {
711
726
  }
712
727
  });
713
728
  }
729
+ /**
730
+ * Forces an error onto a field. Error will be removed if the field value changes
731
+ * @param valuePath the field to display an error for
732
+ * @param error the error to display
733
+ */
734
+ overrideFieldError(valuePath, error) {
735
+ runInAction(() => {
736
+ if (error) {
737
+ this.errorOverrides[valuePath] = error;
738
+ } else {
739
+ delete this.errorOverrides[valuePath];
740
+ }
741
+ });
742
+ }
714
743
  clearFieldError(valuePath) {
715
744
  const fieldOverride = this.fieldOverrides[valuePath];
716
745
  if (fieldOverride != null) {
717
746
  runInAction(() => {
718
747
  delete this.validation[valuePath];
748
+ delete this.errorOverrides[valuePath];
719
749
  });
720
750
  }
721
751
  }
@@ -738,12 +768,14 @@ var FormModel = class {
738
768
  runInAction(() => {
739
769
  this.fieldOverrides[key] = [displayValue];
740
770
  delete this.validation[key];
771
+ delete this.errorOverrides[key];
741
772
  });
742
773
  }
743
774
  clearAll(value) {
744
775
  runInAction(() => {
745
776
  this.validation = {};
746
777
  this.fieldOverrides = {};
778
+ this.errorOverrides = {};
747
779
  this.value = mobxCopy(this.type, value);
748
780
  });
749
781
  }
@@ -756,7 +788,7 @@ var FormModel = class {
756
788
  var _a;
757
789
  return (_a = this.validation[valuePath]) != null ? _a : 0 /* None */;
758
790
  }
759
- isDirty(valuePath) {
791
+ isFieldDirty(valuePath) {
760
792
  const typePath = valuePathToTypePath(
761
793
  this.type,
762
794
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
@@ -770,16 +802,30 @@ var FormModel = class {
770
802
  const {
771
803
  displayedValue,
772
804
  convert,
805
+ revert,
773
806
  context,
774
807
  defaultValue
775
808
  } = field;
776
809
  const originalValue = valuePath in this.originalValues ? this.originalValues[valuePath] : defaultValue;
810
+ if (revert != null) {
811
+ const typeDef = this.flattenedTypeDefs[typePath];
812
+ const {
813
+ value,
814
+ type
815
+ } = revert(displayedValue, valuePath, context);
816
+ if (type === 0 /* Success */) {
817
+ if (equals(typeDef, originalValue, value)) {
818
+ return false;
819
+ }
820
+ }
821
+ }
777
822
  const { value: originalDisplayedValue } = convert(originalValue, valuePath, context);
778
823
  return displayedValue !== originalDisplayedValue;
779
824
  }
780
825
  validateField(valuePath, validation = 2 /* Always */) {
781
826
  runInAction(() => {
782
827
  this.validation[valuePath] = validation;
828
+ delete this.errorOverrides[valuePath];
783
829
  });
784
830
  return this.fields[valuePath].error == null;
785
831
  }
@@ -797,17 +843,23 @@ var FormModel = class {
797
843
  }
798
844
  );
799
845
  }
846
+ validateSubmit() {
847
+ return this.validateAll();
848
+ }
800
849
  };
801
850
  _init = __decoratorStart(null);
802
851
  _value = new WeakMap();
803
852
  _fieldOverrides = new WeakMap();
853
+ _errorOverrides = new WeakMap();
804
854
  _validation = new WeakMap();
805
855
  __decorateElement(_init, 4, "value", _value_dec, FormModel, _value);
806
856
  __decorateElement(_init, 4, "fieldOverrides", _fieldOverrides_dec, FormModel, _fieldOverrides);
857
+ __decorateElement(_init, 4, "errorOverrides", _errorOverrides_dec, FormModel, _errorOverrides);
807
858
  __decorateElement(_init, 4, "validation", _validation_dec, FormModel, _validation);
808
859
  __decorateElement(_init, 2, "fields", _fields_dec, FormModel);
809
860
  __decorateElement(_init, 2, "knownFields", _knownFields_dec, FormModel);
810
861
  __decorateElement(_init, 2, "accessors", _accessors_dec, FormModel);
862
+ __decorateElement(_init, 2, "dirty", _dirty_dec, FormModel);
811
863
  __decoratorMetadata(_init, FormModel);
812
864
 
813
865
  // core/mobx/hooks.tsx
@@ -840,7 +892,7 @@ function useDefaultMobxFormHooks(model, {
840
892
  const onFieldBlur = useCallback(
841
893
  function(path) {
842
894
  setTimeout(function() {
843
- if (model.isValuePathActive(path) && model.isDirty(path)) {
895
+ if (model.isValuePathActive(path) && model.isFieldDirty(path) && model.fields[path].error == null) {
844
896
  model.validateField(path, Math.max(1 /* Changed */, model.getValidation(path)));
845
897
  }
846
898
  }, 100);
@@ -849,7 +901,7 @@ function useDefaultMobxFormHooks(model, {
849
901
  );
850
902
  const onFormSubmit = useCallback(
851
903
  function() {
852
- if (model.validateAll()) {
904
+ if (model.validateSubmit()) {
853
905
  onValidFormSubmit == null ? void 0 : onValidFormSubmit(model.value);
854
906
  }
855
907
  },
package/package.json CHANGED
@@ -72,7 +72,7 @@
72
72
  "test:watch": "vitest"
73
73
  },
74
74
  "type": "module",
75
- "version": "0.0.25",
75
+ "version": "0.0.27",
76
76
  "exports": {
77
77
  ".": {
78
78
  "import": {