@bolttech/form-engine-core 0.0.2-beta.5 → 0.0.2-beta.6
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/README.md +295 -1457
- package/index.esm.js +190 -46
- package/package.json +1 -1
- package/src/helpers/helpers.d.ts +2 -1
- package/src/managers/field.d.ts +16 -2
- package/src/managers/form.d.ts +21 -2
- package/src/managers/formGroup.d.ts +12 -6
- package/src/types/event.d.ts +31 -1
- package/src/types/schema.d.ts +30 -11
package/index.esm.js
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { Subject, Subscription, combineLatest, startWith, groupBy, mergeMap, debounceTime, filter, map } from 'rxjs';
|
|
1
|
+
import { Subject, Subscription, combineLatest, startWith, groupBy, mergeMap, debounceTime, filter, map, distinctUntilKeyChanged } from 'rxjs';
|
|
2
2
|
import creditCardType from 'credit-card-type';
|
|
3
3
|
import { isNumber as isNumber$1, isFunction, cloneDeep, isEqual, get, isNil, set } from 'lodash';
|
|
4
4
|
import { getCurrencySymbol } from '@gaignoux/currency';
|
|
@@ -76,11 +76,10 @@ function makeRequest(method, url, headers, body) {
|
|
|
76
76
|
});
|
|
77
77
|
}
|
|
78
78
|
xhr.onload = function () {
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
}
|
|
79
|
+
resolve({
|
|
80
|
+
status: xhr.status,
|
|
81
|
+
response: xhr.responseText
|
|
82
|
+
});
|
|
84
83
|
};
|
|
85
84
|
xhr.onerror = function () {
|
|
86
85
|
reject(xhr.statusText);
|
|
@@ -2470,6 +2469,11 @@ class FormField {
|
|
|
2470
2469
|
* @param {Function} options.resetValue - A function to reset the field value.
|
|
2471
2470
|
* @param {unknown} [options.initialValue] - The initial value of the form field.
|
|
2472
2471
|
* @param {Subject<{ key: string }>} options.templateSubject$ - A subject for template updates.
|
|
2472
|
+
* @param {Subject<TFieldEvent>} options.fieldEventSubject$, - Subject for basic event mapped field emissions, except onData to form instance
|
|
2473
|
+
* @param {Subject<{ key: string; event: TEvents }>} options.dataSubject$, - Subject to emit onData events to form instance
|
|
2474
|
+
* @param {Subject<{ key: string }>} options.formValidNotification$, - Subject to emit field valid change to form instance
|
|
2475
|
+
* @param {TMapper<unknown>} options.mapper, - component generic mapper containing render parameters for adapters
|
|
2476
|
+
* @param {() => TFormValues<unknown>} options.getFormValues, - form instance function that builds onData parameter payload from fields
|
|
2473
2477
|
*/
|
|
2474
2478
|
constructor({
|
|
2475
2479
|
schemaComponent,
|
|
@@ -2482,7 +2486,9 @@ class FormField {
|
|
|
2482
2486
|
templateSubject$,
|
|
2483
2487
|
fieldEventSubject$,
|
|
2484
2488
|
dataSubject$,
|
|
2485
|
-
|
|
2489
|
+
formValidNotification$,
|
|
2490
|
+
mapper,
|
|
2491
|
+
getFormValues
|
|
2486
2492
|
}) {
|
|
2487
2493
|
var _a, _b, _c, _d, _e, _f, _g;
|
|
2488
2494
|
this.valueSubscription$ = new Subscription();
|
|
@@ -2509,30 +2515,34 @@ class FormField {
|
|
|
2509
2515
|
this.mapper = mapper;
|
|
2510
2516
|
this.validateVisibility = validateVisibility;
|
|
2511
2517
|
this.resetValue = resetValue;
|
|
2518
|
+
this.getFormValues = getFormValues;
|
|
2512
2519
|
this.templateSubject$ = templateSubject$;
|
|
2513
2520
|
this.fieldEventSubject$ = fieldEventSubject$;
|
|
2514
2521
|
this.dataSubject$ = dataSubject$;
|
|
2522
|
+
this.formValidNotification$ = formValidNotification$;
|
|
2515
2523
|
this._props = schemaComponent.props || {};
|
|
2516
2524
|
this._metadata = '';
|
|
2517
2525
|
this.errorsString = '';
|
|
2518
2526
|
this.errorsList = [];
|
|
2519
|
-
this.initialValue = initialValue;
|
|
2527
|
+
this.initialValue = initialValue || (this.valuePropName && !String(this.props[this.valuePropName]).includes('${') ? this.props[this.valuePropName] : null);
|
|
2520
2528
|
this._visibility = true;
|
|
2521
2529
|
this._api = {
|
|
2522
2530
|
default: {
|
|
2523
|
-
response: ((_e = (_d = (_c = this.apiSchema) === null || _c === void 0 ? void 0 : _c.defaultConfig) === null || _d === void 0 ? void 0 : _d.config) === null || _e === void 0 ? void 0 : _e.fallbackValue) || ''
|
|
2531
|
+
response: ((_e = (_d = (_c = this.apiSchema) === null || _c === void 0 ? void 0 : _c.defaultConfig) === null || _d === void 0 ? void 0 : _d.config) === null || _e === void 0 ? void 0 : _e.fallbackValue) || '',
|
|
2532
|
+
status: null
|
|
2524
2533
|
},
|
|
2525
2534
|
named: ((_f = this.apiSchema) === null || _f === void 0 ? void 0 : _f.configs) && Object.keys((_g = this.apiSchema) === null || _g === void 0 ? void 0 : _g.configs).reduce((acc, curr) => {
|
|
2526
2535
|
var _a, _b;
|
|
2527
2536
|
acc[curr] = {
|
|
2528
|
-
response: ((_b = (_a = this.apiSchema) === null || _a === void 0 ? void 0 : _a.configs) === null || _b === void 0 ? void 0 : _b[curr].config.fallbackValue) || ''
|
|
2537
|
+
response: ((_b = (_a = this.apiSchema) === null || _a === void 0 ? void 0 : _a.configs) === null || _b === void 0 ? void 0 : _b[curr].config.fallbackValue) || '',
|
|
2538
|
+
status: null
|
|
2529
2539
|
};
|
|
2530
2540
|
return acc;
|
|
2531
2541
|
}, {})
|
|
2532
2542
|
};
|
|
2533
2543
|
this._errors = {};
|
|
2534
|
-
this._valid = false;
|
|
2535
2544
|
this._mounted = true;
|
|
2545
|
+
this._valid = false;
|
|
2536
2546
|
this.initializeObservers();
|
|
2537
2547
|
this.value = this.initialValue || '';
|
|
2538
2548
|
}
|
|
@@ -2689,7 +2699,7 @@ class FormField {
|
|
|
2689
2699
|
*/
|
|
2690
2700
|
if (!this.visibility) {
|
|
2691
2701
|
this.value = '';
|
|
2692
|
-
this.
|
|
2702
|
+
this.valid = true;
|
|
2693
2703
|
} else {
|
|
2694
2704
|
this.setFieldValidity({
|
|
2695
2705
|
event: 'ON_FIELD_MOUNT'
|
|
@@ -2702,6 +2712,17 @@ class FormField {
|
|
|
2702
2712
|
event: 'ON_VISIBILITY'
|
|
2703
2713
|
});
|
|
2704
2714
|
}
|
|
2715
|
+
/**
|
|
2716
|
+
* sets valid field state and notifies form instance via formValidNotification$
|
|
2717
|
+
*/
|
|
2718
|
+
set valid(valid) {
|
|
2719
|
+
if (this._valid !== valid) {
|
|
2720
|
+
this._valid = valid;
|
|
2721
|
+
this.formValidNotification$.next({
|
|
2722
|
+
fieldTrigger: this.name
|
|
2723
|
+
});
|
|
2724
|
+
}
|
|
2725
|
+
}
|
|
2705
2726
|
/**
|
|
2706
2727
|
* Retrieves the validity status of the form field.
|
|
2707
2728
|
*
|
|
@@ -2843,7 +2864,7 @@ class FormField {
|
|
|
2843
2864
|
var _a, _b, _c, _d;
|
|
2844
2865
|
if (!this.validations || !this.visibility) {
|
|
2845
2866
|
this.errors = {};
|
|
2846
|
-
this.
|
|
2867
|
+
this.valid = true;
|
|
2847
2868
|
return;
|
|
2848
2869
|
}
|
|
2849
2870
|
let valid = true;
|
|
@@ -2865,7 +2886,7 @@ class FormField {
|
|
|
2865
2886
|
delete errors[validationKey];
|
|
2866
2887
|
}
|
|
2867
2888
|
});
|
|
2868
|
-
this.
|
|
2889
|
+
this.valid = valid;
|
|
2869
2890
|
if ((_c = (_b = this.validations) === null || _b === void 0 ? void 0 : _b.eventMessages) === null || _c === void 0 ? void 0 : _c[event]) {
|
|
2870
2891
|
const eventMessages = {};
|
|
2871
2892
|
(_d = this.validations.eventMessages[event]) === null || _d === void 0 ? void 0 : _d.forEach(method => {
|
|
@@ -2930,14 +2951,28 @@ class FormField {
|
|
|
2930
2951
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
2931
2952
|
return __awaiter(this, void 0, void 0, function* () {
|
|
2932
2953
|
const configRequest = config => __awaiter(this, void 0, void 0, function* () {
|
|
2954
|
+
var _k;
|
|
2933
2955
|
try {
|
|
2934
|
-
const
|
|
2935
|
-
|
|
2936
|
-
|
|
2956
|
+
const {
|
|
2957
|
+
status,
|
|
2958
|
+
response
|
|
2959
|
+
} = yield makeRequest(config.method, config.url, config.headers, config.body);
|
|
2960
|
+
const callbackTransform = (_k = config.transform) === null || _k === void 0 ? void 0 : _k.callback;
|
|
2961
|
+
const apiResponseData = callbackTransform ? callbackTransform({
|
|
2962
|
+
payload: JSON.parse(String(response)),
|
|
2963
|
+
formValues: this.getFormValues()
|
|
2964
|
+
}) : JSON.parse(String(response));
|
|
2965
|
+
const responseReturn = config.resultPath ? get(apiResponseData, config.resultPath) : apiResponseData;
|
|
2937
2966
|
// this.apiResponseData = { response };
|
|
2938
|
-
return
|
|
2967
|
+
return {
|
|
2968
|
+
response: responseReturn,
|
|
2969
|
+
status
|
|
2970
|
+
};
|
|
2939
2971
|
} catch (e) {
|
|
2940
|
-
return
|
|
2972
|
+
return {
|
|
2973
|
+
response: !isNil(config === null || config === void 0 ? void 0 : config.fallbackValue) ? config.fallbackValue : 'error',
|
|
2974
|
+
status: 500
|
|
2975
|
+
};
|
|
2941
2976
|
}
|
|
2942
2977
|
});
|
|
2943
2978
|
if (!((_b = (_a = this.apiSchema) === null || _a === void 0 ? void 0 : _a.defaultConfig) === null || _b === void 0 ? void 0 : _b.events.includes(event)) && !(((_c = this.apiSchema) === null || _c === void 0 ? void 0 : _c.configs) && Object.keys((_d = this.apiSchema) === null || _d === void 0 ? void 0 : _d.configs).some(key => {
|
|
@@ -2950,9 +2985,13 @@ class FormField {
|
|
|
2950
2985
|
};
|
|
2951
2986
|
const config = (_e = this.apiSchema.defaultConfig) === null || _e === void 0 ? void 0 : _e.config;
|
|
2952
2987
|
if (config && ((_g = (_f = this.apiSchema) === null || _f === void 0 ? void 0 : _f.defaultConfig) === null || _g === void 0 ? void 0 : _g.events.includes(event)) && this.checkApiRequestValidations(config)) {
|
|
2953
|
-
const
|
|
2988
|
+
const {
|
|
2989
|
+
response,
|
|
2990
|
+
status
|
|
2991
|
+
} = yield configRequest(config);
|
|
2954
2992
|
responses.default = {
|
|
2955
|
-
response
|
|
2993
|
+
response,
|
|
2994
|
+
status
|
|
2956
2995
|
};
|
|
2957
2996
|
}
|
|
2958
2997
|
if (((_h = this.apiSchema) === null || _h === void 0 ? void 0 : _h.configs) && Object.keys((_j = this.apiSchema) === null || _j === void 0 ? void 0 : _j.configs).some(key => {
|
|
@@ -2964,14 +3003,18 @@ class FormField {
|
|
|
2964
3003
|
@TODO handle promises with error
|
|
2965
3004
|
*/
|
|
2966
3005
|
const result = yield Promise.all(Object.keys(this.apiSchema.configs).map(configKey => __awaiter(this, void 0, void 0, function* () {
|
|
2967
|
-
var
|
|
2968
|
-
const config = (
|
|
2969
|
-
if (config && ((
|
|
2970
|
-
const
|
|
3006
|
+
var _l, _m, _o, _p;
|
|
3007
|
+
const config = (_m = (_l = this.apiSchema) === null || _l === void 0 ? void 0 : _l.configs) === null || _m === void 0 ? void 0 : _m[configKey].config;
|
|
3008
|
+
if (config && ((_p = (_o = this.apiSchema) === null || _o === void 0 ? void 0 : _o.configs) === null || _p === void 0 ? void 0 : _p[configKey].events.includes(event)) && this.checkApiRequestValidations(config)) {
|
|
3009
|
+
const {
|
|
3010
|
+
response,
|
|
3011
|
+
status
|
|
3012
|
+
} = yield configRequest(config);
|
|
2971
3013
|
return {
|
|
2972
3014
|
name: configKey,
|
|
2973
3015
|
result: {
|
|
2974
|
-
response
|
|
3016
|
+
response,
|
|
3017
|
+
status
|
|
2975
3018
|
}
|
|
2976
3019
|
};
|
|
2977
3020
|
}
|
|
@@ -3043,6 +3086,8 @@ class FormCore {
|
|
|
3043
3086
|
var _a, _b, _c, _d, _e, _f, _g, _h, _j;
|
|
3044
3087
|
this.templateSubscription$ = new Subscription();
|
|
3045
3088
|
this.mappers = new Map();
|
|
3089
|
+
this.queuedFieldVisibilityEvents = new Map();
|
|
3090
|
+
this.queuedFieldResetValuesEvents = new Map();
|
|
3046
3091
|
this.schema = entry.schema;
|
|
3047
3092
|
this.fields = new Map();
|
|
3048
3093
|
this.initialValues = entry.initialValues || ((_a = entry.schema) === null || _a === void 0 ? void 0 : _a.initialValues);
|
|
@@ -3062,6 +3107,7 @@ class FormCore {
|
|
|
3062
3107
|
this.fieldEventSubject$ = new Subject();
|
|
3063
3108
|
this.dataSubject$ = new Subject();
|
|
3064
3109
|
this.mountSubject$ = new Subject();
|
|
3110
|
+
this.formValidNotification$ = new Subject();
|
|
3065
3111
|
this.subscribedTemplates = [];
|
|
3066
3112
|
this.schema && this.serializeStructure(this.schema.components);
|
|
3067
3113
|
this.schema && this.subscribeTemplates();
|
|
@@ -3171,7 +3217,7 @@ class FormCore {
|
|
|
3171
3217
|
const field = this.fields.get(key);
|
|
3172
3218
|
if (!field) return console.warn(`failed to get value from ${key}`);
|
|
3173
3219
|
if (property === 'props' && path[0] === field.valuePropName) {
|
|
3174
|
-
return field.
|
|
3220
|
+
return field.value;
|
|
3175
3221
|
}
|
|
3176
3222
|
return path.length > 0 ? get(field[property], path) : field[property];
|
|
3177
3223
|
}
|
|
@@ -3383,6 +3429,25 @@ class FormCore {
|
|
|
3383
3429
|
}
|
|
3384
3430
|
});
|
|
3385
3431
|
}
|
|
3432
|
+
/**
|
|
3433
|
+
* executes events that were stored due to field unavaliability
|
|
3434
|
+
*
|
|
3435
|
+
* @param {string} field field to check
|
|
3436
|
+
*/
|
|
3437
|
+
checkFieldEventQueues(field) {
|
|
3438
|
+
if (this.queuedFieldVisibilityEvents.has(field)) {
|
|
3439
|
+
this.setFieldVisibility(Object.assign({
|
|
3440
|
+
field: field
|
|
3441
|
+
}, this.queuedFieldVisibilityEvents.get(field)));
|
|
3442
|
+
this.queuedFieldVisibilityEvents.delete(field);
|
|
3443
|
+
}
|
|
3444
|
+
if (this.queuedFieldResetValuesEvents.has(field)) {
|
|
3445
|
+
this.setResetFieldValue(Object.assign({
|
|
3446
|
+
key: field
|
|
3447
|
+
}, this.queuedFieldResetValuesEvents.get(field)));
|
|
3448
|
+
this.queuedFieldResetValuesEvents.delete(field);
|
|
3449
|
+
}
|
|
3450
|
+
}
|
|
3386
3451
|
/**
|
|
3387
3452
|
* @internal
|
|
3388
3453
|
* Update field visibility accordingly.
|
|
@@ -3391,14 +3456,16 @@ class FormCore {
|
|
|
3391
3456
|
* @param {boolean} hasError - Condition to be used as visibility.
|
|
3392
3457
|
* @param {boolean|undefined} showOnlyIfTrue - Flag to be considered when update field visibility. If it's true, then considered error, if it's false, always considered the opposite.
|
|
3393
3458
|
*/
|
|
3394
|
-
setFieldVisibility(
|
|
3459
|
+
setFieldVisibility({
|
|
3460
|
+
field,
|
|
3461
|
+
hasError,
|
|
3462
|
+
showOnlyIfTrue
|
|
3463
|
+
}) {
|
|
3395
3464
|
if (!this.fields.has(field)) {
|
|
3396
|
-
|
|
3397
|
-
|
|
3398
|
-
|
|
3399
|
-
|
|
3400
|
-
*/
|
|
3401
|
-
console.warn(`failed to update visibility onto field ${field}`);
|
|
3465
|
+
this.queuedFieldVisibilityEvents.set(field, {
|
|
3466
|
+
hasError,
|
|
3467
|
+
showOnlyIfTrue
|
|
3468
|
+
});
|
|
3402
3469
|
} else {
|
|
3403
3470
|
this.fields.get(field).visibility = showOnlyIfTrue ? hasError : !hasError;
|
|
3404
3471
|
}
|
|
@@ -3425,10 +3492,18 @@ class FormCore {
|
|
|
3425
3492
|
const error = handleValidation(field.value, structElement.validations, validations, validationKey);
|
|
3426
3493
|
if (Array.isArray(structElement.fields)) {
|
|
3427
3494
|
structElement.fields.forEach(fieldKey => {
|
|
3428
|
-
this.setFieldVisibility(
|
|
3495
|
+
this.setFieldVisibility({
|
|
3496
|
+
field: fieldKey,
|
|
3497
|
+
hasError: error,
|
|
3498
|
+
showOnlyIfTrue: !!(field.value && structElement.showOnlyIfTrue)
|
|
3499
|
+
});
|
|
3429
3500
|
});
|
|
3430
3501
|
} else if (structElement.fields) {
|
|
3431
|
-
this.setFieldVisibility(
|
|
3502
|
+
this.setFieldVisibility({
|
|
3503
|
+
field: structElement.fields,
|
|
3504
|
+
hasError: error,
|
|
3505
|
+
showOnlyIfTrue: !!(field.value && structElement.showOnlyIfTrue)
|
|
3506
|
+
});
|
|
3432
3507
|
}
|
|
3433
3508
|
});
|
|
3434
3509
|
});
|
|
@@ -3440,9 +3515,14 @@ class FormCore {
|
|
|
3440
3515
|
* @param {string} key - Field name to be updated.
|
|
3441
3516
|
* @param {unknown} value - Value to be inserted into field.
|
|
3442
3517
|
*/
|
|
3443
|
-
setResetFieldValue(
|
|
3518
|
+
setResetFieldValue({
|
|
3519
|
+
key,
|
|
3520
|
+
value
|
|
3521
|
+
}) {
|
|
3444
3522
|
if (!this.fields.has(key)) {
|
|
3445
|
-
|
|
3523
|
+
this.queuedFieldResetValuesEvents.set(key, {
|
|
3524
|
+
value
|
|
3525
|
+
});
|
|
3446
3526
|
} else {
|
|
3447
3527
|
const field = this.fields.get(key);
|
|
3448
3528
|
field.emitValue({
|
|
@@ -3474,10 +3554,16 @@ class FormCore {
|
|
|
3474
3554
|
if (Array.isArray(structElement.fields)) {
|
|
3475
3555
|
structElement.fields.forEach((fieldKey, index) => {
|
|
3476
3556
|
const resettledValue = Array.isArray(structElement.resettledValue) ? structElement.resettledValue[index] : structElement.resettledValue;
|
|
3477
|
-
this.setResetFieldValue(
|
|
3557
|
+
this.setResetFieldValue({
|
|
3558
|
+
key: fieldKey,
|
|
3559
|
+
value: resettledValue
|
|
3560
|
+
});
|
|
3478
3561
|
});
|
|
3479
3562
|
} else if (structElement.fields) {
|
|
3480
|
-
this.setResetFieldValue(
|
|
3563
|
+
this.setResetFieldValue({
|
|
3564
|
+
key: structElement.fields,
|
|
3565
|
+
value: structElement.resettledValue
|
|
3566
|
+
});
|
|
3481
3567
|
}
|
|
3482
3568
|
};
|
|
3483
3569
|
if (!structElement.validations) {
|
|
@@ -3513,10 +3599,12 @@ class FormCore {
|
|
|
3513
3599
|
children: fieldSchema.children ? fieldSchema.children.map(el => el.name) : [],
|
|
3514
3600
|
validateVisibility: this.validateVisibility.bind(this),
|
|
3515
3601
|
resetValue: this.resetValue.bind(this),
|
|
3602
|
+
getFormValues: this.getFormValues.bind(this),
|
|
3516
3603
|
initialValue: (_b = this.initialValues) === null || _b === void 0 ? void 0 : _b[fieldSchema.name],
|
|
3517
3604
|
templateSubject$: this.templateSubject$,
|
|
3518
3605
|
fieldEventSubject$: this.fieldEventSubject$,
|
|
3519
3606
|
dataSubject$: this.dataSubject$,
|
|
3607
|
+
formValidNotification$: this.formValidNotification$,
|
|
3520
3608
|
config: this.config
|
|
3521
3609
|
}));
|
|
3522
3610
|
this.subscribeTemplates();
|
|
@@ -3525,6 +3613,7 @@ class FormCore {
|
|
|
3525
3613
|
event: 'ON_FIELDS',
|
|
3526
3614
|
key: fieldSchema.name
|
|
3527
3615
|
});
|
|
3616
|
+
this.checkFieldEventQueues(fieldSchema.name);
|
|
3528
3617
|
(_c = this.fields.get(fieldSchema.name)) === null || _c === void 0 ? void 0 : _c.emitEvents({
|
|
3529
3618
|
event: 'ON_FIELD_MOUNT'
|
|
3530
3619
|
});
|
|
@@ -3572,7 +3661,9 @@ class FormCore {
|
|
|
3572
3661
|
templateSubject$: this.templateSubject$,
|
|
3573
3662
|
fieldEventSubject$: this.fieldEventSubject$,
|
|
3574
3663
|
dataSubject$: this.dataSubject$,
|
|
3575
|
-
|
|
3664
|
+
formValidNotification$: this.formValidNotification$,
|
|
3665
|
+
config: this.config,
|
|
3666
|
+
getFormValues: this.getFormValues.bind(this)
|
|
3576
3667
|
}));
|
|
3577
3668
|
} else {
|
|
3578
3669
|
currField.children = ((_c = structElement === null || structElement === void 0 ? void 0 : structElement.children) === null || _c === void 0 ? void 0 : _c.map(el => el.name)) || (currField === null || currField === void 0 ? void 0 : currField.children) || [];
|
|
@@ -3608,6 +3699,7 @@ class FormCore {
|
|
|
3608
3699
|
(_a = this.fields.get(key)) === null || _a === void 0 ? void 0 : _a.emitEvents({
|
|
3609
3700
|
event: 'ON_FIELD_MOUNT'
|
|
3610
3701
|
});
|
|
3702
|
+
this.checkFieldEventQueues(key);
|
|
3611
3703
|
}
|
|
3612
3704
|
});
|
|
3613
3705
|
this.subscribedTemplates.forEach(el => {
|
|
@@ -3682,7 +3774,7 @@ class FormCore {
|
|
|
3682
3774
|
}
|
|
3683
3775
|
/**
|
|
3684
3776
|
*
|
|
3685
|
-
* @param {(payload: { field: string; data: TFormValues }) => void} callback callback function to call
|
|
3777
|
+
* @param {(payload: { field: string; data: TFormValues }) => void} callback callback function to call onData
|
|
3686
3778
|
*/
|
|
3687
3779
|
subscribeData(callback) {
|
|
3688
3780
|
const sub = this.dataSubject$.pipe(groupBy(payload => payload.event), mergeMap(group$ => group$.pipe(debounceTime(this.config.defaultStateRefreshTimeMS))), map(({
|
|
@@ -3701,6 +3793,21 @@ class FormCore {
|
|
|
3701
3793
|
});
|
|
3702
3794
|
return sub;
|
|
3703
3795
|
}
|
|
3796
|
+
/**
|
|
3797
|
+
*
|
|
3798
|
+
* @param {(payload: TFormValidationPayload) => void} callback callback function to call onValid
|
|
3799
|
+
*/
|
|
3800
|
+
subscribeFormValidation(callback) {
|
|
3801
|
+
const sub = this.formValidNotification$.pipe(debounceTime(this.config.defaultStateRefreshTimeMS), map(({
|
|
3802
|
+
fieldTrigger
|
|
3803
|
+
}) => ({
|
|
3804
|
+
fieldTrigger,
|
|
3805
|
+
valid: this.isValid
|
|
3806
|
+
})), distinctUntilKeyChanged('valid')).subscribe({
|
|
3807
|
+
next: callback
|
|
3808
|
+
});
|
|
3809
|
+
return sub;
|
|
3810
|
+
}
|
|
3704
3811
|
/**
|
|
3705
3812
|
* Submits the form by triggering form field events and invoking the onSubmit callback.
|
|
3706
3813
|
*/
|
|
@@ -3731,6 +3838,7 @@ class FormCore {
|
|
|
3731
3838
|
this.templateSubscription$.unsubscribe();
|
|
3732
3839
|
this.fieldEventSubject$.unsubscribe();
|
|
3733
3840
|
this.dataSubject$.unsubscribe();
|
|
3841
|
+
this.formValidNotification$.unsubscribe();
|
|
3734
3842
|
this.fields.forEach(field => field.destroyField());
|
|
3735
3843
|
}
|
|
3736
3844
|
}
|
|
@@ -3769,8 +3877,16 @@ class FormGroup {
|
|
|
3769
3877
|
/**
|
|
3770
3878
|
* Creates an instance of FormGroup.
|
|
3771
3879
|
*/
|
|
3772
|
-
constructor() {
|
|
3880
|
+
constructor(entry) {
|
|
3881
|
+
var _a, _b, _c, _d;
|
|
3882
|
+
this.destroy = () => {
|
|
3883
|
+
this.forms.forEach(form => form.destroy());
|
|
3884
|
+
};
|
|
3773
3885
|
this.forms = new Map();
|
|
3886
|
+
this.config = {
|
|
3887
|
+
defaultAPIdebounceTimeMS: Number((_a = entry === null || entry === void 0 ? void 0 : entry.config) === null || _a === void 0 ? void 0 : _a.defaultAPIdebounceTimeMS) ? Number((_b = entry === null || entry === void 0 ? void 0 : entry.config) === null || _b === void 0 ? void 0 : _b.defaultAPIdebounceTimeMS) : DEFAULT_API_DEBOUNCE_TIME,
|
|
3888
|
+
defaultStateRefreshTimeMS: Number((_c = entry === null || entry === void 0 ? void 0 : entry.config) === null || _c === void 0 ? void 0 : _c.defaultStateRefreshTimeMS) ? Number((_d = entry === null || entry === void 0 ? void 0 : entry.config) === null || _d === void 0 ? void 0 : _d.defaultStateRefreshTimeMS) : DEFAULT_STATE_REFRESH_TIME
|
|
3889
|
+
};
|
|
3774
3890
|
}
|
|
3775
3891
|
/**
|
|
3776
3892
|
* Creates an empty form with given index
|
|
@@ -3784,7 +3900,8 @@ class FormGroup {
|
|
|
3784
3900
|
}) {
|
|
3785
3901
|
const formInstance = new FormCore({
|
|
3786
3902
|
index,
|
|
3787
|
-
mappers
|
|
3903
|
+
mappers,
|
|
3904
|
+
config: this.config
|
|
3788
3905
|
});
|
|
3789
3906
|
this.addForm({
|
|
3790
3907
|
key: index,
|
|
@@ -3805,6 +3922,9 @@ class FormGroup {
|
|
|
3805
3922
|
this.checkIndexes({
|
|
3806
3923
|
key
|
|
3807
3924
|
});
|
|
3925
|
+
if (!formInstance.config) {
|
|
3926
|
+
formInstance.config = this.config;
|
|
3927
|
+
}
|
|
3808
3928
|
this.forms.set(key, formInstance);
|
|
3809
3929
|
}
|
|
3810
3930
|
/**
|
|
@@ -3896,8 +4016,7 @@ class FormGroup {
|
|
|
3896
4016
|
}) {
|
|
3897
4017
|
const subs = ids.reduce((acc, formId) => {
|
|
3898
4018
|
var _a, _b;
|
|
3899
|
-
|
|
3900
|
-
const sub = (_a = this.forms.get(formId)) === null || _a === void 0 ? void 0 : _a.dataSubject$.pipe(groupBy(payload => `${formId}.${payload.event}`), mergeMap(group$ => group$.pipe(debounceTime(100))), map(({
|
|
4019
|
+
const sub = (_a = this.forms.get(formId)) === null || _a === void 0 ? void 0 : _a.dataSubject$.pipe(groupBy(payload => `${formId}.${payload.event}`), mergeMap(group$ => group$.pipe(debounceTime(this.config.defaultStateRefreshTimeMS))), map(({
|
|
3901
4020
|
key
|
|
3902
4021
|
}) => {
|
|
3903
4022
|
var _a;
|
|
@@ -3919,6 +4038,31 @@ class FormGroup {
|
|
|
3919
4038
|
const sub = combineLatest(subs).subscribe(callback);
|
|
3920
4039
|
return sub;
|
|
3921
4040
|
}
|
|
4041
|
+
onValidSubscription({
|
|
4042
|
+
ids,
|
|
4043
|
+
callback
|
|
4044
|
+
}) {
|
|
4045
|
+
const subs = ids.reduce((acc, formId) => {
|
|
4046
|
+
var _a;
|
|
4047
|
+
const sub = (_a = this.forms.get(formId)) === null || _a === void 0 ? void 0 : _a.formValidNotification$.pipe(groupBy(payload => `${formId}.${payload.fieldTrigger}`), mergeMap(group$ => group$.pipe(debounceTime(this.config.defaultStateRefreshTimeMS))), startWith({
|
|
4048
|
+
fieldTrigger: null
|
|
4049
|
+
}), map(() => {
|
|
4050
|
+
var _a;
|
|
4051
|
+
return ((_a = this.forms.get(formId)) === null || _a === void 0 ? void 0 : _a.isValid) === false ? false : true;
|
|
4052
|
+
}));
|
|
4053
|
+
if (sub) {
|
|
4054
|
+
acc[formId] = sub;
|
|
4055
|
+
} else {
|
|
4056
|
+
console.warn(`failed to register validation subscription form id ${formId}`);
|
|
4057
|
+
}
|
|
4058
|
+
return acc;
|
|
4059
|
+
}, {});
|
|
4060
|
+
const sub = combineLatest(subs).pipe(map(forms => ({
|
|
4061
|
+
groupValid: Object.keys(forms).every(formId => forms[formId]),
|
|
4062
|
+
forms
|
|
4063
|
+
}))).subscribe(callback);
|
|
4064
|
+
return sub;
|
|
4065
|
+
}
|
|
3922
4066
|
}
|
|
3923
4067
|
|
|
3924
4068
|
export { FormCore, FormField, FormGroup, TMutationEnum };
|
package/package.json
CHANGED
package/src/helpers/helpers.d.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
/// <reference types="node" />
|
|
2
2
|
import { TEMPLATE_AVALIABLE_SCOPES } from '../constants/constants';
|
|
3
|
+
import { TApiResponsePayload } from '../types/schema';
|
|
3
4
|
import { TSubscribedTemplates } from '../types/template';
|
|
4
5
|
import { OutgoingHttpHeaders } from 'http2';
|
|
5
6
|
/**
|
|
@@ -16,7 +17,7 @@ import { OutgoingHttpHeaders } from 'http2';
|
|
|
16
17
|
* const response = await makeRequest('GET', 'https://api.example.com/data');
|
|
17
18
|
* ```
|
|
18
19
|
*/
|
|
19
|
-
declare function makeRequest(method: string, url: string, headers?: OutgoingHttpHeaders, body?: Record<string, unknown>): Promise<
|
|
20
|
+
declare function makeRequest(method: string, url: string, headers?: OutgoingHttpHeaders, body?: Record<string, unknown>): Promise<TApiResponsePayload>;
|
|
20
21
|
/**
|
|
21
22
|
* Extracts keys enclosed in `${}` from a given expression.
|
|
22
23
|
*
|
package/src/managers/field.d.ts
CHANGED
|
@@ -2,10 +2,11 @@ import { Observable, Subject, Subscription } from 'rxjs';
|
|
|
2
2
|
import { TApiConfig, TApiEvent, TApiResponse, TErrorMessages, TFormatters, TMasks, TResetValueMethods, TSchemaFormConfig, TValidations, TVisibility } from '../types/schema';
|
|
3
3
|
import { IComponentSchema, IComponentSchemaAsFormField } from '../interfaces/schema';
|
|
4
4
|
import { IState } from '../interfaces/state';
|
|
5
|
-
import { TEvents, TFieldEvent, TValueChangeEvent } from '../types/event';
|
|
5
|
+
import { TEvents, TFieldEvent, TFormValidationPayload, TValueChangeEvent } from '../types/event';
|
|
6
6
|
import { TMapper } from '../types/mapper';
|
|
7
7
|
import { SafeSubject } from '../helpers/SafeSubject';
|
|
8
8
|
import { TTemplateEvent } from '../types/template';
|
|
9
|
+
import { TFormValues } from '../types/form';
|
|
9
10
|
/**
|
|
10
11
|
* Represents a form field with observables for managing form state, validations, and API requests.
|
|
11
12
|
*/
|
|
@@ -55,6 +56,7 @@ declare class FormField {
|
|
|
55
56
|
key: string;
|
|
56
57
|
event: TEvents;
|
|
57
58
|
}>;
|
|
59
|
+
formValidNotification$: Subject<Pick<TFormValidationPayload, 'fieldTrigger'>>;
|
|
58
60
|
validateVisibility: (payload: {
|
|
59
61
|
event: TEvents;
|
|
60
62
|
key: string;
|
|
@@ -63,6 +65,7 @@ declare class FormField {
|
|
|
63
65
|
event: TEvents;
|
|
64
66
|
key: string;
|
|
65
67
|
}) => void;
|
|
68
|
+
getFormValues: () => TFormValues<unknown>;
|
|
66
69
|
valueChangeEvent: TValueChangeEvent;
|
|
67
70
|
/**
|
|
68
71
|
* Creates an instance of FormField.
|
|
@@ -76,8 +79,13 @@ declare class FormField {
|
|
|
76
79
|
* @param {Function} options.resetValue - A function to reset the field value.
|
|
77
80
|
* @param {unknown} [options.initialValue] - The initial value of the form field.
|
|
78
81
|
* @param {Subject<{ key: string }>} options.templateSubject$ - A subject for template updates.
|
|
82
|
+
* @param {Subject<TFieldEvent>} options.fieldEventSubject$, - Subject for basic event mapped field emissions, except onData to form instance
|
|
83
|
+
* @param {Subject<{ key: string; event: TEvents }>} options.dataSubject$, - Subject to emit onData events to form instance
|
|
84
|
+
* @param {Subject<{ key: string }>} options.formValidNotification$, - Subject to emit field valid change to form instance
|
|
85
|
+
* @param {TMapper<unknown>} options.mapper, - component generic mapper containing render parameters for adapters
|
|
86
|
+
* @param {() => TFormValues<unknown>} options.getFormValues, - form instance function that builds onData parameter payload from fields
|
|
79
87
|
*/
|
|
80
|
-
constructor({ schemaComponent, config, path, children, validateVisibility, resetValue, initialValue, templateSubject$, fieldEventSubject$, dataSubject$, mapper, }: {
|
|
88
|
+
constructor({ schemaComponent, config, path, children, validateVisibility, resetValue, initialValue, templateSubject$, fieldEventSubject$, dataSubject$, formValidNotification$, mapper, getFormValues, }: {
|
|
81
89
|
schemaComponent: IComponentSchema;
|
|
82
90
|
config?: TSchemaFormConfig;
|
|
83
91
|
path?: string;
|
|
@@ -97,7 +105,9 @@ declare class FormField {
|
|
|
97
105
|
key: string;
|
|
98
106
|
event: TEvents;
|
|
99
107
|
}>;
|
|
108
|
+
formValidNotification$: Subject<Pick<TFormValidationPayload, 'fieldTrigger'>>;
|
|
100
109
|
mapper: TMapper<unknown>;
|
|
110
|
+
getFormValues: () => TFormValues<unknown>;
|
|
101
111
|
});
|
|
102
112
|
/**
|
|
103
113
|
* method to initialize all recycled Subjects and initialize Observers on field instance creation or rerender
|
|
@@ -146,6 +156,10 @@ declare class FormField {
|
|
|
146
156
|
* @param {boolean} visible - The new visibility status to be set.
|
|
147
157
|
*/
|
|
148
158
|
set visibility(visible: boolean);
|
|
159
|
+
/**
|
|
160
|
+
* sets valid field state and notifies form instance via formValidNotification$
|
|
161
|
+
*/
|
|
162
|
+
set valid(valid: boolean);
|
|
149
163
|
/**
|
|
150
164
|
* Retrieves the validity status of the form field.
|
|
151
165
|
*
|
package/src/managers/form.d.ts
CHANGED
|
@@ -3,7 +3,7 @@ import { Subject, Subscription } from 'rxjs';
|
|
|
3
3
|
import { IComponentSchema, IComponentSchemaAsFormField, IFormSchema } from '../interfaces/schema';
|
|
4
4
|
import { TSchemaFormConfig } from '../types/schema';
|
|
5
5
|
import { TSubscribedTemplates, TTemplateEvent } from '../types/template';
|
|
6
|
-
import { TEvents, TFieldEvent, TMutationEvents } from '../types/event';
|
|
6
|
+
import { TEvents, TFieldEvent, TFormValidationPayload, TMutationEvents } from '../types/event';
|
|
7
7
|
import { TFormEntry, TFormValues } from '../types/form';
|
|
8
8
|
import { TMapper } from '../types/mapper';
|
|
9
9
|
import { TEMPLATE_AVALIABLE_SCOPES } from '../constants/constants';
|
|
@@ -24,11 +24,19 @@ declare class FormCore {
|
|
|
24
24
|
key: string;
|
|
25
25
|
event: TEvents;
|
|
26
26
|
}>;
|
|
27
|
+
formValidNotification$: Subject<Pick<TFormValidationPayload, 'fieldTrigger'>>;
|
|
27
28
|
subscribedTemplates: TSubscribedTemplates[];
|
|
28
29
|
action?: string;
|
|
29
30
|
method?: string;
|
|
30
31
|
config: Required<TSchemaFormConfig>;
|
|
31
32
|
mappers: Map<string, TMapper<unknown>>;
|
|
33
|
+
queuedFieldVisibilityEvents: Map<string, {
|
|
34
|
+
hasError: boolean;
|
|
35
|
+
showOnlyIfTrue?: boolean;
|
|
36
|
+
}>;
|
|
37
|
+
queuedFieldResetValuesEvents: Map<string, {
|
|
38
|
+
value: unknown;
|
|
39
|
+
}>;
|
|
32
40
|
/**
|
|
33
41
|
* Creates an instance of FormCore.
|
|
34
42
|
*
|
|
@@ -127,6 +135,12 @@ declare class FormCore {
|
|
|
127
135
|
* @param {TMutationEvents} options.event - Internal event descriptor to handle templating.
|
|
128
136
|
*/
|
|
129
137
|
refreshTemplates({ key, event }: TTemplateEvent): void;
|
|
138
|
+
/**
|
|
139
|
+
* executes events that were stored due to field unavaliability
|
|
140
|
+
*
|
|
141
|
+
* @param {string} field field to check
|
|
142
|
+
*/
|
|
143
|
+
checkFieldEventQueues(field: string): void;
|
|
130
144
|
/**
|
|
131
145
|
* Validates and collects the names of form fields in the provided schema structure.
|
|
132
146
|
*
|
|
@@ -228,13 +242,18 @@ declare class FormCore {
|
|
|
228
242
|
subscribeOnMount<T>(callback: (payload: TFormValues<T>) => void): Subscription;
|
|
229
243
|
/**
|
|
230
244
|
*
|
|
231
|
-
* @param {(payload: { field: string; data: TFormValues }) => void} callback callback function to call
|
|
245
|
+
* @param {(payload: { field: string; data: TFormValues }) => void} callback callback function to call onData
|
|
232
246
|
*/
|
|
233
247
|
subscribeData<T>(callback: (payload: {
|
|
234
248
|
field: string;
|
|
235
249
|
data: TFormValues<T>;
|
|
236
250
|
}) => void): Subscription;
|
|
237
251
|
subscribeOnSubmit<T>(callback: (payload: TFormValues<T>) => void): Subscription;
|
|
252
|
+
/**
|
|
253
|
+
*
|
|
254
|
+
* @param {(payload: TFormValidationPayload) => void} callback callback function to call onValid
|
|
255
|
+
*/
|
|
256
|
+
subscribeFormValidation(callback: (payload: TFormValidationPayload) => void): Subscription;
|
|
238
257
|
/**
|
|
239
258
|
* Submits the form by triggering form field events and invoking the onSubmit callback.
|
|
240
259
|
*/
|
|
@@ -1,15 +1,20 @@
|
|
|
1
1
|
import { TFormValues } from '../types/form';
|
|
2
2
|
import { TMapper } from '../types/mapper';
|
|
3
3
|
import { TFormCore } from './form';
|
|
4
|
+
import { TSchemaFormConfig } from '../types/schema';
|
|
5
|
+
import { TFormGroupOnDataEventPayload, TFormGroupOnValidEventPayload } from '../types/event';
|
|
4
6
|
/**
|
|
5
7
|
* Represents a group that manages multiple forms.
|
|
6
8
|
*/
|
|
7
9
|
declare class FormGroup {
|
|
8
10
|
forms: Map<string, TFormCore>;
|
|
11
|
+
config: Required<TSchemaFormConfig>;
|
|
9
12
|
/**
|
|
10
13
|
* Creates an instance of FormGroup.
|
|
11
14
|
*/
|
|
12
|
-
constructor(
|
|
15
|
+
constructor(entry?: {
|
|
16
|
+
config?: TSchemaFormConfig;
|
|
17
|
+
});
|
|
13
18
|
/**
|
|
14
19
|
* Creates an empty form with given index
|
|
15
20
|
*
|
|
@@ -82,12 +87,13 @@ declare class FormGroup {
|
|
|
82
87
|
submitMultipleFormsByIndex<T>(indexes: string[], callback?: (payload: TFormValues<T>) => void): void;
|
|
83
88
|
onDataSubscription<T>({ ids, callback, }: {
|
|
84
89
|
ids: string[];
|
|
85
|
-
callback: (payload:
|
|
86
|
-
formId: string;
|
|
87
|
-
formField: string;
|
|
88
|
-
values?: TFormValues<T>;
|
|
89
|
-
}>) => void;
|
|
90
|
+
callback: (payload: TFormGroupOnDataEventPayload<T>) => void;
|
|
90
91
|
}): import("rxjs").Subscription;
|
|
92
|
+
onValidSubscription({ ids, callback, }: {
|
|
93
|
+
ids: string[];
|
|
94
|
+
callback: (payload: TFormGroupOnValidEventPayload) => void;
|
|
95
|
+
}): import("rxjs").Subscription;
|
|
96
|
+
destroy: () => void;
|
|
91
97
|
}
|
|
92
98
|
type TFormGroup = FormGroup;
|
|
93
99
|
export { TFormGroup, FormGroup };
|