@strictly/react-form 0.0.26 → 0.0.28
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/form_model.d.ts +3 -0
- package/.out/core/mobx/form_model.js +48 -91
- package/.out/core/mobx/hooks.js +2 -2
- package/.out/core/mobx/specs/form_model.tests.js +14 -12
- package/.out/mantine/create_list.d.ts +2 -1
- package/.out/mantine/create_list.js +15 -3
- package/.out/mantine/specs/list_hooks.stories.js +8 -0
- package/.out/tsconfig.tsbuildinfo +1 -1
- package/.out/types/field.d.ts +1 -0
- package/.turbo/turbo-build.log +8 -8
- package/.turbo/turbo-check-types.log +1 -1
- package/core/mobx/form_model.ts +47 -106
- package/core/mobx/hooks.tsx +2 -2
- package/core/mobx/specs/form_model.tests.ts +14 -12
- package/dist/index.cjs +79 -110
- package/dist/index.d.cts +6 -1
- package/dist/index.d.ts +6 -1
- package/dist/index.js +70 -100
- package/mantine/create_list.tsx +27 -3
- package/mantine/specs/__snapshots__/list_hooks.tests.tsx.snap +3 -3
- package/mantine/specs/list_hooks.stories.tsx +8 -0
- package/package.json +1 -1
- package/types/field.ts +1 -0
package/dist/index.js
CHANGED
|
@@ -306,7 +306,6 @@ function listAdapter() {
|
|
|
306
306
|
import {
|
|
307
307
|
assertExists,
|
|
308
308
|
assertExistsAndReturn,
|
|
309
|
-
assertState,
|
|
310
309
|
checkValidNumber,
|
|
311
310
|
map,
|
|
312
311
|
toArray,
|
|
@@ -333,11 +332,12 @@ var Validation = /* @__PURE__ */ ((Validation2) => {
|
|
|
333
332
|
Validation2[Validation2["Always"] = 2] = "Always";
|
|
334
333
|
return Validation2;
|
|
335
334
|
})(Validation || {});
|
|
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];
|
|
335
|
+
var _valueChanged_dec, _dirty_dec, _accessors_dec, _knownFields_dec, _fields_dec, _validation_dec, _errorOverrides_dec, _fieldOverrides_dec, _value_dec, _init, _value, _fieldOverrides, _errorOverrides, _validation;
|
|
336
|
+
_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], _valueChanged_dec = [computed];
|
|
338
337
|
var FormModel = class {
|
|
339
338
|
constructor(type, originalValue, adapters, mode) {
|
|
340
339
|
this.type = type;
|
|
340
|
+
this.originalValue = originalValue;
|
|
341
341
|
this.adapters = adapters;
|
|
342
342
|
this.mode = mode;
|
|
343
343
|
__runInitializers(_init, 5, this);
|
|
@@ -349,7 +349,9 @@ var FormModel = class {
|
|
|
349
349
|
// cannot be type safe
|
|
350
350
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
351
351
|
__publicField(this, "originalValues");
|
|
352
|
-
|
|
352
|
+
// maintains the value paths of lists when the original order is destroyed by deletes or reordering
|
|
353
|
+
__publicField(this, "listIndicesToKeys", {});
|
|
354
|
+
this.originalValues = flattenValuesOfType(type, originalValue, this.listIndicesToKeys);
|
|
353
355
|
this.value = mobxCopy(type, originalValue);
|
|
354
356
|
this.flattenedTypeDefs = flattenTypesOfType(type);
|
|
355
357
|
const conversions = flattenValueTo(
|
|
@@ -371,7 +373,8 @@ var FormModel = class {
|
|
|
371
373
|
return;
|
|
372
374
|
}
|
|
373
375
|
return convert(fieldValue, valuePath, contextValue);
|
|
374
|
-
}
|
|
376
|
+
},
|
|
377
|
+
this.listIndicesToKeys
|
|
375
378
|
);
|
|
376
379
|
this.fieldOverrides = map(conversions, function(_k, v) {
|
|
377
380
|
return v && [v.value];
|
|
@@ -417,7 +420,8 @@ var FormModel = class {
|
|
|
417
420
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
418
421
|
typePath
|
|
419
422
|
);
|
|
420
|
-
}
|
|
423
|
+
},
|
|
424
|
+
this.listIndicesToKeys
|
|
421
425
|
);
|
|
422
426
|
}
|
|
423
427
|
maybeSynthesizeFieldByValuePath(valuePath) {
|
|
@@ -526,7 +530,9 @@ var FormModel = class {
|
|
|
526
530
|
value: displayedValue,
|
|
527
531
|
error,
|
|
528
532
|
readonly: readonly && !this.forceMutableFields,
|
|
529
|
-
required
|
|
533
|
+
required,
|
|
534
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
535
|
+
listIndexToKey: this.listIndicesToKeys[valuePath]
|
|
530
536
|
};
|
|
531
537
|
}
|
|
532
538
|
getAccessorForValuePath(valuePath) {
|
|
@@ -539,7 +545,8 @@ var FormModel = class {
|
|
|
539
545
|
this.value,
|
|
540
546
|
(value) => {
|
|
541
547
|
this.value = mobxCopy(this.type, value);
|
|
542
|
-
}
|
|
548
|
+
},
|
|
549
|
+
this.listIndicesToKeys
|
|
543
550
|
);
|
|
544
551
|
}
|
|
545
552
|
maybeGetAdapterForValuePath(valuePath) {
|
|
@@ -558,6 +565,9 @@ var FormModel = class {
|
|
|
558
565
|
return this.isFieldDirty(valuePath);
|
|
559
566
|
});
|
|
560
567
|
}
|
|
568
|
+
get valueChanged() {
|
|
569
|
+
return !equals(this.type, this.value, this.originalValue);
|
|
570
|
+
}
|
|
561
571
|
typePath(valuePath) {
|
|
562
572
|
return valuePathToTypePath(this.type, valuePath, true);
|
|
563
573
|
}
|
|
@@ -589,110 +599,47 @@ var FormModel = class {
|
|
|
589
599
|
element,
|
|
590
600
|
...originalList.slice(definedIndex)
|
|
591
601
|
];
|
|
592
|
-
const targetPaths = Object.keys(this.fieldOverrides).filter(function(v) {
|
|
593
|
-
return v.startsWith(`${listValuePath}.`);
|
|
594
|
-
}).map(function(v) {
|
|
595
|
-
const parts = v.substring(listValuePath.length + 1).split(".");
|
|
596
|
-
const index2 = parseInt(parts[0]);
|
|
597
|
-
return [
|
|
598
|
-
index2,
|
|
599
|
-
parts.slice(1)
|
|
600
|
-
];
|
|
601
|
-
}).filter(function([index2]) {
|
|
602
|
-
return index2 >= definedIndex;
|
|
603
|
-
}).sort(function([a], [b]) {
|
|
604
|
-
return b - a;
|
|
605
|
-
});
|
|
606
602
|
runInAction(() => {
|
|
607
|
-
targetPaths.forEach(([
|
|
608
|
-
index2,
|
|
609
|
-
postfix
|
|
610
|
-
]) => {
|
|
611
|
-
const fromJsonPath = [
|
|
612
|
-
listValuePath,
|
|
613
|
-
`${index2}`,
|
|
614
|
-
...postfix
|
|
615
|
-
].join(".");
|
|
616
|
-
const toJsonPath = [
|
|
617
|
-
listValuePath,
|
|
618
|
-
`${index2 + 1}`,
|
|
619
|
-
...postfix
|
|
620
|
-
].join(".");
|
|
621
|
-
const fieldOverride = this.fieldOverrides[fromJsonPath];
|
|
622
|
-
delete this.fieldOverrides[fromJsonPath];
|
|
623
|
-
this.fieldOverrides[toJsonPath] = fieldOverride;
|
|
624
|
-
const validation = this.validation[fromJsonPath];
|
|
625
|
-
delete this.validation[fromJsonPath];
|
|
626
|
-
this.validation[toJsonPath] = validation;
|
|
627
|
-
});
|
|
628
603
|
accessor.set(newList);
|
|
629
604
|
delete this.fieldOverrides[listValuePath];
|
|
605
|
+
const indicesToKeys = assertExistsAndReturn(
|
|
606
|
+
this.listIndicesToKeys[listValuePath],
|
|
607
|
+
"no index to key mapping for list {}",
|
|
608
|
+
listValuePath
|
|
609
|
+
);
|
|
610
|
+
const nextKey = indicesToKeys[indicesToKeys.length - 1];
|
|
611
|
+
indicesToKeys.splice(definedIndex, 0, nextKey);
|
|
612
|
+
indicesToKeys[indicesToKeys.length - 1] = nextKey + 1;
|
|
630
613
|
});
|
|
631
614
|
}
|
|
632
615
|
removeListItem(...elementValuePaths) {
|
|
633
|
-
const orderedElementValuePaths = elementValuePaths.toSorted().reverse();
|
|
634
616
|
runInAction(() => {
|
|
635
|
-
|
|
617
|
+
elementValuePaths.forEach((elementValuePath) => {
|
|
618
|
+
var _a;
|
|
636
619
|
const [
|
|
637
620
|
listValuePath,
|
|
638
|
-
|
|
621
|
+
elementKeyString
|
|
639
622
|
] = assertExistsAndReturn(
|
|
640
623
|
jsonPathPop(elementValuePath),
|
|
641
624
|
"expected a path with two or more segments {}",
|
|
642
625
|
elementValuePath
|
|
643
626
|
);
|
|
644
627
|
const accessor = this.accessors[listValuePath];
|
|
645
|
-
const
|
|
646
|
-
parseInt(
|
|
647
|
-
"unexpected
|
|
648
|
-
|
|
649
|
-
elementValuePath
|
|
650
|
-
);
|
|
651
|
-
const newList = [...accessor.value];
|
|
652
|
-
assertState(
|
|
653
|
-
elementIndex >= 0 && elementIndex < newList.length,
|
|
654
|
-
"invalid index from path {} ({})",
|
|
655
|
-
elementIndex,
|
|
628
|
+
const elementKey = checkValidNumber(
|
|
629
|
+
parseInt(elementKeyString),
|
|
630
|
+
"unexpected id {} ({})",
|
|
631
|
+
elementKeyString,
|
|
656
632
|
elementValuePath
|
|
657
633
|
);
|
|
658
|
-
|
|
659
|
-
const
|
|
660
|
-
|
|
661
|
-
|
|
662
|
-
|
|
663
|
-
|
|
664
|
-
|
|
665
|
-
|
|
666
|
-
|
|
667
|
-
];
|
|
668
|
-
}).filter(function([index]) {
|
|
669
|
-
return index > elementIndex;
|
|
670
|
-
}).sort(function([a], [b]) {
|
|
671
|
-
return a - b;
|
|
672
|
-
});
|
|
673
|
-
targetPaths.forEach(([
|
|
674
|
-
index,
|
|
675
|
-
postfix
|
|
676
|
-
]) => {
|
|
677
|
-
const fromJsonPath = [
|
|
678
|
-
listValuePath,
|
|
679
|
-
`${index}`,
|
|
680
|
-
...postfix
|
|
681
|
-
].join(".");
|
|
682
|
-
const toJsonPath = [
|
|
683
|
-
listValuePath,
|
|
684
|
-
`${index - 1}`,
|
|
685
|
-
...postfix
|
|
686
|
-
].join(".");
|
|
687
|
-
const fieldOverride = this.fieldOverrides[fromJsonPath];
|
|
688
|
-
delete this.fieldOverrides[fromJsonPath];
|
|
689
|
-
this.fieldOverrides[toJsonPath] = fieldOverride;
|
|
690
|
-
const validation = this.validation[fromJsonPath];
|
|
691
|
-
delete this.validation[fromJsonPath];
|
|
692
|
-
this.validation[toJsonPath] = validation;
|
|
693
|
-
});
|
|
694
|
-
accessor.set(newList);
|
|
695
|
-
delete this.fieldOverrides[listValuePath];
|
|
634
|
+
const indicesToKeys = this.listIndicesToKeys[listValuePath];
|
|
635
|
+
const elementIndex = (_a = indicesToKeys == null ? void 0 : indicesToKeys.indexOf(elementKey)) != null ? _a : -1;
|
|
636
|
+
if (elementIndex >= 0) {
|
|
637
|
+
const newList = [...accessor.value];
|
|
638
|
+
newList.splice(elementIndex, 1);
|
|
639
|
+
accessor.set(newList);
|
|
640
|
+
delete this.fieldOverrides[listValuePath];
|
|
641
|
+
indicesToKeys.splice(elementIndex, 1);
|
|
642
|
+
}
|
|
696
643
|
});
|
|
697
644
|
});
|
|
698
645
|
}
|
|
@@ -775,7 +722,7 @@ var FormModel = class {
|
|
|
775
722
|
});
|
|
776
723
|
}
|
|
777
724
|
isValuePathActive(valuePath) {
|
|
778
|
-
const values = flattenValuesOfType(this.type, this.value);
|
|
725
|
+
const values = flattenValuesOfType(this.type, this.value, this.listIndicesToKeys);
|
|
779
726
|
const keys = new Set(Object.keys(values));
|
|
780
727
|
return keys.has(valuePath);
|
|
781
728
|
}
|
|
@@ -855,6 +802,7 @@ __decorateElement(_init, 2, "fields", _fields_dec, FormModel);
|
|
|
855
802
|
__decorateElement(_init, 2, "knownFields", _knownFields_dec, FormModel);
|
|
856
803
|
__decorateElement(_init, 2, "accessors", _accessors_dec, FormModel);
|
|
857
804
|
__decorateElement(_init, 2, "dirty", _dirty_dec, FormModel);
|
|
805
|
+
__decorateElement(_init, 2, "valueChanged", _valueChanged_dec, FormModel);
|
|
858
806
|
__decoratorMetadata(_init, FormModel);
|
|
859
807
|
|
|
860
808
|
// core/mobx/hooks.tsx
|
|
@@ -887,7 +835,7 @@ function useDefaultMobxFormHooks(model, {
|
|
|
887
835
|
const onFieldBlur = useCallback(
|
|
888
836
|
function(path) {
|
|
889
837
|
setTimeout(function() {
|
|
890
|
-
if (model.isValuePathActive(path) && model.isFieldDirty(path)) {
|
|
838
|
+
if (model.isValuePathActive(path) && model.isFieldDirty(path) && model.fields[path].error == null) {
|
|
891
839
|
model.validateField(path, Math.max(1 /* Changed */, model.getValidation(path)));
|
|
892
840
|
}
|
|
893
841
|
}, 100);
|
|
@@ -1606,27 +1554,49 @@ function createForm(valuePath, Form, observableProps) {
|
|
|
1606
1554
|
}
|
|
1607
1555
|
|
|
1608
1556
|
// mantine/create_list.tsx
|
|
1557
|
+
import {
|
|
1558
|
+
assertExistsAndReturn as assertExistsAndReturn2
|
|
1559
|
+
} from "@strictly/base";
|
|
1609
1560
|
import {
|
|
1610
1561
|
Fragment
|
|
1611
1562
|
} from "react";
|
|
1612
1563
|
import { Fragment as Fragment2, jsx as jsx6 } from "react/jsx-runtime";
|
|
1613
1564
|
function createList(valuePath, List) {
|
|
1614
1565
|
const propSource = () => {
|
|
1615
|
-
const
|
|
1566
|
+
const field = this.fields[valuePath];
|
|
1567
|
+
const values = [...field.value];
|
|
1616
1568
|
return {
|
|
1617
1569
|
values,
|
|
1618
|
-
listPath: valuePath
|
|
1570
|
+
listPath: valuePath,
|
|
1571
|
+
indexKeys: assertExistsAndReturn2(field.listIndexToKey, "list index to key mapping missing in {}", valuePath)
|
|
1619
1572
|
};
|
|
1620
1573
|
};
|
|
1621
1574
|
return createUnsafePartialObserverComponent(List, propSource);
|
|
1622
1575
|
}
|
|
1623
1576
|
function DefaultList({
|
|
1624
1577
|
values,
|
|
1578
|
+
indexKeys,
|
|
1625
1579
|
listPath,
|
|
1626
1580
|
children
|
|
1627
1581
|
}) {
|
|
1628
1582
|
return /* @__PURE__ */ jsx6(Fragment2, { children: values.map(function(value, index) {
|
|
1629
|
-
|
|
1583
|
+
return [
|
|
1584
|
+
value,
|
|
1585
|
+
index,
|
|
1586
|
+
indexKeys[index]
|
|
1587
|
+
];
|
|
1588
|
+
}).filter(function([
|
|
1589
|
+
_value2,
|
|
1590
|
+
_index,
|
|
1591
|
+
key
|
|
1592
|
+
]) {
|
|
1593
|
+
return key != null;
|
|
1594
|
+
}).map(function([
|
|
1595
|
+
value,
|
|
1596
|
+
index,
|
|
1597
|
+
key
|
|
1598
|
+
]) {
|
|
1599
|
+
const valuePath = `${listPath}.${key}`;
|
|
1630
1600
|
return /* @__PURE__ */ jsx6(Fragment, { children: children(valuePath, value, index) }, valuePath);
|
|
1631
1601
|
}) });
|
|
1632
1602
|
}
|
package/mantine/create_list.tsx
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import {
|
|
2
|
+
assertExistsAndReturn,
|
|
3
|
+
type ElementOfArray,
|
|
4
|
+
} from '@strictly/base'
|
|
2
5
|
import {
|
|
3
6
|
type ComponentType,
|
|
4
7
|
Fragment,
|
|
@@ -15,6 +18,7 @@ import {
|
|
|
15
18
|
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
|
16
19
|
export type SuppliedListProps<Value = any, ListPath extends string = string> = {
|
|
17
20
|
values: readonly Value[],
|
|
21
|
+
indexKeys: number[],
|
|
18
22
|
listPath: ListPath,
|
|
19
23
|
}
|
|
20
24
|
|
|
@@ -34,10 +38,12 @@ export function createList<
|
|
|
34
38
|
List: ComponentType<Props>,
|
|
35
39
|
): MantineFieldComponent<SuppliedListProps<ElementOfArray<ValueTypeOfField<F[K]>>>, Props, never> {
|
|
36
40
|
const propSource = () => {
|
|
37
|
-
const
|
|
41
|
+
const field = this.fields[valuePath]
|
|
42
|
+
const values = [...field.value]
|
|
38
43
|
return {
|
|
39
44
|
values,
|
|
40
45
|
listPath: valuePath,
|
|
46
|
+
indexKeys: assertExistsAndReturn(field.listIndexToKey, 'list index to key mapping missing in {}', valuePath),
|
|
41
47
|
}
|
|
42
48
|
}
|
|
43
49
|
return createUnsafePartialObserverComponent(List, propSource)
|
|
@@ -48,6 +54,7 @@ export function DefaultList<
|
|
|
48
54
|
ListPath extends string,
|
|
49
55
|
>({
|
|
50
56
|
values,
|
|
57
|
+
indexKeys,
|
|
51
58
|
listPath,
|
|
52
59
|
children,
|
|
53
60
|
}: SuppliedListProps<Value, ListPath> & {
|
|
@@ -56,7 +63,24 @@ export function DefaultList<
|
|
|
56
63
|
return (
|
|
57
64
|
<>
|
|
58
65
|
{values.map(function (value, index) {
|
|
59
|
-
|
|
66
|
+
return [
|
|
67
|
+
value,
|
|
68
|
+
index,
|
|
69
|
+
indexKeys[index],
|
|
70
|
+
] as const
|
|
71
|
+
}).filter(function ([
|
|
72
|
+
_value,
|
|
73
|
+
_index,
|
|
74
|
+
key,
|
|
75
|
+
]) {
|
|
76
|
+
// omit entries without keys
|
|
77
|
+
return key != null
|
|
78
|
+
}).map(function ([
|
|
79
|
+
value,
|
|
80
|
+
index,
|
|
81
|
+
key,
|
|
82
|
+
]) {
|
|
83
|
+
const valuePath: `${ListPath}.${number}` = `${listPath}.${key}`
|
|
60
84
|
return (
|
|
61
85
|
<Fragment key={valuePath}>
|
|
62
86
|
{children(valuePath, value, index)}
|
|
@@ -40,7 +40,7 @@ exports[`mantine list hooks > renders Populated 1`] = `
|
|
|
40
40
|
>
|
|
41
41
|
<span>
|
|
42
42
|
ValuePath:
|
|
43
|
-
$.
|
|
43
|
+
$.100
|
|
44
44
|
</span>
|
|
45
45
|
<br />
|
|
46
46
|
<span>
|
|
@@ -78,7 +78,7 @@ exports[`mantine list hooks > renders Populated 1`] = `
|
|
|
78
78
|
>
|
|
79
79
|
<span>
|
|
80
80
|
ValuePath:
|
|
81
|
-
$.
|
|
81
|
+
$.33
|
|
82
82
|
</span>
|
|
83
83
|
<br />
|
|
84
84
|
<span>
|
|
@@ -97,7 +97,7 @@ exports[`mantine list hooks > renders Populated 1`] = `
|
|
|
97
97
|
>
|
|
98
98
|
<span>
|
|
99
99
|
ValuePath:
|
|
100
|
-
$.
|
|
100
|
+
$.5
|
|
101
101
|
</span>
|
|
102
102
|
<br />
|
|
103
103
|
<span>
|
|
@@ -70,6 +70,7 @@ export const Empty: Story = {
|
|
|
70
70
|
readonly: false,
|
|
71
71
|
required: false,
|
|
72
72
|
value: [],
|
|
73
|
+
listIndexToKey: [0],
|
|
73
74
|
},
|
|
74
75
|
},
|
|
75
76
|
},
|
|
@@ -87,6 +88,13 @@ export const Populated: Story = {
|
|
|
87
88
|
'C',
|
|
88
89
|
'D',
|
|
89
90
|
],
|
|
91
|
+
listIndexToKey: [
|
|
92
|
+
100,
|
|
93
|
+
1,
|
|
94
|
+
33,
|
|
95
|
+
5,
|
|
96
|
+
101,
|
|
97
|
+
],
|
|
90
98
|
},
|
|
91
99
|
},
|
|
92
100
|
},
|
package/package.json
CHANGED