@strictly/react-form 0.0.15 → 0.0.16
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/core/mobx/field_adapter_builder.d.ts +1 -1
- package/.out/core/mobx/form_model.d.ts +3 -4
- package/.out/core/mobx/form_model.js +27 -23
- package/.out/core/mobx/specs/form_model.tests.js +18 -8
- package/.out/core/mobx/types.d.ts +4 -4
- package/.out/index.d.ts +0 -1
- package/.out/index.js +0 -1
- package/.out/mantine/create_field_view.d.ts +20 -0
- package/.out/mantine/create_field_view.js +54 -0
- package/.out/mantine/create_list.js +3 -2
- package/.out/mantine/hooks.d.ts +4 -1
- package/.out/mantine/hooks.js +13 -1
- package/.out/mantine/specs/field_view_hooks.stories.d.ts +12 -0
- package/.out/mantine/specs/field_view_hooks.stories.js +61 -0
- package/.out/mantine/specs/field_view_hooks.tests.d.ts +1 -0
- package/.out/mantine/specs/field_view_hooks.tests.js +12 -0
- package/.out/tsconfig.tsbuildinfo +1 -1
- package/.turbo/turbo-build.log +8 -8
- package/.turbo/turbo-check-types.log +1 -1
- package/core/mobx/field_adapter_builder.ts +2 -2
- package/core/mobx/form_model.ts +43 -27
- package/core/mobx/specs/form_model.tests.ts +28 -11
- package/core/mobx/types.ts +4 -4
- package/dist/index.cjs +124 -70
- package/dist/index.d.cts +26 -26
- package/dist/index.d.ts +26 -26
- package/dist/index.js +121 -62
- package/index.ts +0 -1
- package/mantine/create_field_view.tsx +94 -0
- package/mantine/create_list.tsx +9 -2
- package/mantine/hooks.tsx +18 -1
- package/mantine/specs/__snapshots__/field_view_hooks.tests.tsx.snap +153 -0
- package/mantine/specs/field_view_hooks.stories.tsx +112 -0
- package/mantine/specs/field_view_hooks.tests.tsx +15 -0
- package/package.json +1 -1
- package/.out/mantine/field_view.d.ts +0 -18
- package/.out/mantine/field_view.js +0 -16
- package/mantine/field_view.tsx +0 -39
package/.turbo/turbo-build.log
CHANGED
|
@@ -7,12 +7,12 @@ $ tsup
|
|
|
7
7
|
[34mCLI[39m Target: es6
|
|
8
8
|
[34mCJS[39m Build start
|
|
9
9
|
[34mESM[39m Build start
|
|
10
|
-
[32mESM[39m [1mdist/index.js [22m[
|
|
11
|
-
[32mESM[39m ⚡️ Build success in
|
|
12
|
-
[32mCJS[39m [1mdist/index.cjs [22m[
|
|
13
|
-
[32mCJS[39m ⚡️ Build success in
|
|
10
|
+
[32mESM[39m [1mdist/index.js [22m[32m57.40 KB[39m
|
|
11
|
+
[32mESM[39m ⚡️ Build success in 138ms
|
|
12
|
+
[32mCJS[39m [1mdist/index.cjs [22m[32m61.39 KB[39m
|
|
13
|
+
[32mCJS[39m ⚡️ Build success in 139ms
|
|
14
14
|
[34mDTS[39m Build start
|
|
15
|
-
[32mDTS[39m ⚡️ Build success in
|
|
16
|
-
[32mDTS[39m [1mdist/index.d.cts [22m[32m37.
|
|
17
|
-
[32mDTS[39m [1mdist/index.d.ts [22m[32m37.
|
|
18
|
-
Done in 10.
|
|
15
|
+
[32mDTS[39m ⚡️ Build success in 9840ms
|
|
16
|
+
[32mDTS[39m [1mdist/index.d.cts [22m[32m37.86 KB[39m
|
|
17
|
+
[32mDTS[39m [1mdist/index.d.ts [22m[32m37.86 KB[39m
|
|
18
|
+
Done in 10.97s.
|
|
@@ -336,8 +336,8 @@ export function trimmingStringAdapter<
|
|
|
336
336
|
|
|
337
337
|
export function listAdapter<
|
|
338
338
|
E,
|
|
339
|
-
ValuePath extends string,
|
|
340
|
-
Context,
|
|
339
|
+
ValuePath extends string = string,
|
|
340
|
+
Context = unknown,
|
|
341
341
|
>() {
|
|
342
342
|
return new FieldAdapterBuilder<readonly E[], readonly E[], never, ValuePath, Context>(
|
|
343
343
|
annotatedIdentityConverter<readonly E[], ValuePath, Context>(false),
|
package/core/mobx/form_model.ts
CHANGED
|
@@ -105,11 +105,18 @@ export type ValuePathsToAdaptersOf<
|
|
|
105
105
|
: never
|
|
106
106
|
|
|
107
107
|
export type ContextOf<TypePathsToAdapters extends Partial<Readonly<Record<string, FieldAdapter>>>> =
|
|
108
|
-
UnionToIntersection<
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
108
|
+
UnionToIntersection<
|
|
109
|
+
| {
|
|
110
|
+
readonly [
|
|
111
|
+
K in keyof TypePathsToAdapters
|
|
112
|
+
]: TypePathsToAdapters[K] extends undefined ? undefined
|
|
113
|
+
// ignore unspecified values
|
|
114
|
+
: unknown extends ContextOfFieldAdapter<NonNullable<TypePathsToAdapters[K]>> ? never
|
|
115
|
+
: ContextOfFieldAdapter<NonNullable<TypePathsToAdapters[K]>>
|
|
116
|
+
}[keyof TypePathsToAdapters]
|
|
117
|
+
// ensure we have at least one thing to intersect (can end up with a `never` context otherwise)
|
|
118
|
+
| {}
|
|
119
|
+
>
|
|
113
120
|
|
|
114
121
|
export abstract class FormModel<
|
|
115
122
|
T extends Type,
|
|
@@ -140,7 +147,6 @@ export abstract class FormModel<
|
|
|
140
147
|
) {
|
|
141
148
|
this.value = mobxCopy(type, value)
|
|
142
149
|
this.flattenedTypeDefs = flattenTypesOfType(type)
|
|
143
|
-
const contextValue = this.toContext(value)
|
|
144
150
|
// pre-populate field overrides for consistent behavior when default information is overwritten
|
|
145
151
|
// then returned to
|
|
146
152
|
const conversions = flattenValueTo(
|
|
@@ -149,11 +155,14 @@ export abstract class FormModel<
|
|
|
149
155
|
() => {},
|
|
150
156
|
(
|
|
151
157
|
_t: StrictTypeDef,
|
|
152
|
-
|
|
158
|
+
fieldValue: AnyValueType,
|
|
153
159
|
_setter,
|
|
154
160
|
typePath,
|
|
155
161
|
valuePath,
|
|
156
162
|
): AnnotatedFieldConversion<FieldOverride> | undefined => {
|
|
163
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
164
|
+
const contextValue = this.toContext(value, valuePath as keyof ValuePathsToAdapters)
|
|
165
|
+
|
|
157
166
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
158
167
|
const adapter = this.adapters[typePath as keyof TypePathsToAdapters]
|
|
159
168
|
if (adapter == null) {
|
|
@@ -168,7 +177,7 @@ export abstract class FormModel<
|
|
|
168
177
|
return
|
|
169
178
|
}
|
|
170
179
|
// cannot call this.context yet as the "this" pointer has not been fully created
|
|
171
|
-
return convert(
|
|
180
|
+
return convert(fieldValue, valuePath, contextValue)
|
|
172
181
|
},
|
|
173
182
|
)
|
|
174
183
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
@@ -177,12 +186,10 @@ export abstract class FormModel<
|
|
|
177
186
|
}) as FlattenedFieldOverrides<ValuePathsToAdapters>
|
|
178
187
|
}
|
|
179
188
|
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
protected abstract toContext(value: ValueOfType<ReadonlyTypeOfType<T>>): ContextType
|
|
189
|
+
protected abstract toContext(
|
|
190
|
+
value: ValueOfType<ReadonlyTypeOfType<T>>,
|
|
191
|
+
valuePath: keyof ValuePathsToAdapters,
|
|
192
|
+
): ContextType
|
|
186
193
|
|
|
187
194
|
@computed
|
|
188
195
|
get fields(): SimplifyDeep<FlattenedConvertedFieldsOf<ValuePathsToAdapters>> {
|
|
@@ -256,6 +263,7 @@ export abstract class FormModel<
|
|
|
256
263
|
const accessor = this.getAccessorForValuePath(valuePath)
|
|
257
264
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
258
265
|
const fieldTypeDef = this.flattenedTypeDefs[typePath as string]
|
|
266
|
+
const context = this.toContext(this.value, valuePath)
|
|
259
267
|
const {
|
|
260
268
|
value,
|
|
261
269
|
required,
|
|
@@ -267,14 +275,14 @@ export abstract class FormModel<
|
|
|
267
275
|
? mobxCopy(
|
|
268
276
|
fieldTypeDef,
|
|
269
277
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
270
|
-
create(valuePath as string,
|
|
278
|
+
create(valuePath as string, context),
|
|
271
279
|
)
|
|
272
280
|
// fake values can't be copied
|
|
273
281
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
274
|
-
: create(valuePath as string,
|
|
282
|
+
: create(valuePath as string, context),
|
|
275
283
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
276
284
|
valuePath as string,
|
|
277
|
-
|
|
285
|
+
context,
|
|
278
286
|
)
|
|
279
287
|
const error = this.errors[valuePath]
|
|
280
288
|
return {
|
|
@@ -360,7 +368,9 @@ export abstract class FormModel<
|
|
|
360
368
|
: elementAdapter.create(
|
|
361
369
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
362
370
|
elementTypePath as string,
|
|
363
|
-
|
|
371
|
+
// TODO what can we use for the value path here?
|
|
372
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
373
|
+
this.toContext(this.value, valuePath as unknown as keyof ValuePathsToAdapters),
|
|
364
374
|
)
|
|
365
375
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
366
376
|
const originalList: any[] = accessor.value
|
|
@@ -505,7 +515,7 @@ export abstract class FormModel<
|
|
|
505
515
|
assertExists(revert, 'setting value not supported {}', valuePath)
|
|
506
516
|
|
|
507
517
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions, @typescript-eslint/no-explicit-any
|
|
508
|
-
const conversion = revert(value, valuePath as any, this.
|
|
518
|
+
const conversion = revert(value, valuePath as any, this.toContext(this.value, valuePath))
|
|
509
519
|
const accessor = this.getAccessorForValuePath(valuePath)
|
|
510
520
|
return runInAction(() => {
|
|
511
521
|
this.fieldOverrides[valuePath] = [value]
|
|
@@ -548,10 +558,12 @@ export abstract class FormModel<
|
|
|
548
558
|
convert,
|
|
549
559
|
create,
|
|
550
560
|
} = adapter
|
|
551
|
-
|
|
561
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
562
|
+
const context = this.toContext(this.value, valuePath as unknown as keyof ValuePathsToAdapters)
|
|
563
|
+
const value = create(valuePath, context)
|
|
552
564
|
const {
|
|
553
565
|
value: displayValue,
|
|
554
|
-
} = convert(value, valuePath,
|
|
566
|
+
} = convert(value, valuePath, context)
|
|
555
567
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
556
568
|
const key = valuePath as unknown as keyof ValuePathsToAdapters
|
|
557
569
|
runInAction(() => {
|
|
@@ -586,16 +598,18 @@ export abstract class FormModel<
|
|
|
586
598
|
} = this.getAdapterForValuePath(valuePath)
|
|
587
599
|
const fieldOverride = this.fieldOverrides[valuePath]
|
|
588
600
|
const accessor = this.getAccessorForValuePath(valuePath)
|
|
601
|
+
const context = this.toContext(this.value, valuePath)
|
|
602
|
+
|
|
589
603
|
const {
|
|
590
604
|
value: storedValue,
|
|
591
605
|
} = convert(
|
|
592
606
|
accessor != null
|
|
593
607
|
? accessor.value
|
|
594
608
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
595
|
-
: create(valuePath as string,
|
|
609
|
+
: create(valuePath as string, context),
|
|
596
610
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
597
611
|
valuePath as string,
|
|
598
|
-
|
|
612
|
+
context,
|
|
599
613
|
)
|
|
600
614
|
const value = fieldOverride != null
|
|
601
615
|
? fieldOverride[0]
|
|
@@ -605,13 +619,13 @@ export abstract class FormModel<
|
|
|
605
619
|
if (ignoreDefaultValue) {
|
|
606
620
|
const {
|
|
607
621
|
value: defaultDisplayValue,
|
|
608
|
-
} = convert(create(valuePath,
|
|
622
|
+
} = convert(create(valuePath, context), valuePath, context)
|
|
609
623
|
if (defaultDisplayValue === value) {
|
|
610
624
|
return true
|
|
611
625
|
}
|
|
612
626
|
}
|
|
613
627
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
614
|
-
const conversion = revert(value, valuePath as string,
|
|
628
|
+
const conversion = revert(value, valuePath as string, context)
|
|
615
629
|
return runInAction(() => {
|
|
616
630
|
switch (conversion.type) {
|
|
617
631
|
case UnreliableFieldConversionType.Failure:
|
|
@@ -662,16 +676,18 @@ export abstract class FormModel<
|
|
|
662
676
|
return success
|
|
663
677
|
}
|
|
664
678
|
const fieldOverride = this.fieldOverrides[adapterPath]
|
|
679
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
680
|
+
const context = this.toContext(this.value, valuePath as keyof ValuePathsToAdapters)
|
|
665
681
|
const {
|
|
666
682
|
value: storedValue,
|
|
667
|
-
} = convert(accessor.value, valuePath,
|
|
683
|
+
} = convert(accessor.value, valuePath, context)
|
|
668
684
|
const value = fieldOverride != null
|
|
669
685
|
? fieldOverride[0]
|
|
670
686
|
: storedValue
|
|
671
687
|
// TODO more nuanced comparison
|
|
672
688
|
const dirty = fieldOverride != null && fieldOverride[0] !== storedValue
|
|
673
689
|
|
|
674
|
-
const conversion = revert(value, valuePath,
|
|
690
|
+
const conversion = revert(value, valuePath, context)
|
|
675
691
|
switch (conversion.type) {
|
|
676
692
|
case UnreliableFieldConversionType.Failure:
|
|
677
693
|
this.errors[adapterPath] = conversion.error
|
|
@@ -13,7 +13,9 @@ import {
|
|
|
13
13
|
type ValueOfType,
|
|
14
14
|
type ValueToTypePathsOfType,
|
|
15
15
|
} from '@strictly/define'
|
|
16
|
-
import {
|
|
16
|
+
import {
|
|
17
|
+
type FieldAdapter,
|
|
18
|
+
} from 'core/mobx/field_adapter'
|
|
17
19
|
import {
|
|
18
20
|
adapterFromTwoWayConverter,
|
|
19
21
|
identityAdapter,
|
|
@@ -27,7 +29,9 @@ import { IntegerToStringConverter } from 'field_converters/integer_to_string_con
|
|
|
27
29
|
import { NullableToBooleanConverter } from 'field_converters/nullable_to_boolean_converter'
|
|
28
30
|
import { SelectDiscriminatedUnionConverter } from 'field_converters/select_value_type_converter'
|
|
29
31
|
import { prototypingFieldValueFactory } from 'field_value_factories/prototyping_field_value_factory'
|
|
30
|
-
import {
|
|
32
|
+
import {
|
|
33
|
+
type Simplify,
|
|
34
|
+
} from 'type-fest'
|
|
31
35
|
import { type Field } from 'types/field'
|
|
32
36
|
import {
|
|
33
37
|
UnreliableFieldConversionType,
|
|
@@ -54,9 +58,13 @@ class TestFormModel<
|
|
|
54
58
|
{}
|
|
55
59
|
>,
|
|
56
60
|
> extends FormModel<T, ValueToTypePaths, TypePathsToAdapters, {}> {
|
|
57
|
-
override toContext(
|
|
61
|
+
override toContext(
|
|
62
|
+
value: ValueOfType<T>,
|
|
63
|
+
valuePath: keyof ValuePathsToAdaptersOf<TypePathsToAdapters, ValueToTypePaths>,
|
|
64
|
+
) {
|
|
58
65
|
return {
|
|
59
|
-
|
|
66
|
+
value,
|
|
67
|
+
valuePath,
|
|
60
68
|
}
|
|
61
69
|
}
|
|
62
70
|
}
|
|
@@ -740,10 +748,10 @@ describe('all', function () {
|
|
|
740
748
|
|
|
741
749
|
// no longer passes context, but will pass context eventually again
|
|
742
750
|
describe('passes context', function () {
|
|
743
|
-
let contextCopy:
|
|
751
|
+
let contextCopy: string
|
|
744
752
|
beforeEach(function () {
|
|
745
753
|
integerToStringAdapter.revert.mockImplementationOnce(function (_value, _path, context) {
|
|
746
|
-
contextCopy =
|
|
754
|
+
contextCopy = JSON.stringify(context)
|
|
747
755
|
return {
|
|
748
756
|
type: UnreliableFieldConversionType.Success,
|
|
749
757
|
value: 1,
|
|
@@ -751,7 +759,7 @@ describe('all', function () {
|
|
|
751
759
|
})
|
|
752
760
|
})
|
|
753
761
|
|
|
754
|
-
it('supplies the
|
|
762
|
+
it('supplies the context when converting', function () {
|
|
755
763
|
model.setFieldValueAndValidate('$.2', '4')
|
|
756
764
|
|
|
757
765
|
expect(integerToStringAdapter.revert).toHaveBeenCalledOnce()
|
|
@@ -759,14 +767,23 @@ describe('all', function () {
|
|
|
759
767
|
'4',
|
|
760
768
|
'$.2',
|
|
761
769
|
{
|
|
762
|
-
|
|
770
|
+
// the supplied value isn't a copy, so it will be the model value, even
|
|
771
|
+
// if the value has since changed
|
|
772
|
+
value: model.value,
|
|
773
|
+
valuePath: '$.2',
|
|
763
774
|
},
|
|
764
775
|
)
|
|
765
776
|
})
|
|
766
777
|
|
|
767
|
-
it('supplies the context', function () {
|
|
768
|
-
|
|
769
|
-
|
|
778
|
+
it('supplies the correct context value at the time it is being checked', function () {
|
|
779
|
+
// the copy will show the supplied value however
|
|
780
|
+
expect(JSON.parse(contextCopy)).toEqual({
|
|
781
|
+
value: [
|
|
782
|
+
1,
|
|
783
|
+
3,
|
|
784
|
+
7,
|
|
785
|
+
],
|
|
786
|
+
valuePath: '$.2',
|
|
770
787
|
})
|
|
771
788
|
})
|
|
772
789
|
})
|
package/core/mobx/types.ts
CHANGED
|
@@ -6,7 +6,7 @@ import {
|
|
|
6
6
|
} from './form_model'
|
|
7
7
|
|
|
8
8
|
/**
|
|
9
|
-
* Used to extract the supported value paths from a
|
|
9
|
+
* Used to extract the supported value paths from a model
|
|
10
10
|
*/
|
|
11
11
|
export type ValuePathsOfModel<
|
|
12
12
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -22,7 +22,7 @@ export type ValuePathsOfModel<
|
|
|
22
22
|
|
|
23
23
|
/**
|
|
24
24
|
* Used to extract the render type (so the value that is passed to the view) of a given value path
|
|
25
|
-
* from a
|
|
25
|
+
* from a model
|
|
26
26
|
*/
|
|
27
27
|
export type ToValueOfModelValuePath<
|
|
28
28
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
@@ -38,9 +38,9 @@ export type ToValueOfModelValuePath<
|
|
|
38
38
|
: never
|
|
39
39
|
|
|
40
40
|
/**
|
|
41
|
-
* Extracts the form fields from
|
|
41
|
+
* Extracts the form fields from a form model. The recommended way is to
|
|
42
42
|
* define the form fields explicitly and use that type to enforce the types
|
|
43
|
-
* of your converters, but generating the FormFields from your
|
|
43
|
+
* of your converters, but generating the FormFields from your model
|
|
44
44
|
* is less typing, albeit at the cost of potentially getting type errors
|
|
45
45
|
* reported a long way away from the source
|
|
46
46
|
*/
|