@strictly/react-form 0.0.27 → 0.0.29
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 -1
- package/.out/core/mobx/form_model.js +50 -100
- 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 +48 -115
- package/core/mobx/specs/form_model.tests.ts +14 -12
- package/dist/index.cjs +80 -115
- package/dist/index.d.cts +6 -2
- package/dist/index.d.ts +6 -2
- package/dist/index.js +71 -105
- 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
|
@@ -34,6 +34,7 @@ export type ContextOf<TypePathsToAdapters extends Partial<Readonly<Record<string
|
|
|
34
34
|
export type FormMode = 'edit' | 'create';
|
|
35
35
|
export declare abstract class FormModel<T extends Type, ValueToTypePaths extends Readonly<Record<string, string>>, TypePathsToAdapters extends FlattenedTypePathsToAdaptersOf<FlattenedValuesOfType<T, '*'>, ContextType>, ContextType = ContextOf<TypePathsToAdapters>, ValuePathsToAdapters extends ValuePathsToAdaptersOf<TypePathsToAdapters, ValueToTypePaths> = ValuePathsToAdaptersOf<TypePathsToAdapters, ValueToTypePaths>> {
|
|
36
36
|
readonly type: T;
|
|
37
|
+
private readonly originalValue;
|
|
37
38
|
protected readonly adapters: TypePathsToAdapters;
|
|
38
39
|
protected readonly mode: FormMode;
|
|
39
40
|
accessor value: MobxValueOfType<T>;
|
|
@@ -42,6 +43,7 @@ export declare abstract class FormModel<T extends Type, ValueToTypePaths extends
|
|
|
42
43
|
accessor validation: FlattenedValidation<ValuePathsToAdapters>;
|
|
43
44
|
private readonly flattenedTypeDefs;
|
|
44
45
|
private readonly originalValues;
|
|
46
|
+
private readonly listIndicesToKeys;
|
|
45
47
|
constructor(type: T, originalValue: ValueOfType<ReadonlyTypeOfType<T>>, adapters: TypePathsToAdapters, mode: FormMode);
|
|
46
48
|
protected abstract toContext(value: ValueOfType<ReadonlyTypeOfType<T>>, valuePath: keyof ValuePathsToAdapters): ContextType;
|
|
47
49
|
get forceMutableFields(): boolean;
|
|
@@ -55,11 +57,11 @@ export declare abstract class FormModel<T extends Type, ValueToTypePaths extends
|
|
|
55
57
|
private maybeGetAdapterForValuePath;
|
|
56
58
|
private getAdapterForValuePath;
|
|
57
59
|
get dirty(): boolean;
|
|
60
|
+
get valueChanged(): boolean;
|
|
58
61
|
typePath<K extends keyof ValueToTypePaths>(valuePath: K): ValueToTypePaths[K];
|
|
59
62
|
setFieldValue<K extends keyof ValuePathsToAdapters>(valuePath: K, value: ToOfFieldAdapter<ValuePathsToAdapters[K]>, validation?: Validation): boolean;
|
|
60
63
|
addListItem<K extends keyof FlattenedListTypesOfType<T>>(valuePath: K, elementValue?: Maybe<ElementOfArray<FlattenedValuesOfType<T>[K]>>, index?: number): void;
|
|
61
64
|
removeListItem<K extends keyof FlattenedListTypesOfType<T>>(...elementValuePaths: readonly `${K}.${number}`[]): void;
|
|
62
|
-
protected moveListItem<K extends keyof FlattenedListTypesOfType<T>>(fromValuePath: K, toValuePath: K): void;
|
|
63
65
|
private internalSetFieldValue;
|
|
64
66
|
/**
|
|
65
67
|
* Forces an error onto a field. Error will be removed if the field value changes
|
|
@@ -43,7 +43,7 @@ var __classPrivateFieldSet = (this && this.__classPrivateFieldSet) || function (
|
|
|
43
43
|
if (typeof state === "function" ? receiver !== state || !f : !state.has(receiver)) throw new TypeError("Cannot write private member to an object whose class did not declare it");
|
|
44
44
|
return (kind === "a" ? f.call(receiver, value) : f ? f.value = value : state.set(receiver, value)), value;
|
|
45
45
|
};
|
|
46
|
-
import { assertExists, assertExistsAndReturn,
|
|
46
|
+
import { assertExists, assertExistsAndReturn, checkValidNumber, map, toArray, UnreachableError, } from '@strictly/base';
|
|
47
47
|
import { equals, flattenAccessorsOfType, flattenTypesOfType, flattenValuesOfType, flattenValueTo, jsonPathPop, mobxCopy, valuePathToTypePath, } from '@strictly/define';
|
|
48
48
|
import { computed, observable, runInAction, } from 'mobx';
|
|
49
49
|
import { UnreliableFieldConversionType, } from 'types/field_converters';
|
|
@@ -73,6 +73,7 @@ let FormModel = (() => {
|
|
|
73
73
|
let _get_knownFields_decorators;
|
|
74
74
|
let _get_accessors_decorators;
|
|
75
75
|
let _get_dirty_decorators;
|
|
76
|
+
let _get_valueChanged_decorators;
|
|
76
77
|
return _a = class FormModel {
|
|
77
78
|
get value() { return __classPrivateFieldGet(this, _FormModel_value_accessor_storage, "f"); }
|
|
78
79
|
set value(value) { __classPrivateFieldSet(this, _FormModel_value_accessor_storage, value, "f"); }
|
|
@@ -89,6 +90,12 @@ let FormModel = (() => {
|
|
|
89
90
|
writable: true,
|
|
90
91
|
value: (__runInitializers(this, _instanceExtraInitializers), type)
|
|
91
92
|
});
|
|
93
|
+
Object.defineProperty(this, "originalValue", {
|
|
94
|
+
enumerable: true,
|
|
95
|
+
configurable: true,
|
|
96
|
+
writable: true,
|
|
97
|
+
value: originalValue
|
|
98
|
+
});
|
|
92
99
|
Object.defineProperty(this, "adapters", {
|
|
93
100
|
enumerable: true,
|
|
94
101
|
configurable: true,
|
|
@@ -119,7 +126,14 @@ let FormModel = (() => {
|
|
|
119
126
|
writable: true,
|
|
120
127
|
value: void 0
|
|
121
128
|
});
|
|
122
|
-
|
|
129
|
+
// maintains the value paths of lists when the original order is destroyed by deletes or reordering
|
|
130
|
+
Object.defineProperty(this, "listIndicesToKeys", {
|
|
131
|
+
enumerable: true,
|
|
132
|
+
configurable: true,
|
|
133
|
+
writable: true,
|
|
134
|
+
value: {}
|
|
135
|
+
});
|
|
136
|
+
this.originalValues = flattenValuesOfType(type, originalValue, this.listIndicesToKeys);
|
|
123
137
|
this.value = mobxCopy(type, originalValue);
|
|
124
138
|
this.flattenedTypeDefs = flattenTypesOfType(type);
|
|
125
139
|
// pre-populate field overrides for consistent behavior when default information is overwritten
|
|
@@ -139,7 +153,7 @@ let FormModel = (() => {
|
|
|
139
153
|
}
|
|
140
154
|
// cannot call this.context yet as the "this" pointer has not been fully created
|
|
141
155
|
return convert(fieldValue, valuePath, contextValue);
|
|
142
|
-
});
|
|
156
|
+
}, this.listIndicesToKeys);
|
|
143
157
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
144
158
|
this.fieldOverrides = map(conversions, function (_k, v) {
|
|
145
159
|
return v && [v.value];
|
|
@@ -179,7 +193,7 @@ let FormModel = (() => {
|
|
|
179
193
|
valuePath,
|
|
180
194
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
181
195
|
typePath);
|
|
182
|
-
});
|
|
196
|
+
}, this.listIndicesToKeys);
|
|
183
197
|
}
|
|
184
198
|
maybeSynthesizeFieldByValuePath(valuePath) {
|
|
185
199
|
let typePath;
|
|
@@ -233,7 +247,7 @@ let FormModel = (() => {
|
|
|
233
247
|
};
|
|
234
248
|
}
|
|
235
249
|
synthesizeFieldByPaths(valuePath, typePath) {
|
|
236
|
-
var _b;
|
|
250
|
+
var _b, _c;
|
|
237
251
|
const field = this.getField(valuePath, typePath);
|
|
238
252
|
if (field == null) {
|
|
239
253
|
return;
|
|
@@ -282,6 +296,9 @@ let FormModel = (() => {
|
|
|
282
296
|
error,
|
|
283
297
|
readonly: readonly && !this.forceMutableFields,
|
|
284
298
|
required,
|
|
299
|
+
// make a copy of the index mapping and remove the final value (next id)
|
|
300
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
301
|
+
listIndexToKey: (_c = this.listIndicesToKeys[valuePath]) === null || _c === void 0 ? void 0 : _c.slice(0, -1),
|
|
285
302
|
};
|
|
286
303
|
}
|
|
287
304
|
getAccessorForValuePath(valuePath) {
|
|
@@ -291,7 +308,7 @@ let FormModel = (() => {
|
|
|
291
308
|
get accessors() {
|
|
292
309
|
return flattenAccessorsOfType(this.type, this.value, (value) => {
|
|
293
310
|
this.value = mobxCopy(this.type, value);
|
|
294
|
-
});
|
|
311
|
+
}, this.listIndicesToKeys);
|
|
295
312
|
}
|
|
296
313
|
maybeGetAdapterForValuePath(valuePath) {
|
|
297
314
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
@@ -308,6 +325,10 @@ let FormModel = (() => {
|
|
|
308
325
|
return this.isFieldDirty(valuePath);
|
|
309
326
|
});
|
|
310
327
|
}
|
|
328
|
+
get valueChanged() {
|
|
329
|
+
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
330
|
+
return !equals(this.type, this.value, this.originalValue);
|
|
331
|
+
}
|
|
311
332
|
typePath(valuePath) {
|
|
312
333
|
return valuePathToTypePath(this.type, valuePath, true);
|
|
313
334
|
}
|
|
@@ -341,113 +362,40 @@ let FormModel = (() => {
|
|
|
341
362
|
element,
|
|
342
363
|
...originalList.slice(definedIndex),
|
|
343
364
|
];
|
|
344
|
-
// shuffle the overrides around to account for new indices
|
|
345
|
-
// to so this we need to sort the array indices in descending order
|
|
346
|
-
const targetPaths = Object.keys(this.fieldOverrides).filter(function (v) {
|
|
347
|
-
return v.startsWith(`${listValuePath}.`);
|
|
348
|
-
}).map(function (v) {
|
|
349
|
-
const parts = v.substring(listValuePath.length + 1).split('.');
|
|
350
|
-
const index = parseInt(parts[0]);
|
|
351
|
-
return [
|
|
352
|
-
index,
|
|
353
|
-
parts.slice(1),
|
|
354
|
-
];
|
|
355
|
-
}).filter(function ([index]) {
|
|
356
|
-
return index >= definedIndex;
|
|
357
|
-
}).sort(function ([a], [b]) {
|
|
358
|
-
// descending
|
|
359
|
-
return b - a;
|
|
360
|
-
});
|
|
361
365
|
runInAction(() => {
|
|
362
|
-
targetPaths.forEach(([index, postfix,]) => {
|
|
363
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
364
|
-
const fromJsonPath = [
|
|
365
|
-
listValuePath,
|
|
366
|
-
`${index}`,
|
|
367
|
-
...postfix,
|
|
368
|
-
].join('.');
|
|
369
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
370
|
-
const toJsonPath = [
|
|
371
|
-
listValuePath,
|
|
372
|
-
`${index + 1}`,
|
|
373
|
-
...postfix,
|
|
374
|
-
].join('.');
|
|
375
|
-
const fieldOverride = this.fieldOverrides[fromJsonPath];
|
|
376
|
-
delete this.fieldOverrides[fromJsonPath];
|
|
377
|
-
this.fieldOverrides[toJsonPath] = fieldOverride;
|
|
378
|
-
const validation = this.validation[fromJsonPath];
|
|
379
|
-
delete this.validation[fromJsonPath];
|
|
380
|
-
this.validation[toJsonPath] = validation;
|
|
381
|
-
});
|
|
382
366
|
accessor.set(newList);
|
|
383
367
|
// delete any value overrides so the new list isn't shadowed
|
|
384
368
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
385
369
|
delete this.fieldOverrides[listValuePath];
|
|
370
|
+
const indicesToKeys = assertExistsAndReturn(this.listIndicesToKeys[listValuePath], 'no index to key mapping for list {}', listValuePath);
|
|
371
|
+
const nextKey = indicesToKeys[indicesToKeys.length - 1];
|
|
372
|
+
// insert the next key
|
|
373
|
+
indicesToKeys.splice(definedIndex, 0, nextKey);
|
|
374
|
+
// create the new next key
|
|
375
|
+
indicesToKeys[indicesToKeys.length - 1] = nextKey + 1;
|
|
386
376
|
});
|
|
387
377
|
}
|
|
388
378
|
removeListItem(...elementValuePaths) {
|
|
389
|
-
// sort and reverse so we delete last to first so indices of sequential deletions are preserved
|
|
390
|
-
const orderedElementValuePaths = elementValuePaths.toSorted().reverse();
|
|
391
379
|
runInAction(() => {
|
|
392
|
-
|
|
393
|
-
|
|
380
|
+
elementValuePaths.forEach(elementValuePath => {
|
|
381
|
+
var _b;
|
|
382
|
+
const [listValuePath, elementKeyString,] = assertExistsAndReturn(jsonPathPop(elementValuePath), 'expected a path with two or more segments {}', elementValuePath);
|
|
394
383
|
const accessor = this.accessors[listValuePath];
|
|
395
|
-
const
|
|
396
|
-
const
|
|
397
|
-
|
|
398
|
-
|
|
399
|
-
|
|
400
|
-
|
|
401
|
-
|
|
402
|
-
|
|
403
|
-
}).map(function (v) {
|
|
404
|
-
const parts = v.substring(listValuePath.length + 1).split('.');
|
|
405
|
-
const index = parseInt(parts[0]);
|
|
406
|
-
return [
|
|
407
|
-
index,
|
|
408
|
-
parts.slice(1),
|
|
409
|
-
];
|
|
410
|
-
}).filter(function ([index]) {
|
|
411
|
-
return index > elementIndex;
|
|
412
|
-
}).sort(function ([a], [b]) {
|
|
413
|
-
// descending
|
|
414
|
-
return a - b;
|
|
415
|
-
});
|
|
416
|
-
targetPaths.forEach(([index, postfix,]) => {
|
|
417
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
418
|
-
const fromJsonPath = [
|
|
419
|
-
listValuePath,
|
|
420
|
-
`${index}`,
|
|
421
|
-
...postfix,
|
|
422
|
-
].join('.');
|
|
384
|
+
const elementKey = checkValidNumber(parseInt(elementKeyString), 'unexpected id {} ({})', elementKeyString, elementValuePath);
|
|
385
|
+
const indicesToKeys = this.listIndicesToKeys[listValuePath];
|
|
386
|
+
const elementIndex = (_b = indicesToKeys === null || indicesToKeys === void 0 ? void 0 : indicesToKeys.indexOf(elementKey)) !== null && _b !== void 0 ? _b : -1;
|
|
387
|
+
if (elementIndex >= 0) {
|
|
388
|
+
const newList = [...accessor.value];
|
|
389
|
+
newList.splice(elementIndex, 1);
|
|
390
|
+
accessor.set(newList);
|
|
391
|
+
// delete any value overrides so the new list isn't shadowed
|
|
423
392
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
...postfix,
|
|
428
|
-
].join('.');
|
|
429
|
-
const fieldOverride = this.fieldOverrides[fromJsonPath];
|
|
430
|
-
delete this.fieldOverrides[fromJsonPath];
|
|
431
|
-
this.fieldOverrides[toJsonPath] = fieldOverride;
|
|
432
|
-
const validation = this.validation[fromJsonPath];
|
|
433
|
-
delete this.validation[fromJsonPath];
|
|
434
|
-
this.validation[toJsonPath] = validation;
|
|
435
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions, @typescript-eslint/no-explicit-any
|
|
436
|
-
this.moveListItem(fromJsonPath, toJsonPath);
|
|
437
|
-
});
|
|
438
|
-
accessor.set(newList);
|
|
439
|
-
// delete any value overrides so the new list isn't shadowed
|
|
440
|
-
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
441
|
-
delete this.fieldOverrides[listValuePath];
|
|
393
|
+
delete this.fieldOverrides[listValuePath];
|
|
394
|
+
indicesToKeys.splice(elementIndex, 1);
|
|
395
|
+
}
|
|
442
396
|
});
|
|
443
397
|
});
|
|
444
398
|
}
|
|
445
|
-
moveListItem(fromValuePath, toValuePath) {
|
|
446
|
-
// do nothing, this is for subclasses to override
|
|
447
|
-
// put in some nonsense so TS doesn't complain about the parameters not being used
|
|
448
|
-
fromValuePath;
|
|
449
|
-
toValuePath;
|
|
450
|
-
}
|
|
451
399
|
internalSetFieldValue(valuePath, value, validation) {
|
|
452
400
|
const { revert } = this.getAdapterForValuePath(valuePath);
|
|
453
401
|
assertExists(revert, 'setting value not supported {}', valuePath);
|
|
@@ -528,7 +476,7 @@ let FormModel = (() => {
|
|
|
528
476
|
});
|
|
529
477
|
}
|
|
530
478
|
isValuePathActive(valuePath) {
|
|
531
|
-
const values = flattenValuesOfType(this.type, this.value);
|
|
479
|
+
const values = flattenValuesOfType(this.type, this.value, this.listIndicesToKeys);
|
|
532
480
|
const keys = new Set(Object.keys(values));
|
|
533
481
|
// eslint-disable-next-line @typescript-eslint/consistent-type-assertions
|
|
534
482
|
return keys.has(valuePath);
|
|
@@ -606,6 +554,7 @@ let FormModel = (() => {
|
|
|
606
554
|
_get_knownFields_decorators = [computed];
|
|
607
555
|
_get_accessors_decorators = [computed];
|
|
608
556
|
_get_dirty_decorators = [computed];
|
|
557
|
+
_get_valueChanged_decorators = [computed];
|
|
609
558
|
__esDecorate(_a, null, _value_decorators, { kind: "accessor", name: "value", static: false, private: false, access: { has: obj => "value" in obj, get: obj => obj.value, set: (obj, value) => { obj.value = value; } }, metadata: _metadata }, _value_initializers, _value_extraInitializers);
|
|
610
559
|
__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);
|
|
611
560
|
__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);
|
|
@@ -614,6 +563,7 @@ let FormModel = (() => {
|
|
|
614
563
|
__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);
|
|
615
564
|
__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);
|
|
616
565
|
__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
|
+
__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);
|
|
617
567
|
if (_metadata) Object.defineProperty(_a, Symbol.metadata, { enumerable: true, configurable: true, writable: true, value: _metadata });
|
|
618
568
|
})(),
|
|
619
569
|
_a;
|
|
@@ -546,19 +546,20 @@ describe('all', function () {
|
|
|
546
546
|
});
|
|
547
547
|
it.each([
|
|
548
548
|
[
|
|
549
|
-
|
|
549
|
+
// new
|
|
550
|
+
'$.3',
|
|
550
551
|
'0',
|
|
551
552
|
],
|
|
552
553
|
[
|
|
553
|
-
'$.
|
|
554
|
+
'$.0',
|
|
554
555
|
'x',
|
|
555
556
|
],
|
|
556
557
|
[
|
|
557
|
-
'$.
|
|
558
|
+
'$.1',
|
|
558
559
|
'3',
|
|
559
560
|
],
|
|
560
561
|
[
|
|
561
|
-
'$.
|
|
562
|
+
'$.2',
|
|
562
563
|
'z',
|
|
563
564
|
],
|
|
564
565
|
])('it reports the value of field %s as %s', function (path, fieldValue) {
|
|
@@ -567,19 +568,20 @@ describe('all', function () {
|
|
|
567
568
|
});
|
|
568
569
|
it.each([
|
|
569
570
|
[
|
|
570
|
-
|
|
571
|
+
// new
|
|
572
|
+
'$.3',
|
|
571
573
|
undefined,
|
|
572
574
|
],
|
|
573
575
|
[
|
|
574
|
-
'$.
|
|
576
|
+
'$.0',
|
|
575
577
|
IS_NAN_ERROR,
|
|
576
578
|
],
|
|
577
579
|
[
|
|
578
|
-
'$.
|
|
580
|
+
'$.1',
|
|
579
581
|
undefined,
|
|
580
582
|
],
|
|
581
583
|
[
|
|
582
|
-
'$.
|
|
584
|
+
'$.2',
|
|
583
585
|
IS_NAN_ERROR,
|
|
584
586
|
],
|
|
585
587
|
])('it reports the error of field %s', function (path, error) {
|
|
@@ -636,11 +638,11 @@ describe('all', function () {
|
|
|
636
638
|
});
|
|
637
639
|
it('updates the field values and errors', function () {
|
|
638
640
|
expect(model.fields).toEqual({
|
|
639
|
-
'$.
|
|
641
|
+
'$.1': expect.objectContaining({
|
|
640
642
|
value: '3',
|
|
641
643
|
error: undefined,
|
|
642
644
|
}),
|
|
643
|
-
'$.
|
|
645
|
+
'$.2': expect.objectContaining({
|
|
644
646
|
value: 'z',
|
|
645
647
|
error: IS_NAN_ERROR,
|
|
646
648
|
}),
|
|
@@ -663,7 +665,7 @@ describe('all', function () {
|
|
|
663
665
|
value: 'x',
|
|
664
666
|
error: IS_NAN_ERROR,
|
|
665
667
|
}),
|
|
666
|
-
'$.
|
|
668
|
+
'$.2': expect.objectContaining({
|
|
667
669
|
value: 'z',
|
|
668
670
|
error: IS_NAN_ERROR,
|
|
669
671
|
}),
|
|
@@ -679,7 +681,7 @@ describe('all', function () {
|
|
|
679
681
|
});
|
|
680
682
|
it('updates the field values and errors', function () {
|
|
681
683
|
expect(model.fields).toEqual({
|
|
682
|
-
'$.
|
|
684
|
+
'$.2': expect.objectContaining({
|
|
683
685
|
value: 'z',
|
|
684
686
|
error: IS_NAN_ERROR,
|
|
685
687
|
}),
|
|
@@ -6,11 +6,12 @@ import { type ValueTypeOfField } from 'types/value_type_of_field';
|
|
|
6
6
|
import { type MantineFieldComponent, type MantineForm } from './types';
|
|
7
7
|
export type SuppliedListProps<Value = any, ListPath extends string = string> = {
|
|
8
8
|
values: readonly Value[];
|
|
9
|
+
indexKeys: number[];
|
|
9
10
|
listPath: ListPath;
|
|
10
11
|
};
|
|
11
12
|
export declare function createList<F extends Fields, K extends keyof ListFieldsOfFields<F>, Props extends SuppliedListProps<ElementOfArray<ValueTypeOfField<F[K]>>> & {
|
|
12
13
|
children: (valuePath: `${K}.${number}`, value: ElementOfArray<ValueTypeOfField<F[K]>>, index: number) => React.ReactNode;
|
|
13
14
|
}>(this: MantineForm<F>, valuePath: K, List: ComponentType<Props>): MantineFieldComponent<SuppliedListProps<ElementOfArray<ValueTypeOfField<F[K]>>>, Props, never>;
|
|
14
|
-
export declare function DefaultList<Value, ListPath extends string>({ values, listPath, children, }: SuppliedListProps<Value, ListPath> & {
|
|
15
|
+
export declare function DefaultList<Value, ListPath extends string>({ values, indexKeys, listPath, children, }: SuppliedListProps<Value, ListPath> & {
|
|
15
16
|
children: (valuePath: `${ListPath}.${number}`, value: Value, index: number) => React.ReactNode;
|
|
16
17
|
}): import("react/jsx-runtime").JSX.Element;
|
|
@@ -1,19 +1,31 @@
|
|
|
1
1
|
import { jsx as _jsx, Fragment as _Fragment } from "react/jsx-runtime";
|
|
2
|
+
import { assertExistsAndReturn, } from '@strictly/base';
|
|
2
3
|
import { Fragment, } from 'react';
|
|
3
4
|
import { createUnsafePartialObserverComponent } from 'util/partial';
|
|
4
5
|
export function createList(valuePath, List) {
|
|
5
6
|
const propSource = () => {
|
|
6
|
-
const
|
|
7
|
+
const field = this.fields[valuePath];
|
|
8
|
+
const values = [...field.value];
|
|
7
9
|
return {
|
|
8
10
|
values,
|
|
9
11
|
listPath: valuePath,
|
|
12
|
+
indexKeys: assertExistsAndReturn(field.listIndexToKey, 'list index to key mapping missing in {}', valuePath),
|
|
10
13
|
};
|
|
11
14
|
};
|
|
12
15
|
return createUnsafePartialObserverComponent(List, propSource);
|
|
13
16
|
}
|
|
14
|
-
export function DefaultList({ values, listPath, children, }) {
|
|
17
|
+
export function DefaultList({ values, indexKeys, listPath, children, }) {
|
|
15
18
|
return (_jsx(_Fragment, { children: values.map(function (value, index) {
|
|
16
|
-
|
|
19
|
+
return [
|
|
20
|
+
value,
|
|
21
|
+
index,
|
|
22
|
+
indexKeys[index],
|
|
23
|
+
];
|
|
24
|
+
}).filter(function ([_value, _index, key,]) {
|
|
25
|
+
// omit entries without keys
|
|
26
|
+
return key != null;
|
|
27
|
+
}).map(function ([value, index, key,]) {
|
|
28
|
+
const valuePath = `${listPath}.${key}`;
|
|
17
29
|
return (_jsx(Fragment, { children: children(valuePath, value, index) }, valuePath));
|
|
18
30
|
}) }));
|
|
19
31
|
}
|
|
@@ -26,6 +26,7 @@ export const Empty = {
|
|
|
26
26
|
readonly: false,
|
|
27
27
|
required: false,
|
|
28
28
|
value: [],
|
|
29
|
+
listIndexToKey: [0],
|
|
29
30
|
},
|
|
30
31
|
},
|
|
31
32
|
},
|
|
@@ -42,6 +43,13 @@ export const Populated = {
|
|
|
42
43
|
'C',
|
|
43
44
|
'D',
|
|
44
45
|
],
|
|
46
|
+
listIndexToKey: [
|
|
47
|
+
100,
|
|
48
|
+
1,
|
|
49
|
+
33,
|
|
50
|
+
5,
|
|
51
|
+
101,
|
|
52
|
+
],
|
|
45
53
|
},
|
|
46
54
|
},
|
|
47
55
|
},
|