@strictly/react-form 0.0.31 → 0.0.32
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/.out/.storybook/preview.js +7 -0
- package/.out/core/mobx/FormModel.d.ts +3 -2
- package/.out/core/mobx/FormModel.js +46 -34
- package/.out/core/mobx/hooks.js +14 -5
- package/.out/core/mobx/peek.d.ts +5 -0
- package/.out/core/mobx/peek.js +16 -0
- package/.out/index.d.ts +1 -0
- package/.out/index.js +1 -0
- package/.out/tsconfig.tsbuildinfo +1 -1
- package/.storybook/preview.tsx +8 -0
- package/.turbo/turbo-build.log +8 -8
- package/.turbo/turbo-check-types.log +1 -1
- package/.turbo/turbo-release$colon$exports.log +1 -1
- package/core/mobx/FormModel.ts +29 -22
- package/core/mobx/hooks.tsx +17 -5
- package/core/mobx/peek.ts +17 -0
- package/dist/index.cjs +63 -34
- package/dist/index.d.cts +10 -3
- package/dist/index.d.ts +10 -3
- package/dist/index.js +65 -35
- package/index.ts +1 -0
- package/package.json +1 -1
|
@@ -1,7 +1,14 @@
|
|
|
1
1
|
import { jsx as _jsx } from "react/jsx-runtime";
|
|
2
2
|
import '@mantine/core/styles.css';
|
|
3
3
|
import { MantineProvider } from '@mantine/core';
|
|
4
|
+
import { configure } from 'mobx';
|
|
4
5
|
import { StrictMode } from 'react';
|
|
6
|
+
// turn on all useful mobx warnings in storybook to try to catch bad behavior
|
|
7
|
+
configure({
|
|
8
|
+
enforceActions: 'observed',
|
|
9
|
+
observableRequiresReaction: true,
|
|
10
|
+
reactionRequiresObservable: true,
|
|
11
|
+
});
|
|
5
12
|
const preview = {
|
|
6
13
|
parameters: {
|
|
7
14
|
controls: {
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
import { type ElementOfArray, type Maybe } from '@strictly/base';
|
|
2
|
-
import { type Accessor, type FlattenedValuesOfType, type
|
|
2
|
+
import { type Accessor, type FlattenedValuesOfType, type ReadonlyTypeOfType, type Type, type ValueOfType } from '@strictly/define';
|
|
3
3
|
import { type ReadonlyDeep, type SimplifyDeep, type StringKeyOf, type UnionToIntersection, type ValueOf } from 'type-fest';
|
|
4
4
|
import { type Field } from 'types/Field';
|
|
5
5
|
import { type ContextOfFieldAdapter, type ErrorOfFieldAdapter, type FieldAdapter, type ToOfFieldAdapter } from './FieldAdapter';
|
|
@@ -37,7 +37,7 @@ export declare abstract class FormModel<T extends Type, ValueToTypePaths extends
|
|
|
37
37
|
private readonly originalValue;
|
|
38
38
|
protected readonly adapters: TypePathsToAdapters;
|
|
39
39
|
protected readonly mode: FormMode;
|
|
40
|
-
accessor
|
|
40
|
+
private accessor observableValue;
|
|
41
41
|
accessor fieldOverrides: FlattenedFieldOverrides<ValuePathsToAdapters>;
|
|
42
42
|
accessor errorOverrides: FlattenedErrorOverrides<ValuePathsToAdapters>;
|
|
43
43
|
accessor validation: FlattenedValidation<ValuePathsToAdapters>;
|
|
@@ -47,6 +47,7 @@ export declare abstract class FormModel<T extends Type, ValueToTypePaths extends
|
|
|
47
47
|
constructor(type: T, originalValue: ValueOfType<ReadonlyTypeOfType<T>>, adapters: TypePathsToAdapters, mode: FormMode);
|
|
48
48
|
protected abstract toContext(value: ValueOfType<ReadonlyTypeOfType<T>>, valuePath: keyof ValuePathsToAdapters): ContextType;
|
|
49
49
|
get forceMutableFields(): boolean;
|
|
50
|
+
get value(): ValueOfType<ReadonlyTypeOfType<T>>;
|
|
50
51
|
get fields(): SimplifyDeep<FlattenedConvertedFieldsOf<ValuePathsToAdapters>>;
|
|
51
52
|
private get knownFields();
|
|
52
53
|
private maybeSynthesizeFieldByValuePath;
|
|
@@ -44,8 +44,8 @@ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (
|
|
|
44
44
|
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
45
45
|
};
|
|
46
46
|
import { assertExists, assertExistsAndReturn, checkValidNumber, map, toArray, UnreachableError, } from '@strictly/base';
|
|
47
|
-
import { equals, flattenAccessorsOfType, flattenTypesOfType, flattenValuesOfType, flattenValueTo, jsonPathPop, mobxCopy, valuePathToTypePath, } from '@strictly/define';
|
|
48
|
-
import { computed, observable, runInAction, } from 'mobx';
|
|
47
|
+
import { copy, equals, flattenAccessorsOfType, flattenTypesOfType, flattenValuesOfType, flattenValueTo, jsonPathPop, mobxCopy, valuePathToTypePath, } from '@strictly/define';
|
|
48
|
+
import { action, computed, observable, runInAction, } from 'mobx';
|
|
49
49
|
import { UnreliableFieldConversionType, } from 'types/FieldConverters';
|
|
50
50
|
export var Validation;
|
|
51
51
|
(function (Validation) {
|
|
@@ -54,12 +54,12 @@ export var Validation;
|
|
|
54
54
|
Validation[Validation["Always"] = 2] = "Always";
|
|
55
55
|
})(Validation || (Validation = {}));
|
|
56
56
|
let FormModel = (() => {
|
|
57
|
-
var _a,
|
|
57
|
+
var _a, _FormModel_observableValue_accessor_storage, _FormModel_fieldOverrides_accessor_storage, _FormModel_errorOverrides_accessor_storage, _FormModel_validation_accessor_storage;
|
|
58
58
|
var _b, _c, _d, _e;
|
|
59
59
|
let _instanceExtraInitializers = [];
|
|
60
|
-
let
|
|
61
|
-
let
|
|
62
|
-
let
|
|
60
|
+
let _observableValue_decorators;
|
|
61
|
+
let _observableValue_initializers = [];
|
|
62
|
+
let _observableValue_extraInitializers = [];
|
|
63
63
|
let _fieldOverrides_decorators;
|
|
64
64
|
let _fieldOverrides_initializers = [];
|
|
65
65
|
let _fieldOverrides_extraInitializers = [];
|
|
@@ -69,14 +69,18 @@ let FormModel = (() => {
|
|
|
69
69
|
let _validation_decorators;
|
|
70
70
|
let _validation_initializers = [];
|
|
71
71
|
let _validation_extraInitializers = [];
|
|
72
|
+
let _get_value_decorators;
|
|
72
73
|
let _get_fields_decorators;
|
|
73
74
|
let _get_knownFields_decorators;
|
|
74
75
|
let _get_accessors_decorators;
|
|
75
76
|
let _get_dirty_decorators;
|
|
76
77
|
let _get_valueChanged_decorators;
|
|
78
|
+
let _setFieldValue_decorators;
|
|
79
|
+
let _validateField_decorators;
|
|
80
|
+
let _validateAll_decorators;
|
|
77
81
|
return _a = class FormModel {
|
|
78
|
-
get
|
|
79
|
-
set
|
|
82
|
+
get observableValue() { return __classPrivateFieldGet(this, _FormModel_observableValue_accessor_storage, "f"); }
|
|
83
|
+
set observableValue(value) { __classPrivateFieldSet(this, _FormModel_observableValue_accessor_storage, value, "f"); }
|
|
80
84
|
get fieldOverrides() { return __classPrivateFieldGet(this, _FormModel_fieldOverrides_accessor_storage, "f"); }
|
|
81
85
|
set fieldOverrides(value) { __classPrivateFieldSet(this, _FormModel_fieldOverrides_accessor_storage, value, "f"); }
|
|
82
86
|
get errorOverrides() { return __classPrivateFieldGet(this, _FormModel_errorOverrides_accessor_storage, "f"); }
|
|
@@ -108,8 +112,8 @@ let FormModel = (() => {
|
|
|
108
112
|
writable: true,
|
|
109
113
|
value: mode
|
|
110
114
|
});
|
|
111
|
-
|
|
112
|
-
_FormModel_fieldOverrides_accessor_storage.set(this, (__runInitializers(this,
|
|
115
|
+
_FormModel_observableValue_accessor_storage.set(this, __runInitializers(this, _observableValue_initializers, void 0));
|
|
116
|
+
_FormModel_fieldOverrides_accessor_storage.set(this, (__runInitializers(this, _observableValue_extraInitializers), __runInitializers(this, _fieldOverrides_initializers, void 0)));
|
|
113
117
|
_FormModel_errorOverrides_accessor_storage.set(this, (__runInitializers(this, _fieldOverrides_extraInitializers), __runInitializers(this, _errorOverrides_initializers, {})));
|
|
114
118
|
_FormModel_validation_accessor_storage.set(this, (__runInitializers(this, _errorOverrides_extraInitializers), __runInitializers(this, _validation_initializers, {})));
|
|
115
119
|
Object.defineProperty(this, "flattenedTypeDefs", {
|
|
@@ -134,11 +138,11 @@ let FormModel = (() => {
|
|
|
134
138
|
value: {}
|
|
135
139
|
});
|
|
136
140
|
this.originalValues = flattenValuesOfType(type, originalValue, this.listIndicesToKeys);
|
|
137
|
-
this.
|
|
141
|
+
this.observableValue = mobxCopy(type, originalValue);
|
|
138
142
|
this.flattenedTypeDefs = flattenTypesOfType(type);
|
|
139
143
|
// pre-populate field overrides for consistent behavior when default information is overwritten
|
|
140
144
|
// then returned to
|
|
141
|
-
const conversions = flattenValueTo(type,
|
|
145
|
+
const conversions = flattenValueTo(type, originalValue, () => { }, (_t, fieldValue, _setter, typePath, valuePath) => {
|
|
142
146
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
143
147
|
const contextValue = this.toContext(originalValue, valuePath);
|
|
144
148
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
@@ -169,6 +173,10 @@ let FormModel = (() => {
|
|
|
169
173
|
throw new UnreachableError(this.mode);
|
|
170
174
|
}
|
|
171
175
|
}
|
|
176
|
+
get value() {
|
|
177
|
+
// copy and strip out the mobx so this computed will fire every time anything changes
|
|
178
|
+
return copy(this.type, this.observableValue);
|
|
179
|
+
}
|
|
172
180
|
get fields() {
|
|
173
181
|
return new Proxy(this.knownFields, {
|
|
174
182
|
get: (target, prop) => {
|
|
@@ -185,7 +193,7 @@ let FormModel = (() => {
|
|
|
185
193
|
});
|
|
186
194
|
}
|
|
187
195
|
get knownFields() {
|
|
188
|
-
return flattenValueTo(this.type, this.
|
|
196
|
+
return flattenValueTo(this.type, this.observableValue, () => { },
|
|
189
197
|
// TODO swap these to valuePath, typePath in flatten
|
|
190
198
|
(_t, _v, _setter, typePath, valuePath) => {
|
|
191
199
|
return this.synthesizeFieldByPaths(
|
|
@@ -222,7 +230,7 @@ let FormModel = (() => {
|
|
|
222
230
|
const accessor = this.getAccessorForValuePath(valuePath);
|
|
223
231
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
224
232
|
const fieldTypeDef = this.flattenedTypeDefs[typePath];
|
|
225
|
-
const context = this.toContext(this.
|
|
233
|
+
const context = this.toContext(this.observableValue, valuePath);
|
|
226
234
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
227
235
|
const defaultValue = create(valuePath, context);
|
|
228
236
|
const { value, required, readonly, } = convert(accessor != null
|
|
@@ -306,8 +314,8 @@ let FormModel = (() => {
|
|
|
306
314
|
return this.accessors[valuePath];
|
|
307
315
|
}
|
|
308
316
|
get accessors() {
|
|
309
|
-
return flattenAccessorsOfType(this.type, this.
|
|
310
|
-
this.
|
|
317
|
+
return flattenAccessorsOfType(this.type, this.observableValue, (value) => {
|
|
318
|
+
this.observableValue = mobxCopy(this.type, value);
|
|
311
319
|
}, this.listIndicesToKeys);
|
|
312
320
|
}
|
|
313
321
|
maybeGetAdapterForValuePath(valuePath) {
|
|
@@ -327,7 +335,7 @@ let FormModel = (() => {
|
|
|
327
335
|
}
|
|
328
336
|
get valueChanged() {
|
|
329
337
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
330
|
-
return !equals(this.type, this.
|
|
338
|
+
return !equals(this.type, this.observableValue, this.originalValue);
|
|
331
339
|
}
|
|
332
340
|
typePath(valuePath) {
|
|
333
341
|
return valuePathToTypePath(this.type, valuePath, true);
|
|
@@ -354,7 +362,7 @@ let FormModel = (() => {
|
|
|
354
362
|
elementTypePath,
|
|
355
363
|
// TODO what can we use for the value path here?
|
|
356
364
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
357
|
-
this.toContext(this.
|
|
365
|
+
this.toContext(this.observableValue, valuePath));
|
|
358
366
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
359
367
|
const originalList = accessor.value;
|
|
360
368
|
const newList = [
|
|
@@ -400,7 +408,7 @@ let FormModel = (() => {
|
|
|
400
408
|
const { revert } = this.getAdapterForValuePath(valuePath);
|
|
401
409
|
assertExists(revert, 'setting value not supported {}', valuePath);
|
|
402
410
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions, @typescript-eslint/no-explicit-any
|
|
403
|
-
const conversion = revert(value, valuePath, this.toContext(this.
|
|
411
|
+
const conversion = revert(value, valuePath, this.toContext(this.observableValue, valuePath));
|
|
404
412
|
const accessor = this.getAccessorForValuePath(valuePath);
|
|
405
413
|
return runInAction(() => {
|
|
406
414
|
this.fieldOverrides[valuePath] = [value];
|
|
@@ -455,7 +463,7 @@ let FormModel = (() => {
|
|
|
455
463
|
}
|
|
456
464
|
const { convert, create, } = adapter;
|
|
457
465
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
458
|
-
const context = this.toContext(this.
|
|
466
|
+
const context = this.toContext(this.observableValue, valuePath);
|
|
459
467
|
const value = create(valuePath, context);
|
|
460
468
|
const { value: displayValue, } = convert(value, valuePath, context);
|
|
461
469
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
@@ -472,11 +480,11 @@ let FormModel = (() => {
|
|
|
472
480
|
// TODO this isn't correct, should reload from value
|
|
473
481
|
this.fieldOverrides = {};
|
|
474
482
|
this.errorOverrides = {};
|
|
475
|
-
this.
|
|
483
|
+
this.observableValue = mobxCopy(this.type, value);
|
|
476
484
|
});
|
|
477
485
|
}
|
|
478
486
|
isValuePathActive(valuePath) {
|
|
479
|
-
const values = flattenValuesOfType(this.type, this.
|
|
487
|
+
const values = flattenValuesOfType(this.type, this.observableValue, this.listIndicesToKeys);
|
|
480
488
|
const keys = new Set(Object.keys(values));
|
|
481
489
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
482
490
|
return keys.has(valuePath);
|
|
@@ -516,19 +524,15 @@ let FormModel = (() => {
|
|
|
516
524
|
return displayedValue !== originalDisplayedValue;
|
|
517
525
|
}
|
|
518
526
|
validateField(valuePath, validation = Validation.Always) {
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
delete this.errorOverrides[valuePath];
|
|
522
|
-
});
|
|
527
|
+
this.validation[valuePath] = validation;
|
|
528
|
+
delete this.errorOverrides[valuePath];
|
|
523
529
|
return this.fields[valuePath].error == null;
|
|
524
530
|
}
|
|
525
531
|
validateAll(validation = Validation.Always) {
|
|
526
532
|
const accessors = toArray(this.accessors);
|
|
527
|
-
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
this.validation[valuePath] = validation;
|
|
531
|
-
});
|
|
533
|
+
accessors.forEach(([valuePath]) => {
|
|
534
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
535
|
+
this.validation[valuePath] = validation;
|
|
532
536
|
});
|
|
533
537
|
return accessors.every(([valuePath]) => {
|
|
534
538
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
@@ -540,30 +544,38 @@ let FormModel = (() => {
|
|
|
540
544
|
return this.validateAll();
|
|
541
545
|
}
|
|
542
546
|
},
|
|
543
|
-
|
|
547
|
+
_FormModel_observableValue_accessor_storage = new WeakMap(),
|
|
544
548
|
_FormModel_fieldOverrides_accessor_storage = new WeakMap(),
|
|
545
549
|
_FormModel_errorOverrides_accessor_storage = new WeakMap(),
|
|
546
550
|
_FormModel_validation_accessor_storage = new WeakMap(),
|
|
547
551
|
(() => {
|
|
548
552
|
const _metadata = typeof Symbol === "function" && Symbol.metadata ? Object.create(null) : void 0;
|
|
549
|
-
|
|
553
|
+
_observableValue_decorators = [(_b = observable).ref.bind(_b)];
|
|
550
554
|
_fieldOverrides_decorators = [(_c = observable).shallow.bind(_c)];
|
|
551
555
|
_errorOverrides_decorators = [(_d = observable).shallow.bind(_d)];
|
|
552
556
|
_validation_decorators = [(_e = observable).shallow.bind(_e)];
|
|
557
|
+
_get_value_decorators = [computed];
|
|
553
558
|
_get_fields_decorators = [computed];
|
|
554
559
|
_get_knownFields_decorators = [computed];
|
|
555
560
|
_get_accessors_decorators = [computed];
|
|
556
561
|
_get_dirty_decorators = [computed];
|
|
557
562
|
_get_valueChanged_decorators = [computed];
|
|
558
|
-
|
|
563
|
+
_setFieldValue_decorators = [action];
|
|
564
|
+
_validateField_decorators = [action];
|
|
565
|
+
_validateAll_decorators = [action];
|
|
566
|
+
__esDecorate(_a, null, _observableValue_decorators, { kind: "accessor", name: "observableValue", static: false, private: false, access: { has: obj => "observableValue" in obj, get: obj => obj.observableValue, set: (obj, value) => { obj.observableValue = value; } }, metadata: _metadata }, _observableValue_initializers, _observableValue_extraInitializers);
|
|
559
567
|
__esDecorate(_a, null, _fieldOverrides_decorators, { kind: "accessor", name: "fieldOverrides", static: false, private: false, access: { has: obj => "fieldOverrides" in obj, get: obj => obj.fieldOverrides, set: (obj, value) => { obj.fieldOverrides = value; } }, metadata: _metadata }, _fieldOverrides_initializers, _fieldOverrides_extraInitializers);
|
|
560
568
|
__esDecorate(_a, null, _errorOverrides_decorators, { kind: "accessor", name: "errorOverrides", static: false, private: false, access: { has: obj => "errorOverrides" in obj, get: obj => obj.errorOverrides, set: (obj, value) => { obj.errorOverrides = value; } }, metadata: _metadata }, _errorOverrides_initializers, _errorOverrides_extraInitializers);
|
|
561
569
|
__esDecorate(_a, null, _validation_decorators, { kind: "accessor", name: "validation", static: false, private: false, access: { has: obj => "validation" in obj, get: obj => obj.validation, set: (obj, value) => { obj.validation = value; } }, metadata: _metadata }, _validation_initializers, _validation_extraInitializers);
|
|
570
|
+
__esDecorate(_a, null, _get_value_decorators, { kind: "getter", name: "value", static: false, private: false, access: { has: obj => "value" in obj, get: obj => obj.value }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
562
571
|
__esDecorate(_a, null, _get_fields_decorators, { kind: "getter", name: "fields", static: false, private: false, access: { has: obj => "fields" in obj, get: obj => obj.fields }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
563
572
|
__esDecorate(_a, null, _get_knownFields_decorators, { kind: "getter", name: "knownFields", static: false, private: false, access: { has: obj => "knownFields" in obj, get: obj => obj.knownFields }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
564
573
|
__esDecorate(_a, null, _get_accessors_decorators, { kind: "getter", name: "accessors", static: false, private: false, access: { has: obj => "accessors" in obj, get: obj => obj.accessors }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
565
574
|
__esDecorate(_a, null, _get_dirty_decorators, { kind: "getter", name: "dirty", static: false, private: false, access: { has: obj => "dirty" in obj, get: obj => obj.dirty }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
566
575
|
__esDecorate(_a, null, _get_valueChanged_decorators, { kind: "getter", name: "valueChanged", static: false, private: false, access: { has: obj => "valueChanged" in obj, get: obj => obj.valueChanged }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
576
|
+
__esDecorate(_a, null, _setFieldValue_decorators, { kind: "method", name: "setFieldValue", static: false, private: false, access: { has: obj => "setFieldValue" in obj, get: obj => obj.setFieldValue }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
577
|
+
__esDecorate(_a, null, _validateField_decorators, { kind: "method", name: "validateField", static: false, private: false, access: { has: obj => "validateField" in obj, get: obj => obj.validateField }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
578
|
+
__esDecorate(_a, null, _validateAll_decorators, { kind: "method", name: "validateAll", static: false, private: false, access: { has: obj => "validateAll" in obj, get: obj => obj.validateAll }, metadata: _metadata }, null, _instanceExtraInitializers);
|
|
567
579
|
if (_metadata) Object.defineProperty(_a, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
568
580
|
})(),
|
|
569
581
|
_a;
|
package/.out/core/mobx/hooks.js
CHANGED
|
@@ -1,8 +1,10 @@
|
|
|
1
1
|
import { useCallback, } from 'react';
|
|
2
2
|
import { Validation, } from './FormModel';
|
|
3
|
+
import { peek } from './peek';
|
|
3
4
|
export function useDefaultMobxFormHooks(model, { onValidFieldSubmit, onValidFormSubmit, } = {}) {
|
|
4
5
|
const onFieldValueChange = useCallback(function (path, value) {
|
|
5
|
-
const
|
|
6
|
+
const activeValidation = peek(() => model.getValidation(path));
|
|
7
|
+
const validation = Math.min(activeValidation, Validation.Changed);
|
|
6
8
|
model.setFieldValue(path, value, validation);
|
|
7
9
|
}, [model]);
|
|
8
10
|
const onFieldSubmit = useCallback(function (valuePath) {
|
|
@@ -19,16 +21,23 @@ export function useDefaultMobxFormHooks(model, { onValidFieldSubmit, onValidForm
|
|
|
19
21
|
// (e.g. changing a discriminator)
|
|
20
22
|
// TODO debounce?
|
|
21
23
|
setTimeout(function () {
|
|
24
|
+
const [validate, activeValidation,] = peek(() => [
|
|
25
|
+
model.isValuePathActive(path) && model.isFieldDirty(path) && model.fields[path].error == null,
|
|
26
|
+
model.getValidation(path),
|
|
27
|
+
]);
|
|
22
28
|
// only start validation if the user has changed the field and there isn't already an error visible
|
|
23
|
-
if (
|
|
29
|
+
if (validate) {
|
|
30
|
+
const validation = Math.max(Validation.Changed, activeValidation);
|
|
24
31
|
// further workaround to make sure we don't downgrade the existing validation
|
|
25
|
-
model.validateField(path,
|
|
32
|
+
model.validateField(path, validation);
|
|
26
33
|
}
|
|
27
34
|
}, 100);
|
|
28
35
|
}, [model]);
|
|
29
36
|
const onFormSubmit = useCallback(function () {
|
|
30
|
-
|
|
31
|
-
|
|
37
|
+
const valid = peek(() => model.validateSubmit());
|
|
38
|
+
if (valid && onValidFormSubmit) {
|
|
39
|
+
const value = peek(() => model.value);
|
|
40
|
+
onValidFormSubmit(value);
|
|
32
41
|
}
|
|
33
42
|
}, [
|
|
34
43
|
model,
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
import { when } from 'mobx';
|
|
2
|
+
/**
|
|
3
|
+
* Used for when you want to look at the value of an observable without observing it (or triggering
|
|
4
|
+
* the mobx runtime linter)
|
|
5
|
+
*/
|
|
6
|
+
export function peek(operation) {
|
|
7
|
+
let result;
|
|
8
|
+
// when will make mobx think we are observing the value
|
|
9
|
+
void when(() => {
|
|
10
|
+
// trick mobx runtime linting
|
|
11
|
+
result = operation();
|
|
12
|
+
return true;
|
|
13
|
+
});
|
|
14
|
+
// biome-ignore lint/style/noNonNullAssertion: the result is always there
|
|
15
|
+
return result;
|
|
16
|
+
}
|
package/.out/index.d.ts
CHANGED
|
@@ -7,6 +7,7 @@ export * from './core/mobx/FormModel';
|
|
|
7
7
|
export * from './core/mobx/hooks';
|
|
8
8
|
export * from './core/mobx/mergeFieldAdaptersWithTwoWayConverter';
|
|
9
9
|
export * from './core/mobx/mergeFieldAdaptersWithValidators';
|
|
10
|
+
export * from './core/mobx/peek';
|
|
10
11
|
export * from './core/mobx/subFormFieldAdapters';
|
|
11
12
|
export * from './core/props';
|
|
12
13
|
export * from './field_converters/IntegerToStringConverter';
|
package/.out/index.js
CHANGED
|
@@ -7,6 +7,7 @@ export * from './core/mobx/FormModel';
|
|
|
7
7
|
export * from './core/mobx/hooks';
|
|
8
8
|
export * from './core/mobx/mergeFieldAdaptersWithTwoWayConverter';
|
|
9
9
|
export * from './core/mobx/mergeFieldAdaptersWithValidators';
|
|
10
|
+
export * from './core/mobx/peek';
|
|
10
11
|
export * from './core/mobx/subFormFieldAdapters';
|
|
11
12
|
export * from './core/props';
|
|
12
13
|
export * from './field_converters/IntegerToStringConverter';
|