@bolttech/form-engine-core 1.0.7 → 1.0.8

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.
Files changed (3) hide show
  1. package/index.d.ts +15 -7
  2. package/index.esm.js +46 -28
  3. package/package.json +1 -1
package/index.d.ts CHANGED
@@ -1,5 +1,5 @@
1
1
  import * as rxjs from 'rxjs';
2
- import { Subject, Subscription } from 'rxjs';
2
+ import { Subject, Subscription, BehaviorSubject } from 'rxjs';
3
3
  import { TCurrencyLocalCode, TCurrencyCode } from '@gaignoux/currency';
4
4
  import { OutgoingHttpHeaders } from 'http2';
5
5
 
@@ -7,7 +7,12 @@ type AllowOnly<T, K extends keyof T> = Pick<T, K> & {
7
7
  [P in keyof Omit<T, K>]?: never;
8
8
  };
9
9
  type OneOf<T, K = keyof T> = K extends keyof T ? AllowOnly<T, K> : never;
10
- type TValidationHandler = Record<string, (value: unknown, validations: TValidationMethods) => boolean>;
10
+ type TValidationPayload = [
11
+ unknown,
12
+ TValidationMethods,
13
+ TFormValues<unknown>?
14
+ ];
15
+ type TValidationHandler = Record<string, (...args: TValidationPayload) => boolean>;
11
16
 
12
17
  type TComponentPropsMappingSubset = keyof (Pick<TEventPropsEnum, 'onBlur' | 'onChange' | 'onFocus' | 'onKeyDown' | 'onKeyUp' | 'onClick'> & Pick<TEventDataPropsEnum, 'onSubmit'>);
13
18
  /**
@@ -325,7 +330,7 @@ type TLengthValidation = {
325
330
  * const callbackValidation: TCallbackValidation = (value) => typeof value === 'string';
326
331
  * ```
327
332
  */
328
- type TCallbackValidation = (value: unknown) => boolean;
333
+ type TCallbackValidation = (value: unknown, formValues: TFormValues<unknown>) => boolean;
329
334
  /**
330
335
  * @type TBetweenValidation
331
336
  * Represents validation rules that check if a value is between a range.
@@ -1422,6 +1427,7 @@ declare class FormField {
1422
1427
  key: string;
1423
1428
  status: boolean;
1424
1429
  }>;
1430
+ formValuesStateSubject$: BehaviorSubject<TFormValues<unknown>>;
1425
1431
  validateVisibility: (payload: {
1426
1432
  event: TEvents;
1427
1433
  key: string;
@@ -1456,7 +1462,7 @@ declare class FormField {
1456
1462
  * @param {TMapper<unknown>} options.mapper, - component generic mapper containing render parameters for adapters
1457
1463
  * @param {() => TFormValues<unknown>} options.getFormValues, - form instance function that builds onData parameter payload from fields
1458
1464
  */
1459
- constructor({ formIndex, schemaComponent, config, children, validateVisibility, resetValue, resetProperty, templateSubject$, fieldEventSubject$, dataSubject$, fieldValidNotification$, mountSubject$, mapper, getFormValues, submitEvent, visibility, persistValue, }: {
1465
+ constructor({ formIndex, schemaComponent, config, children, validateVisibility, resetValue, resetProperty, templateSubject$, fieldEventSubject$, dataSubject$, fieldValidNotification$, mountSubject$, mapper, formValuesStateSubject$, submitEvent, visibility, persistValue, }: {
1460
1466
  formIndex: string;
1461
1467
  schemaComponent: IComponentSchema;
1462
1468
  config?: TSchemaFormConfig;
@@ -1483,8 +1489,8 @@ declare class FormField {
1483
1489
  key: string;
1484
1490
  status: boolean;
1485
1491
  }>;
1492
+ formValuesStateSubject$: BehaviorSubject<TFormValues<unknown>>;
1486
1493
  mapper: TMapper<unknown>;
1487
- getFormValues: () => TFormValues<unknown>;
1488
1494
  visibility?: boolean;
1489
1495
  persistValue?: boolean;
1490
1496
  });
@@ -1721,6 +1727,7 @@ declare class FormCore {
1721
1727
  dataSubject$: Subject<TFormDataPayload>;
1722
1728
  formValidSubject$: Subject<TFormValidationPayload>;
1723
1729
  fieldValidNotification$: Subject<TFieldValidationPayload>;
1730
+ formValuesStateSubject$: BehaviorSubject<TFormValues<unknown>>;
1724
1731
  subscribedTemplates: TSubscribedTemplates[];
1725
1732
  action?: string;
1726
1733
  method?: string;
@@ -1742,6 +1749,7 @@ declare class FormCore {
1742
1749
  _valid: boolean;
1743
1750
  stopEventsOnSubmit: boolean;
1744
1751
  submitted: boolean;
1752
+ getFormValues: () => TFormValues<unknown>;
1745
1753
  /**
1746
1754
  * Creates an instance of FormCore.
1747
1755
  *
@@ -1998,7 +2006,7 @@ declare class FormCore {
1998
2006
  *
1999
2007
  * @returns {TFormValues} The current form values.
2000
2008
  */
2001
- getFormValues<T>(): TFormValues<T>;
2009
+ getFormState<T>(): TFormValues<T>;
2002
2010
  /**
2003
2011
  * function to be called to events sent from the adapter
2004
2012
  *
@@ -2324,4 +2332,4 @@ type TFormGroupOnValidEventPayload = {
2324
2332
  type TFormGroupOnSubmitEventPayload<T> = Record<string, TFormValues<T> | undefined>;
2325
2333
 
2326
2334
  export { FormCore, FormField, FormGroup, TMutationEnum };
2327
- export type { AllowOnly, IComponentSchema, IComponentSchemaAsFormField, IFormField, IFormSchema, IState, OneOf, TAllowedResetPropsMutationsEnum, TApiConfig, TApiEvent, TApiResponse, TApiResponsePayload, TAvailableValidations, TBetweenDatesValidation, TBetweenValidation, TCallbackValidation, TComponentPropsMapping, TConditionsValidation, TConditionsValidationSet, TCreditCardMatch, TCurrencyMask, TDateFormatsValidation, TDateInterval, TDateOperatorsValidation, TDateValidation, TDocumentValidation, TErrorMessages, TEvent, TEventDataProps, TEventDataPropsEnum, TEventEnum, TEventMessages, TEventMessagesValidationMethods, TEventProps, TEventPropsEnum, TEvents, TFieldEvent, TFieldValidationPayload, TFormCore, TFormDataPayload, TFormDataValues, TFormEntry, TFormGroup, TFormGroupOnDataEventPayload, TFormGroupOnSubmitEventPayload, TFormGroupOnValidEventPayload, TFormSubmitPayload, TFormValidationPayload, TFormValues, TFormatters, TGenericValidationRule, TLengthValidation, TMapper, TMaskGeneric, TMasks, TMultipleValidation, TMutationEvents, TProps, TResetPathMethods, TResetValueMethods, TSchemaFormConfig, TSchemaValidation, TSplitterFormatterValue, TSubscribedTemplates, TTemplateAvaliableScopes, TTemplateAvaliableScopesEnum, TTemplateEvent, TValidationHandler, TValidationMethods, TValidations, TValueChangeEvent, TVisibility };
2335
+ export type { AllowOnly, IComponentSchema, IComponentSchemaAsFormField, IFormField, IFormSchema, IState, OneOf, TAllowedResetPropsMutationsEnum, TApiConfig, TApiEvent, TApiResponse, TApiResponsePayload, TAvailableValidations, TBetweenDatesValidation, TBetweenValidation, TCallbackValidation, TComponentPropsMapping, TConditionsValidation, TConditionsValidationSet, TCreditCardMatch, TCurrencyMask, TDateFormatsValidation, TDateInterval, TDateOperatorsValidation, TDateValidation, TDocumentValidation, TErrorMessages, TEvent, TEventDataProps, TEventDataPropsEnum, TEventEnum, TEventMessages, TEventMessagesValidationMethods, TEventProps, TEventPropsEnum, TEvents, TFieldEvent, TFieldValidationPayload, TFormCore, TFormDataPayload, TFormDataValues, TFormEntry, TFormGroup, TFormGroupOnDataEventPayload, TFormGroupOnSubmitEventPayload, TFormGroupOnValidEventPayload, TFormSubmitPayload, TFormValidationPayload, TFormValues, TFormatters, TGenericValidationRule, TLengthValidation, TMapper, TMaskGeneric, TMasks, TMultipleValidation, TMutationEvents, TProps, TResetPathMethods, TResetValueMethods, TSchemaFormConfig, TSchemaValidation, TSplitterFormatterValue, TSubscribedTemplates, TTemplateAvaliableScopes, TTemplateAvaliableScopesEnum, TTemplateEvent, TValidationHandler, TValidationMethods, TValidationPayload, TValidations, TValueChangeEvent, TVisibility };
package/index.esm.js CHANGED
@@ -1,4 +1,4 @@
1
- import { Subject, Subscription, groupBy, mergeMap, debounceTime, filter, combineLatest, startWith, map, distinctUntilKeyChanged } from 'rxjs';
1
+ import { Subject, Subscription, groupBy, mergeMap, debounceTime, filter, combineLatest, startWith, BehaviorSubject, map, distinctUntilKeyChanged } from 'rxjs';
2
2
  import creditCardType from 'credit-card-type';
3
3
  import isNumber$1 from 'lodash/isNumber';
4
4
  import { getCurrencySymbol } from '@gaignoux/currency';
@@ -1612,9 +1612,9 @@ const repeated = (value, validations) => {
1612
1612
  * };
1613
1613
  * ```
1614
1614
  */
1615
- const callback = (value, validations) => {
1615
+ const callback = (value, validations, formValues) => {
1616
1616
  if (!validations.callback || !((validations === null || validations === void 0 ? void 0 : validations.callback) instanceof Function)) return false;
1617
- return validations.callback(value);
1617
+ return validations.callback(value, formValues);
1618
1618
  };
1619
1619
 
1620
1620
  /**
@@ -2475,9 +2475,9 @@ class SafeSubject extends Subject {
2475
2475
  * const isValid = handleValidation(value, validations, methods, key);
2476
2476
  * console.log(isValid); // Output: true
2477
2477
  */
2478
- function handleValidation(value, validations, methods, key) {
2478
+ function handleValidation(value, validations, methods, key, formValues) {
2479
2479
  if (isFunction(methods[key])) {
2480
- return methods[key](value, validations);
2480
+ return methods[key](value, validations, formValues);
2481
2481
  }
2482
2482
  return namedRule(value, validations[key], methods);
2483
2483
  }
@@ -2518,7 +2518,7 @@ class FormField {
2518
2518
  fieldValidNotification$,
2519
2519
  mountSubject$,
2520
2520
  mapper,
2521
- getFormValues,
2521
+ formValuesStateSubject$,
2522
2522
  submitEvent,
2523
2523
  visibility,
2524
2524
  persistValue
@@ -2550,13 +2550,14 @@ class FormField {
2550
2550
  this.validateVisibility = validateVisibility;
2551
2551
  this.resetValue = resetValue;
2552
2552
  this.resetProperty = resetProperty;
2553
- this.getFormValues = getFormValues;
2554
2553
  this.submitEvent = submitEvent;
2555
2554
  this.templateSubject$ = templateSubject$;
2556
2555
  this.fieldEventSubject$ = fieldEventSubject$;
2557
2556
  this.dataSubject$ = dataSubject$;
2558
2557
  this.fieldValidNotification$ = fieldValidNotification$;
2559
2558
  this.mountSubject$ = mountSubject$;
2559
+ this.formValuesStateSubject$ = formValuesStateSubject$;
2560
+ this.getFormValues = () => this.formValuesStateSubject$.value;
2560
2561
  this._props = FormField.filterProps(cloneDeep(schemaComponent.props || {}));
2561
2562
  this._adapterProps = JSON.stringify(schemaComponent.props || {});
2562
2563
  this._metadata = '';
@@ -2633,7 +2634,7 @@ class FormField {
2633
2634
  */
2634
2635
  set adapterProps(props) {
2635
2636
  const currentProps = JSON.stringify(props || {});
2636
- // it's a very basic comparison to determine if props changed,
2637
+ // it's a very basic comparison to determine if props changed,
2637
2638
  // will need review if we need complex comparisons
2638
2639
  if (currentProps !== this.adapterProps) {
2639
2640
  this.props = FormField.filterProps(props);
@@ -2895,7 +2896,7 @@ class FormField {
2895
2896
  if (typeof mountedStatus === 'undefined' || mountedStatus === this.mounted) return;
2896
2897
  this._mounted = mountedStatus;
2897
2898
  this.initializeObservers();
2898
- this.mountSubject$.next({
2899
+ if (!this.mountSubject$.closed) this.mountSubject$.next({
2899
2900
  key: this.name,
2900
2901
  status: this.mounted
2901
2902
  });
@@ -2918,7 +2919,7 @@ class FormField {
2918
2919
  this.valueSubject$.next(this.stateValue);
2919
2920
  this.propsSubject$.next(this.props);
2920
2921
  this.visibilitySubject$.next(this.visibility);
2921
- this.setFieldValidity({
2922
+ this.emitEvents({
2922
2923
  event: 'ON_FIELD_MOUNT'
2923
2924
  });
2924
2925
  }
@@ -2997,12 +2998,12 @@ class FormField {
2997
2998
  const schemaValidations = (_a = this.validations) === null || _a === void 0 ? void 0 : _a.methods;
2998
2999
  if (schemaValidations) {
2999
3000
  Object.keys(schemaValidations).forEach(validationKey => {
3000
- var _a;
3001
- const error = handleValidation(this.value, schemaValidations, validations, validationKey);
3001
+ var _a, _b;
3002
+ const error = handleValidation(this.value, schemaValidations, validations, validationKey, (_a = this.formValuesStateSubject$) === null || _a === void 0 ? void 0 : _a.value);
3002
3003
  // setting valid flag
3003
3004
  valid = !error && valid;
3004
3005
  // setting error messages
3005
- if (error && ((_a = this.validations) === null || _a === void 0 ? void 0 : _a.messages)) {
3006
+ if (error && ((_b = this.validations) === null || _b === void 0 ? void 0 : _b.messages)) {
3006
3007
  if (validationKey in this.validations.messages) {
3007
3008
  const messages = this.validations.messages;
3008
3009
  errors[validationKey] = messages[validationKey];
@@ -3060,7 +3061,8 @@ class FormField {
3060
3061
  const preConditions = config.preConditions;
3061
3062
  if (preConditions) {
3062
3063
  Object.keys(preConditions).forEach(validationKey => {
3063
- const error = handleValidation(this.value, preConditions, validations, validationKey);
3064
+ var _a;
3065
+ const error = handleValidation(this.value, preConditions, validations, validationKey, (_a = this.formValuesStateSubject$) === null || _a === void 0 ? void 0 : _a.value);
3064
3066
  valid = valid && !error;
3065
3067
  });
3066
3068
  }
@@ -3082,7 +3084,7 @@ class FormField {
3082
3084
  var _b, _c, _d, _e, _f, _g, _h, _j, _k;
3083
3085
  let requestMadeOnce = false;
3084
3086
  const configRequest = config => __awaiter(this, void 0, void 0, function* () {
3085
- var _a;
3087
+ var _a, _b;
3086
3088
  try {
3087
3089
  const {
3088
3090
  status,
@@ -3091,7 +3093,7 @@ class FormField {
3091
3093
  const callbackTransform = (_a = config.transform) === null || _a === void 0 ? void 0 : _a.callback;
3092
3094
  const apiResponseData = callbackTransform ? callbackTransform({
3093
3095
  payload: JSON.parse(String(response)),
3094
- formValues: this.getFormValues()
3096
+ formValues: (_b = this.formValuesStateSubject$) === null || _b === void 0 ? void 0 : _b.value
3095
3097
  }) : JSON.parse(String(response));
3096
3098
  const responseReturn = config.resultPath ? get(apiResponseData, config.resultPath) : apiResponseData;
3097
3099
  // this.apiResponseData = { response };
@@ -3277,11 +3279,21 @@ class FormCore {
3277
3279
  this.submitSubject$ = entry.submitSubject$ ? entry.submitSubject$ : new Subject();
3278
3280
  this.dataSubject$ = entry.dataSubject$ ? entry.dataSubject$ : new Subject();
3279
3281
  this.formValidSubject$ = entry.formValidSubject$ ? entry.formValidSubject$ : new Subject();
3282
+ this.formValuesStateSubject$ = new BehaviorSubject({
3283
+ erroredFields: [],
3284
+ isValid: true,
3285
+ metadata: [],
3286
+ values: []
3287
+ });
3288
+ this.getFormValues = () => this.formValuesStateSubject$.value;
3280
3289
  this.subscribedTemplates = [];
3281
3290
  this.templateSubscription$ = this.templateSubject$.subscribe(this.refreshTemplates.bind(this));
3282
3291
  this.fieldValidNotification$.subscribe(() => {
3283
3292
  this.validateForm();
3284
3293
  });
3294
+ this.fieldEventSubject$.subscribe(() => {
3295
+ this.formValuesStateSubject$.next(this.getFormState());
3296
+ });
3285
3297
  this.mountSubject$.subscribe(this.mountActions.bind(this));
3286
3298
  this.initialValues = entry.initialValues || ((_j = entry.schema) === null || _j === void 0 ? void 0 : _j.initialValues);
3287
3299
  this.iVars = entry.iVars || ((_k = entry.schema) === null || _k === void 0 ? void 0 : _k.iVars) || {};
@@ -3803,7 +3815,7 @@ class FormCore {
3803
3815
  structVisibility.forEach(structElement => {
3804
3816
  if (!structElement.events.includes(event)) return;
3805
3817
  Object.keys(structElement.validations).forEach(validationKey => {
3806
- const error = handleValidation(field.value, structElement.validations, validations, validationKey);
3818
+ const error = handleValidation(field.value, structElement.validations, validations, validationKey, this.formValuesStateSubject$.value);
3807
3819
  if (Array.isArray(structElement.fields)) {
3808
3820
  structElement.fields.forEach(fieldKey => {
3809
3821
  this.setFieldVisibility({
@@ -3882,7 +3894,7 @@ class FormCore {
3882
3894
  return handleFieldRestoration();
3883
3895
  }
3884
3896
  Object.keys(structElement.validations).forEach(validationKey => {
3885
- const error = handleValidation(field.value, structElement.validations, validations, validationKey);
3897
+ const error = handleValidation(field.value, structElement.validations, validations, validationKey, this.formValuesStateSubject$.value);
3886
3898
  if (!error) {
3887
3899
  handleFieldRestoration();
3888
3900
  }
@@ -3948,7 +3960,7 @@ class FormCore {
3948
3960
  });
3949
3961
  }
3950
3962
  Object.keys(structElement.validations).forEach(validationKey => {
3951
- const error = handleValidation(field.value, structElement.validations, validations, validationKey);
3963
+ const error = handleValidation(field.value, structElement.validations, validations, validationKey, this.formValuesStateSubject$.value);
3952
3964
  if (!error) {
3953
3965
  this.setResetPathValue({
3954
3966
  key: structElement.field,
@@ -3991,7 +4003,7 @@ class FormCore {
3991
4003
  validateVisibility: this.validateVisibility.bind(this),
3992
4004
  resetValue: this.resetValue.bind(this),
3993
4005
  resetProperty: this.resetProperty.bind(this),
3994
- getFormValues: this.getFormValues.bind(this),
4006
+ formValuesStateSubject$: this.formValuesStateSubject$,
3995
4007
  templateSubject$: this.templateSubject$,
3996
4008
  fieldEventSubject$: this.fieldEventSubject$,
3997
4009
  dataSubject$: this.dataSubject$,
@@ -4102,14 +4114,14 @@ class FormCore {
4102
4114
  * Prints the current values of all form fields.
4103
4115
  */
4104
4116
  printValues() {
4105
- console.table(this.getFormValues().values);
4117
+ console.table(this.formValuesStateSubject$.value.values);
4106
4118
  }
4107
4119
  /**
4108
4120
  * Gets the current values of all form fields.
4109
4121
  *
4110
4122
  * @returns {TFormValues} The current form values.
4111
4123
  */
4112
- getFormValues() {
4124
+ getFormState() {
4113
4125
  const values = {};
4114
4126
  const metadata = {};
4115
4127
  const erroredFields = [];
@@ -4150,7 +4162,7 @@ class FormCore {
4150
4162
  * @returns Subscription
4151
4163
  */
4152
4164
  subscribeOnMount(callback) {
4153
- const sub = this.mountSubject$.pipe(map(() => this.getFormValues())).subscribe({
4165
+ const sub = this.mountSubject$.pipe(map(() => this.formValuesStateSubject$.value)).subscribe({
4154
4166
  next: callback
4155
4167
  });
4156
4168
  return sub;
@@ -4166,7 +4178,7 @@ class FormCore {
4166
4178
  fieldIndex
4167
4179
  }) => ({
4168
4180
  field: fieldIndex,
4169
- data: this.getFormValues()
4181
+ data: this.formValuesStateSubject$.value
4170
4182
  }))).subscribe({
4171
4183
  next: callback
4172
4184
  });
@@ -4216,7 +4228,7 @@ class FormCore {
4216
4228
  });
4217
4229
  });
4218
4230
  if (!this.valid) return;
4219
- const values = this.getFormValues();
4231
+ const values = this.formValuesStateSubject$.value;
4220
4232
  this.submitSubject$.next({
4221
4233
  formIndex: this.index,
4222
4234
  values
@@ -4227,9 +4239,15 @@ class FormCore {
4227
4239
  * recycles all the Suscriptions, to be called from the adapter when the form leaves the page
4228
4240
  */
4229
4241
  destroy() {
4242
+ this.templateSubject$.unsubscribe();
4230
4243
  this.templateSubscription$.unsubscribe();
4244
+ this.submitSubject$.unsubscribe();
4245
+ this.mountSubject$.unsubscribe();
4231
4246
  this.fieldEventSubject$.unsubscribe();
4247
+ this.dataSubject$.unsubscribe();
4248
+ this.formValidSubject$.unsubscribe();
4232
4249
  this.fieldValidNotification$.unsubscribe();
4250
+ this.formValuesStateSubject$.unsubscribe();
4233
4251
  this.fields.forEach(field => field.destroyField());
4234
4252
  }
4235
4253
  }
@@ -4410,7 +4428,7 @@ class FormGroup {
4410
4428
  indexes.forEach(index => {
4411
4429
  var _a, _b;
4412
4430
  (_a = this.forms.get(index)) === null || _a === void 0 ? void 0 : _a.submit();
4413
- const res = (_b = this.forms.get(index)) === null || _b === void 0 ? void 0 : _b.getFormValues();
4431
+ const res = (_b = this.forms.get(index)) === null || _b === void 0 ? void 0 : _b.formValuesStateSubject$.value;
4414
4432
  const formMetadata = typeof (res === null || res === void 0 ? void 0 : res.metadata) === 'object' && res.metadata !== null ? res.metadata : {};
4415
4433
  isValid = isValid && ((res === null || res === void 0 ? void 0 : res.isValid) || false);
4416
4434
  values = Object.assign(Object.assign({}, values), (res === null || res === void 0 ? void 0 : res.values) || {});
@@ -4444,7 +4462,7 @@ class FormGroup {
4444
4462
  acc[curr] = {
4445
4463
  formId: formIndex,
4446
4464
  formField: fieldIndex,
4447
- values: formInstance.getFormValues()
4465
+ values: formInstance.formValuesStateSubject$.value
4448
4466
  };
4449
4467
  }
4450
4468
  return acc;
@@ -4485,7 +4503,7 @@ class FormGroup {
4485
4503
  }) => ids.includes(formIndex)), map(() => ids.reduce((acc, curr) => {
4486
4504
  const formInstance = this.forms.get(curr);
4487
4505
  if (formInstance) {
4488
- acc[curr] = formInstance.getFormValues();
4506
+ acc[curr] = formInstance.formValuesStateSubject$.value;
4489
4507
  }
4490
4508
  return acc;
4491
4509
  }, {}))).subscribe(callback);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bolttech/form-engine-core",
3
- "version": "1.0.7",
3
+ "version": "1.0.8",
4
4
  "dependencies": {
5
5
  "@gaignoux/currency": "^1.1.0",
6
6
  "credit-card-type": "^10.0.0",