@bolttech/form-engine-core 1.0.0-beta.7 → 1.0.0-beta.9

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/index.esm.js CHANGED
@@ -2563,6 +2563,8 @@ class FormField {
2563
2563
  }
2564
2564
  /**
2565
2565
  * method to initialize all recycled Subjects and initialize Observers on field instance creation or rerender
2566
+ * due to some visibility conditions unmounts the field from the adapter if they are children of it and avoid
2567
+ * emissions to unsubscribed fields
2566
2568
  */
2567
2569
  initializeObservers() {
2568
2570
  var _a;
@@ -2624,6 +2626,12 @@ class FormField {
2624
2626
  event: 'ON_PROPS'
2625
2627
  });
2626
2628
  }
2629
+ /**
2630
+ * Static function to remove templates form the component props that will be shown when
2631
+ * the field mounts and the template routine executes, to be used on the adapter
2632
+ *
2633
+ * @param {unknown} props - the properties from the adapter components.
2634
+ */
2627
2635
  static filterProps(props) {
2628
2636
  if (Array.isArray(props)) {
2629
2637
  return props.filter(el => typeof el === 'string' && el.includes('${') ? false : true).map(el => FormField.filterProps(el));
@@ -2804,12 +2812,24 @@ class FormField {
2804
2812
  event: 'ON_API_FIELD_RESPONSE'
2805
2813
  });
2806
2814
  }
2815
+ /**
2816
+ * Retrieves the mounted status of the field.
2817
+ *
2818
+ * @returns {boolean} - the mounted status of the field.
2819
+ */
2807
2820
  get mounted() {
2808
2821
  return this._mounted;
2809
2822
  }
2823
+ /**
2824
+ * sets the mountedStatus and notifies the form that the field was mounted on the adapter
2825
+ * and it's ready to be handled by the form instance
2826
+ *
2827
+ * @param {boolean} mountedStatus - the mounted status to be set from the mountField function.
2828
+ */
2810
2829
  set mounted(mountedStatus) {
2811
2830
  if (typeof mountedStatus === 'undefined' || mountedStatus === this.mounted) return;
2812
2831
  this._mounted = mountedStatus;
2832
+ this.initializeObservers();
2813
2833
  this.mountSubject$.next({
2814
2834
  key: this.name,
2815
2835
  status: this.mounted
@@ -2827,9 +2847,9 @@ class FormField {
2827
2847
  valueSubscription,
2828
2848
  propsSubscription
2829
2849
  }) {
2850
+ this.mounted = true;
2830
2851
  this.subscribeValue(valueSubscription);
2831
2852
  this.subscribeState(propsSubscription);
2832
- this.mounted = true;
2833
2853
  this.valueSubject$.next(this.stateValue);
2834
2854
  this.propsSubject$.next(this.props);
2835
2855
  this.visibilitySubject$.next(this.visibility);
@@ -3125,7 +3145,7 @@ class FormCore {
3125
3145
  * @param {((payload: {field: string;data: TFormValues;}) => void) | undefined} [entry.onData] - A callback function to handle data emission.
3126
3146
  */
3127
3147
  constructor(entry) {
3128
- var _a, _b, _c, _d, _e, _f, _g, _h, _j;
3148
+ var _a, _b, _c, _d, _e, _f, _g, _h, _j, _k;
3129
3149
  this.templateSubscription$ = new Subscription();
3130
3150
  this.mappers = new Map();
3131
3151
  this.queuedFieldVisibilityEvents = new Map();
@@ -3136,13 +3156,12 @@ class FormCore {
3136
3156
  this.fields = new Map();
3137
3157
  this.action = entry.action || ((_a = entry.schema) === null || _a === void 0 ? void 0 : _a.action);
3138
3158
  this.method = entry.method || ((_b = entry.schema) === null || _b === void 0 ? void 0 : _b.method);
3139
- this._iVars = entry.iVars || ((_c = entry.schema) === null || _c === void 0 ? void 0 : _c.iVars) || {};
3140
3159
  this.config = {
3141
- defaultAPIdebounceTimeMS: Number((_d = entry.config) === null || _d === void 0 ? void 0 : _d.defaultAPIdebounceTimeMS) ? Number((_e = entry.config) === null || _e === void 0 ? void 0 : _e.defaultAPIdebounceTimeMS) : DEFAULT_API_DEBOUNCE_TIME,
3142
- defaultStateRefreshTimeMS: Number((_f = entry.config) === null || _f === void 0 ? void 0 : _f.defaultStateRefreshTimeMS) ? Number((_g = entry.config) === null || _g === void 0 ? void 0 : _g.defaultStateRefreshTimeMS) : DEFAULT_STATE_REFRESH_TIME,
3143
- defaultLogVerbose: ((_h = entry.config) === null || _h === void 0 ? void 0 : _h.defaultLogVerbose) ? entry.config.defaultLogVerbose : DEFAULT_LOG_VERBOSE
3160
+ defaultAPIdebounceTimeMS: Number((_c = entry.config) === null || _c === void 0 ? void 0 : _c.defaultAPIdebounceTimeMS) ? Number((_d = entry.config) === null || _d === void 0 ? void 0 : _d.defaultAPIdebounceTimeMS) : DEFAULT_API_DEBOUNCE_TIME,
3161
+ defaultStateRefreshTimeMS: Number((_e = entry.config) === null || _e === void 0 ? void 0 : _e.defaultStateRefreshTimeMS) ? Number((_f = entry.config) === null || _f === void 0 ? void 0 : _f.defaultStateRefreshTimeMS) : DEFAULT_STATE_REFRESH_TIME,
3162
+ defaultLogVerbose: ((_g = entry.config) === null || _g === void 0 ? void 0 : _g.defaultLogVerbose) ? entry.config.defaultLogVerbose : DEFAULT_LOG_VERBOSE
3144
3163
  };
3145
- (_j = entry.mappers) === null || _j === void 0 ? void 0 : _j.map(mapper => {
3164
+ (_h = entry.mappers) === null || _h === void 0 ? void 0 : _h.map(mapper => {
3146
3165
  this.mappers.set(mapper.componentName, mapper);
3147
3166
  });
3148
3167
  this.schema && FormCore.checkIndexes(this.schema.components);
@@ -3153,44 +3172,46 @@ class FormCore {
3153
3172
  this.mountSubject$ = new Subject();
3154
3173
  this.formValidNotification$ = new Subject();
3155
3174
  this.subscribedTemplates = [];
3156
- // this.schema && this.serializeStructure(this.schema.components);
3157
- // this.schema && this.subscribeTemplates();
3158
3175
  this.templateSubscription$ = this.templateSubject$.subscribe(this.refreshTemplates.bind(this));
3159
3176
  this.mountSubject$.subscribe(this.mountActions.bind(this));
3160
- // this.templateSubject$.next({
3161
- // scope: 'iVars',
3162
- // event: 'ON_IVARS',
3163
- // });
3164
- /*
3165
- only emits event ON_FIELD_MOUNT if does not have initialValue, if has initialValue, initialValues class property setter will
3166
- emit the value along with ON_FIELD_MOUNT event
3167
- */
3168
- // const initialValues = entry.initialValues || entry.schema?.initialValues;
3169
- // this.fields.forEach((field, key) => {
3170
- // if (
3171
- // !initialValues ||
3172
- // (initialValues && !Object.keys(initialValues).includes(key))
3173
- // ) {
3174
- // const propValue = field?.props?.[field?.valuePropName || ''];
3175
- // !field?.value &&
3176
- // field?.emitValue({
3177
- // value:
3178
- // typeof propValue === 'string' && !propValue.includes('${')
3179
- // ? propValue
3180
- // : '',
3181
- // event: 'ON_FIELD_MOUNT',
3182
- // });
3183
- // }
3184
- // this.refreshTemplates({ scope: 'fields', key, event: 'ON_FIELDS' });
3185
- // });
3186
- // this.setInitialValues(initialValues);
3177
+ this.initialValues = entry.initialValues || ((_j = entry.schema) === null || _j === void 0 ? void 0 : _j.initialValues);
3178
+ this.iVars = entry.iVars || ((_k = entry.schema) === null || _k === void 0 ? void 0 : _k.iVars) || {};
3179
+ }
3180
+ /**
3181
+ * mock function to simulate form mount onto the adapter
3182
+ */
3183
+ generateFields() {
3184
+ this.schema && this.serializeStructure(this.schema.components);
3185
+ this.fields.forEach(field => {
3186
+ field.mountField({
3187
+ valueSubscription: () => null,
3188
+ propsSubscription: () => null
3189
+ });
3190
+ });
3187
3191
  }
3192
+ /**
3193
+ * callback function passed to field instance to notify field adapter mount status
3194
+ * once the field has all field instance properties set, this function will handle all
3195
+ * field routines
3196
+ *
3197
+ * @param { string } entry.key field unique identifier
3198
+ * @param { boolean } entry.status mount status notified from field
3199
+ */
3188
3200
  mountActions({
3189
- status,
3190
- key
3201
+ key,
3202
+ status
3191
3203
  }) {
3192
3204
  var _a;
3193
3205
  if (status) {
3206
+ const field = this.fields.get(key);
3207
+ if (!field) {
3208
+ /*
3209
+ @TODO check a better way to handle nested fields unmounted by visiblity conditions from a parent
3210
+ since they are dependent on adapter field recycling runtimes
3211
+ */
3212
+ this.config.defaultLogVerbose && console.log(`field ${key} was mounted but since it's parent has some visibility condition the field was already removed`);
3213
+ return;
3214
+ }
3194
3215
  this.subscribeTemplates();
3195
3216
  this.refreshTemplates({
3196
3217
  scope: 'fields',
@@ -3201,7 +3222,6 @@ class FormCore {
3201
3222
  event: 'ON_IVARS'
3202
3223
  });
3203
3224
  if (!this.queuedInitialValues.has(key)) {
3204
- const field = this.fields.get(key);
3205
3225
  const propValue = (_a = field === null || field === void 0 ? void 0 : field.props) === null || _a === void 0 ? void 0 : _a[(field === null || field === void 0 ? void 0 : field.valuePropName) || ''];
3206
3226
  !(field === null || field === void 0 ? void 0 : field.value) ? field.emitValue({
3207
3227
  value: typeof propValue === 'string' && !propValue.includes('${') ? propValue : '',
@@ -3213,6 +3233,11 @@ class FormCore {
3213
3233
  this.checkFieldEventQueues(key);
3214
3234
  }
3215
3235
  }
3236
+ /**
3237
+ * initialValues setter to handle field values set externally from the adapter
3238
+ *
3239
+ * @param { Record<string, unknown> | undefined } payload initialValues to set onto fields
3240
+ */
3216
3241
  set initialValues(payload) {
3217
3242
  if (payload) {
3218
3243
  Object.keys(payload).forEach(key => {
@@ -3815,25 +3840,12 @@ class FormCore {
3815
3840
  submitEvent: this.submit.bind(this),
3816
3841
  visibility: fieldSchema.visibility
3817
3842
  }));
3818
- // this.subscribeTemplates();
3819
- // this.refreshTemplates({
3820
- // scope: 'fields',
3821
- // event: 'ON_FIELDS',
3822
- // });
3823
- // // if (!this.queuedInitialValues.has(fieldSchema.name)) {
3824
- // // const field = this.fields.get(fieldSchema.name);
3825
- // // const propValue = field?.props?.[field?.valuePropName || ''];
3826
- // // !field?.value &&
3827
- // // field?.emitValue({
3828
- // // value:
3829
- // // typeof propValue === 'string' && !propValue.includes('${')
3830
- // // ? propValue
3831
- // // : '',
3832
- // // event: 'ON_FIELD_MOUNT',
3833
- // // });
3834
- // // }
3835
- // this.checkFieldEventQueues(fieldSchema.name);
3836
3843
  }
3844
+ /**
3845
+ * function to be called from the adapter to remove a field when a field is removed from it
3846
+ *
3847
+ * @param {{ key: string }} entry.key
3848
+ */
3837
3849
  removeField({
3838
3850
  key
3839
3851
  }) {
@@ -3980,6 +3992,12 @@ class FormCore {
3980
3992
  isValid: this.isValid
3981
3993
  };
3982
3994
  }
3995
+ /**
3996
+ * function to be called to events sent from the adapter
3997
+ *
3998
+ * @param {{callback: (payload: TFieldEvent) => void}} entry.callback callback function from the adapter
3999
+ * @returns
4000
+ */
3983
4001
  subscribeFieldEvent({
3984
4002
  callback
3985
4003
  }) {
@@ -3988,6 +4006,12 @@ class FormCore {
3988
4006
  });
3989
4007
  return sub;
3990
4008
  }
4009
+ /**
4010
+ * to be called from the adapter when the form mounts
4011
+ *
4012
+ * @param {(payload: TFormValues<T>) => void} callback
4013
+ * @returns Subscription
4014
+ */
3991
4015
  subscribeOnMount(callback) {
3992
4016
  const sub = this.mountSubject$.pipe(map(() => this.getFormValues())).subscribe({
3993
4017
  next: callback
@@ -4009,13 +4033,19 @@ class FormCore {
4009
4033
  });
4010
4034
  return sub;
4011
4035
  }
4036
+ /**
4037
+ * method to register a callback function to be called when the form is valid
4038
+ *
4039
+ * @param {(payload: TFormValues<T>) => void} callback callback function to call when the submit action occurs
4040
+ */
4012
4041
  subscribeOnSubmit(callback) {
4013
- const sub = this.submitSubject$.pipe(map(() => this.getFormValues())).subscribe({
4042
+ const sub = this.submitSubject$.subscribe({
4014
4043
  next: callback
4015
4044
  });
4016
4045
  return sub;
4017
4046
  }
4018
4047
  /**
4048
+ * method to check whenever the validity status of the form changes, only emits on status change
4019
4049
  *
4020
4050
  * @param {(payload: TFormValidationPayload) => void} callback callback function to call onValid
4021
4051
  */
@@ -4043,8 +4073,10 @@ class FormCore {
4043
4073
  const values = this.getFormValues();
4044
4074
  this.submitSubject$.next(values);
4045
4075
  }
4076
+ /**
4077
+ * recycles all the Suscriptions, to be called from the adapter when the form leaves the page
4078
+ */
4046
4079
  destroy() {
4047
- console.log('removing form');
4048
4080
  this.submitSubject$.unsubscribe();
4049
4081
  this.templateSubscription$.unsubscribe();
4050
4082
  this.fieldEventSubject$.unsubscribe();
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bolttech/form-engine-core",
3
- "version": "1.0.0-beta.7",
3
+ "version": "1.0.0-beta.9",
4
4
  "module": "./index.esm.js",
5
5
  "type": "module",
6
6
  "main": "./index.esm.js",
@@ -129,6 +129,8 @@ declare class FormField {
129
129
  });
130
130
  /**
131
131
  * method to initialize all recycled Subjects and initialize Observers on field instance creation or rerender
132
+ * due to some visibility conditions unmounts the field from the adapter if they are children of it and avoid
133
+ * emissions to unsubscribed fields
132
134
  */
133
135
  initializeObservers(): void;
134
136
  /**
@@ -143,6 +145,12 @@ declare class FormField {
143
145
  * @param {Record<string, unknown>} props - The new properties to be set.
144
146
  */
145
147
  set props(props: Record<string, unknown>);
148
+ /**
149
+ * Static function to remove templates form the component props that will be shown when
150
+ * the field mounts and the template routine executes, to be used on the adapter
151
+ *
152
+ * @param {unknown} props - the properties from the adapter components.
153
+ */
146
154
  static filterProps(props: unknown): unknown;
147
155
  /**
148
156
  * Retrieves the current state value of the form field.
@@ -209,7 +217,18 @@ declare class FormField {
209
217
  * @param {TApiResponse} response - The new API response data to be set.
210
218
  */
211
219
  set api(response: TApiResponse);
220
+ /**
221
+ * Retrieves the mounted status of the field.
222
+ *
223
+ * @returns {boolean} - the mounted status of the field.
224
+ */
212
225
  get mounted(): boolean;
226
+ /**
227
+ * sets the mountedStatus and notifies the form that the field was mounted on the adapter
228
+ * and it's ready to be handled by the form instance
229
+ *
230
+ * @param {boolean} mountedStatus - the mounted status to be set from the mountField function.
231
+ */
213
232
  set mounted(mountedStatus: boolean);
214
233
  /**
215
234
  * Mounts the form field by initializing necessary subjects and combining their streams.
@@ -57,10 +57,27 @@ declare class FormCore {
57
57
  * @param {((payload: {field: string;data: TFormValues;}) => void) | undefined} [entry.onData] - A callback function to handle data emission.
58
58
  */
59
59
  constructor(entry: TFormEntry & Omit<IFormSchema, 'components'>);
60
- mountActions({ status, key }: {
60
+ /**
61
+ * mock function to simulate form mount onto the adapter
62
+ */
63
+ generateFields(): void;
64
+ /**
65
+ * callback function passed to field instance to notify field adapter mount status
66
+ * once the field has all field instance properties set, this function will handle all
67
+ * field routines
68
+ *
69
+ * @param { string } entry.key field unique identifier
70
+ * @param { boolean } entry.status mount status notified from field
71
+ */
72
+ mountActions({ key, status }: {
61
73
  key: string;
62
74
  status: boolean;
63
75
  }): void;
76
+ /**
77
+ * initialValues setter to handle field values set externally from the adapter
78
+ *
79
+ * @param { Record<string, unknown> | undefined } payload initialValues to set onto fields
80
+ */
64
81
  set initialValues(payload: Record<string, unknown> | undefined);
65
82
  /**
66
83
  * Retrieves the internal variables (iVars) of the form.
@@ -237,6 +254,11 @@ declare class FormCore {
237
254
  fieldSchema: IComponentSchema;
238
255
  mapperElement?: TMapper<unknown>;
239
256
  }): void;
257
+ /**
258
+ * function to be called from the adapter to remove a field when a field is removed from it
259
+ *
260
+ * @param {{ key: string }} entry.key
261
+ */
240
262
  removeField({ key }: {
241
263
  key: string;
242
264
  }): void;
@@ -273,9 +295,21 @@ declare class FormCore {
273
295
  * @returns {TFormValues} The current form values.
274
296
  */
275
297
  getFormValues<T>(): TFormValues<T>;
298
+ /**
299
+ * function to be called to events sent from the adapter
300
+ *
301
+ * @param {{callback: (payload: TFieldEvent) => void}} entry.callback callback function from the adapter
302
+ * @returns
303
+ */
276
304
  subscribeFieldEvent({ callback, }: {
277
305
  callback: (payload: TFieldEvent) => void;
278
306
  }): Subscription;
307
+ /**
308
+ * to be called from the adapter when the form mounts
309
+ *
310
+ * @param {(payload: TFormValues<T>) => void} callback
311
+ * @returns Subscription
312
+ */
279
313
  subscribeOnMount<T>(callback: (payload: TFormValues<T>) => void): Subscription;
280
314
  /**
281
315
  *
@@ -285,8 +319,14 @@ declare class FormCore {
285
319
  field: string;
286
320
  data: TFormValues<T>;
287
321
  }) => void): Subscription;
322
+ /**
323
+ * method to register a callback function to be called when the form is valid
324
+ *
325
+ * @param {(payload: TFormValues<T>) => void} callback callback function to call when the submit action occurs
326
+ */
288
327
  subscribeOnSubmit<T>(callback: (payload: TFormValues<T>) => void): Subscription;
289
328
  /**
329
+ * method to check whenever the validity status of the form changes, only emits on status change
290
330
  *
291
331
  * @param {(payload: TFormValidationPayload) => void} callback callback function to call onValid
292
332
  */
@@ -295,6 +335,9 @@ declare class FormCore {
295
335
  * Submits the form by triggering form field events and invoking the onSubmit callback.
296
336
  */
297
337
  submit<T>(): void;
338
+ /**
339
+ * recycles all the Suscriptions, to be called from the adapter when the form leaves the page
340
+ */
298
341
  destroy(): void;
299
342
  }
300
343
  type TFormCore = FormCore;