@strictly/react-form 0.0.25 → 0.0.26

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
  }
@@ -694,6 +703,7 @@ var FormModel = class {
694
703
  const accessor = this.getAccessorForValuePath(valuePath);
695
704
  return runInAction(() => {
696
705
  this.fieldOverrides[valuePath] = [value];
706
+ delete this.errorOverrides[valuePath];
697
707
  if (validation != null) {
698
708
  this.validation[valuePath] = validation;
699
709
  }
@@ -711,11 +721,26 @@ var FormModel = class {
711
721
  }
712
722
  });
713
723
  }
724
+ /**
725
+ * Forces an error onto a field. Error will be removed if the field value changes
726
+ * @param valuePath the field to display an error for
727
+ * @param error the error to display
728
+ */
729
+ overrideFieldError(valuePath, error) {
730
+ runInAction(() => {
731
+ if (error) {
732
+ this.errorOverrides[valuePath] = error;
733
+ } else {
734
+ delete this.errorOverrides[valuePath];
735
+ }
736
+ });
737
+ }
714
738
  clearFieldError(valuePath) {
715
739
  const fieldOverride = this.fieldOverrides[valuePath];
716
740
  if (fieldOverride != null) {
717
741
  runInAction(() => {
718
742
  delete this.validation[valuePath];
743
+ delete this.errorOverrides[valuePath];
719
744
  });
720
745
  }
721
746
  }
@@ -738,12 +763,14 @@ var FormModel = class {
738
763
  runInAction(() => {
739
764
  this.fieldOverrides[key] = [displayValue];
740
765
  delete this.validation[key];
766
+ delete this.errorOverrides[key];
741
767
  });
742
768
  }
743
769
  clearAll(value) {
744
770
  runInAction(() => {
745
771
  this.validation = {};
746
772
  this.fieldOverrides = {};
773
+ this.errorOverrides = {};
747
774
  this.value = mobxCopy(this.type, value);
748
775
  });
749
776
  }
@@ -756,7 +783,7 @@ var FormModel = class {
756
783
  var _a;
757
784
  return (_a = this.validation[valuePath]) != null ? _a : 0 /* None */;
758
785
  }
759
- isDirty(valuePath) {
786
+ isFieldDirty(valuePath) {
760
787
  const typePath = valuePathToTypePath(
761
788
  this.type,
762
789
  // eslint-disable-next-line @typescript-eslint/consistent-type-assertions
@@ -770,16 +797,30 @@ var FormModel = class {
770
797
  const {
771
798
  displayedValue,
772
799
  convert,
800
+ revert,
773
801
  context,
774
802
  defaultValue
775
803
  } = field;
776
804
  const originalValue = valuePath in this.originalValues ? this.originalValues[valuePath] : defaultValue;
805
+ if (revert != null) {
806
+ const typeDef = this.flattenedTypeDefs[typePath];
807
+ const {
808
+ value,
809
+ type
810
+ } = revert(displayedValue, valuePath, context);
811
+ if (type === 0 /* Success */) {
812
+ if (equals(typeDef, originalValue, value)) {
813
+ return false;
814
+ }
815
+ }
816
+ }
777
817
  const { value: originalDisplayedValue } = convert(originalValue, valuePath, context);
778
818
  return displayedValue !== originalDisplayedValue;
779
819
  }
780
820
  validateField(valuePath, validation = 2 /* Always */) {
781
821
  runInAction(() => {
782
822
  this.validation[valuePath] = validation;
823
+ delete this.errorOverrides[valuePath];
783
824
  });
784
825
  return this.fields[valuePath].error == null;
785
826
  }
@@ -797,17 +838,23 @@ var FormModel = class {
797
838
  }
798
839
  );
799
840
  }
841
+ validateSubmit() {
842
+ return this.validateAll();
843
+ }
800
844
  };
801
845
  _init = __decoratorStart(null);
802
846
  _value = new WeakMap();
803
847
  _fieldOverrides = new WeakMap();
848
+ _errorOverrides = new WeakMap();
804
849
  _validation = new WeakMap();
805
850
  __decorateElement(_init, 4, "value", _value_dec, FormModel, _value);
806
851
  __decorateElement(_init, 4, "fieldOverrides", _fieldOverrides_dec, FormModel, _fieldOverrides);
852
+ __decorateElement(_init, 4, "errorOverrides", _errorOverrides_dec, FormModel, _errorOverrides);
807
853
  __decorateElement(_init, 4, "validation", _validation_dec, FormModel, _validation);
808
854
  __decorateElement(_init, 2, "fields", _fields_dec, FormModel);
809
855
  __decorateElement(_init, 2, "knownFields", _knownFields_dec, FormModel);
810
856
  __decorateElement(_init, 2, "accessors", _accessors_dec, FormModel);
857
+ __decorateElement(_init, 2, "dirty", _dirty_dec, FormModel);
811
858
  __decoratorMetadata(_init, FormModel);
812
859
 
813
860
  // core/mobx/hooks.tsx
@@ -840,7 +887,7 @@ function useDefaultMobxFormHooks(model, {
840
887
  const onFieldBlur = useCallback(
841
888
  function(path) {
842
889
  setTimeout(function() {
843
- if (model.isValuePathActive(path) && model.isDirty(path)) {
890
+ if (model.isValuePathActive(path) && model.isFieldDirty(path)) {
844
891
  model.validateField(path, Math.max(1 /* Changed */, model.getValidation(path)));
845
892
  }
846
893
  }, 100);
@@ -849,7 +896,7 @@ function useDefaultMobxFormHooks(model, {
849
896
  );
850
897
  const onFormSubmit = useCallback(
851
898
  function() {
852
- if (model.validateAll()) {
899
+ if (model.validateSubmit()) {
853
900
  onValidFormSubmit == null ? void 0 : onValidFormSubmit(model.value);
854
901
  }
855
902
  },
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.26",
76
76
  "exports": {
77
77
  ".": {
78
78
  "import": {