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

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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@bolttech/form-engine-core",
3
- "version": "1.0.0-beta.9",
3
+ "version": "1.0.1-beta.0",
4
4
  "module": "./index.esm.js",
5
5
  "type": "module",
6
6
  "main": "./index.esm.js",
@@ -4,7 +4,7 @@ declare const TEMPLATE_REGEX_STRING_CONCATENATION_DETECTOR: RegExp;
4
4
  declare const TEMPLATE_REGEX_DELIMITATOR: RegExp;
5
5
  declare const TEMPLATE_REGEX_OPERATOR_SPLITTER: RegExp;
6
6
  declare const TEMPLATE_REGEX_OPERATOR_MATCHER: RegExp;
7
- declare const TEMPLATE_AVALIABLE_SCOPES: readonly ["fields", "iVars"];
7
+ declare const TEMPLATE_AVALIABLE_SCOPES: readonly ["fields", "iVars", "form"];
8
8
  declare const ALLOWED_RESET_PROPS_MUTATIONS: ("api" | "apiSchema" | "props" | "validations" | "visibilityConditions" | "resetValues")[];
9
9
  declare const DEFAULT_LOG_VERBOSE = false;
10
10
  export { DEFAULT_API_DEBOUNCE_TIME, DEFAULT_STATE_REFRESH_TIME, DEFAULT_LOG_VERBOSE, TEMPLATE_REGEX_STRING_CONCATENATION_DETECTOR, TEMPLATE_REGEX_DELIMITATOR, TEMPLATE_REGEX_OPERATOR_SPLITTER, TEMPLATE_REGEX_OPERATOR_MATCHER, TEMPLATE_AVALIABLE_SCOPES, ALLOWED_RESET_PROPS_MUTATIONS, };
@@ -15,6 +15,8 @@ import { TApiEvent, TFormatters, TMasks, TProps, TResetPathMethods, TResetValueM
15
15
  * @property {TFormatters} [formatters] - The formatters for the component.
16
16
  * @property {TMasks} [masks] - The masks for the component.
17
17
  * @property {IComponentSchema[]} [children] - The child components.
18
+ * @property {boolean} visibility - visibility status the component will mount (to avoid SSR blinking)
19
+ * @property {boolean} persistValue - check this if you want the last visible value to be restored after a visiblity schema rule applied
18
20
  *
19
21
  * @example
20
22
  * ```typescript
@@ -45,7 +47,9 @@ import { TApiEvent, TFormatters, TMasks, TProps, TResetPathMethods, TResetValueM
45
47
  * api: { defaultConfig: { config: { method: 'POST', url: 'https://api.example.com/submit' }, events: [{ eventName: 'ON_FORM_SUBMIT' }] } },
46
48
  * formatters: { capitalize: true },
47
49
  * masks: { currency: { align: 'left', decimal: '.', precision: 2, prefix: '$', thousands: ',' } },
48
- * children: []
50
+ * children: [],
51
+ * visibility: true,
52
+ * persistValue: true,
49
53
  * };
50
54
  * ```
51
55
  */
@@ -63,6 +67,7 @@ interface IComponentSchema {
63
67
  masks?: TMasks;
64
68
  children?: IComponentSchema[];
65
69
  visibility?: boolean;
70
+ persistValue?: boolean;
66
71
  }
67
72
  interface IComponentSchemaAsFormField<T> extends IComponentSchema {
68
73
  mapper?: TMapper<T>;
@@ -1,8 +1,8 @@
1
- import { Observable, Subject, Subscription } from 'rxjs';
1
+ import { Subject, Subscription } from 'rxjs';
2
2
  import { TApiConfig, TApiEvent, TApiResponse, TErrorMessages, TFormatters, TMasks, TResetPathMethods, 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, TFormValidationPayload, TValueChangeEvent } from '../types/event';
5
+ import { TEvents, TFieldEvent, TFieldValidationPayload, TFormDataPayload, 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';
@@ -11,6 +11,7 @@ import { TFormValues } from '../types/form';
11
11
  * Represents a form field with observables for managing form state, validations, and API requests.
12
12
  */
13
13
  declare class FormField {
14
+ formIndex: string;
14
15
  name: string;
15
16
  nameToSubmit?: string;
16
17
  component: string;
@@ -21,7 +22,6 @@ declare class FormField {
21
22
  visibilityConditions?: TVisibility[];
22
23
  resetValues?: TResetValueMethods[];
23
24
  resetPropertyValues?: TResetPathMethods[];
24
- errorMessages?: TErrorMessages;
25
25
  apiSchema?: TApiEvent;
26
26
  formatters?: TFormatters;
27
27
  masks?: TMasks;
@@ -44,19 +44,14 @@ declare class FormField {
44
44
  valueSubject$: SafeSubject<Record<string, unknown>>;
45
45
  valueSubscription$: Subscription;
46
46
  visibilitySubject$: SafeSubject<boolean>;
47
- apiSubject$: SafeSubject<TApiResponse>;
48
47
  fieldEventSubject$: Subject<TFieldEvent>;
49
48
  apiEventQueueSubject$: SafeSubject<{
50
49
  event: TEvents;
51
50
  }>;
52
- fieldState$: Observable<IState>;
53
51
  fieldStateSubscription$: Subscription;
54
52
  templateSubject$: Subject<TTemplateEvent>;
55
- dataSubject$: Subject<{
56
- key: string;
57
- event: TEvents;
58
- }>;
59
- formValidNotification$: Subject<Pick<TFormValidationPayload, 'fieldTrigger'>>;
53
+ dataSubject$: Subject<TFormDataPayload>;
54
+ fieldValidNotification$: Subject<TFieldValidationPayload>;
60
55
  mountSubject$: Subject<{
61
56
  key: string;
62
57
  status: boolean;
@@ -76,6 +71,7 @@ declare class FormField {
76
71
  getFormValues: () => TFormValues<unknown>;
77
72
  valueChangeEvent: TValueChangeEvent;
78
73
  submitEvent: () => void;
74
+ persistValue?: boolean;
79
75
  /**
80
76
  * Creates an instance of FormField.
81
77
  *
@@ -94,7 +90,8 @@ declare class FormField {
94
90
  * @param {TMapper<unknown>} options.mapper, - component generic mapper containing render parameters for adapters
95
91
  * @param {() => TFormValues<unknown>} options.getFormValues, - form instance function that builds onData parameter payload from fields
96
92
  */
97
- constructor({ schemaComponent, config, path, children, validateVisibility, resetValue, resetProperty, templateSubject$, fieldEventSubject$, dataSubject$, formValidNotification$, mountSubject$, mapper, getFormValues, submitEvent, visibility, }: {
93
+ constructor({ formIndex, schemaComponent, config, path, children, validateVisibility, resetValue, resetProperty, templateSubject$, fieldEventSubject$, dataSubject$, fieldValidNotification$, mountSubject$, mapper, getFormValues, submitEvent, visibility, persistValue, }: {
94
+ formIndex: string;
98
95
  schemaComponent: IComponentSchema;
99
96
  config?: TSchemaFormConfig;
100
97
  path?: string;
@@ -114,11 +111,8 @@ declare class FormField {
114
111
  submitEvent: () => void;
115
112
  templateSubject$: Subject<TTemplateEvent>;
116
113
  fieldEventSubject$: Subject<TFieldEvent>;
117
- dataSubject$: Subject<{
118
- key: string;
119
- event: TEvents;
120
- }>;
121
- formValidNotification$: Subject<Pick<TFormValidationPayload, 'fieldTrigger'>>;
114
+ dataSubject$: Subject<TFormDataPayload>;
115
+ fieldValidNotification$: Subject<TFieldValidationPayload>;
122
116
  mountSubject$: Subject<{
123
117
  key: string;
124
118
  status: boolean;
@@ -126,6 +120,7 @@ declare class FormField {
126
120
  mapper: TMapper<unknown>;
127
121
  getFormValues: () => TFormValues<unknown>;
128
122
  visibility?: boolean;
123
+ persistValue?: boolean;
129
124
  });
130
125
  /**
131
126
  * method to initialize all recycled Subjects and initialize Observers on field instance creation or rerender
@@ -193,6 +188,14 @@ declare class FormField {
193
188
  * @returns {boolean} - The validity status of the form field.
194
189
  */
195
190
  get valid(): boolean;
191
+ /**
192
+ * triggers field valid notification to handle the form instance valid notification
193
+ *
194
+ * Note: since form unmount can occur before field unmount, this subject might already be closed by form instance
195
+ * quick workaround is to check if the subject is already closed before emitting
196
+ * if form instance onValid or template form.valid doesn't work properly, might be due to this workaround
197
+ */
198
+ triggerFieldValidNotification(): void;
196
199
  /**
197
200
  * Retrieves the error messages associated with the form field.
198
201
  *
@@ -218,7 +221,10 @@ declare class FormField {
218
221
  */
219
222
  set api(response: TApiResponse);
220
223
  /**
221
- * Retrieves the mounted status of the field.
224
+ * notifies templates and event binded field configurations that a request starts it's processing
225
+ */
226
+ notifyApiRequest(): void;
227
+ /** Retrieves the mounted status of the field.
222
228
  *
223
229
  * @returns {boolean} - the mounted status of the field.
224
230
  */
@@ -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, TFormValidationPayload, TMutationEvents } from '../types/event';
6
+ import { TEvents, TFieldEvent, TFieldValidationPayload, TFormDataPayload, TFormSubmitPayload, 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';
@@ -11,22 +11,21 @@ import { TEMPLATE_AVALIABLE_SCOPES } from '../constants/constants';
11
11
  * Represents the core logic for managing a form, including field management, validation, and submission.
12
12
  */
13
13
  declare class FormCore {
14
+ index: string;
14
15
  schema?: IFormSchema;
15
16
  fields: Map<string, IFormField>;
16
17
  private _iVars;
17
18
  templateSubject$: Subject<TTemplateEvent>;
18
19
  templateSubscription$: Subscription;
19
- submitSubject$: Subject<TFormValues<any>>;
20
+ submitSubject$: Subject<TFormSubmitPayload<unknown>>;
20
21
  mountSubject$: Subject<{
21
22
  key: string;
22
23
  status: boolean;
23
24
  }>;
24
25
  fieldEventSubject$: Subject<TFieldEvent>;
25
- dataSubject$: Subject<{
26
- key: string;
27
- event: TEvents;
28
- }>;
29
- formValidNotification$: Subject<Pick<TFormValidationPayload, 'fieldTrigger'>>;
26
+ dataSubject$: Subject<TFormDataPayload>;
27
+ formValidSubject$: Subject<TFormValidationPayload>;
28
+ fieldValidNotification$: Subject<TFieldValidationPayload>;
30
29
  subscribedTemplates: TSubscribedTemplates[];
31
30
  action?: string;
32
31
  method?: string;
@@ -45,6 +44,7 @@ declare class FormCore {
45
44
  value: unknown;
46
45
  }>;
47
46
  queuedInitialValues: Map<string, unknown>;
47
+ _valid: boolean;
48
48
  /**
49
49
  * Creates an instance of FormCore.
50
50
  *
@@ -92,11 +92,12 @@ declare class FormCore {
92
92
  */
93
93
  set iVars(payload: Record<string, unknown>);
94
94
  /**
95
- * Checks if the form is valid by validating all form fields.
95
+ * Validates all form fields and sets the form valid flag
96
96
  *
97
- * @returns {boolean} True if the form is valid; otherwise, false.
98
97
  */
99
- get isValid(): boolean;
98
+ validateForm(): boolean;
99
+ get valid(): boolean;
100
+ set valid(valid: boolean);
100
101
  /**
101
102
  * Subscribes to templates for dynamic updates.
102
103
  */
@@ -250,9 +251,10 @@ declare class FormCore {
250
251
  * @param fieldSchema
251
252
  * @param mapperElement
252
253
  */
253
- addField({ fieldSchema, mapperElement, }: {
254
+ addField({ fieldSchema, mapperElement, path, }: {
254
255
  fieldSchema: IComponentSchema;
255
256
  mapperElement?: TMapper<unknown>;
257
+ path?: string;
256
258
  }): void;
257
259
  /**
258
260
  * function to be called from the adapter to remove a field when a field is removed from it
@@ -1,14 +1,18 @@
1
- import { TFormValues } from '../types/form';
1
+ import { Subject } from 'rxjs';
2
+ import { TFormEntry, TFormValues } from '../types/form';
2
3
  import { TMapper } from '../types/mapper';
3
4
  import { TFormCore } from './form';
4
5
  import { TSchemaFormConfig } from '../types/schema';
5
- import { TFormGroupOnDataEventPayload, TFormGroupOnSubmitEventPayload, TFormGroupOnValidEventPayload } from '../types/event';
6
+ import { TFormDataPayload, TFormGroupOnDataEventPayload, TFormGroupOnSubmitEventPayload, TFormGroupOnValidEventPayload, TFormSubmitPayload, TFormValidationPayload } from '../types/event';
6
7
  /**
7
8
  * Represents a group that manages multiple forms.
8
9
  */
9
10
  declare class FormGroup {
10
11
  forms: Map<string, TFormCore>;
11
12
  config: Required<TSchemaFormConfig>;
13
+ dataSubject$: Subject<TFormDataPayload>;
14
+ formValidSubject$: Subject<TFormValidationPayload>;
15
+ submitSubject$: Subject<TFormSubmitPayload<unknown>>;
12
16
  /**
13
17
  * Creates an instance of FormGroup.
14
18
  */
@@ -32,9 +36,9 @@ declare class FormGroup {
32
36
  * @param {string} options.key - The key associated with the form instance.
33
37
  * @param {TFormCore} options.formInstance - The instance of the form to add.
34
38
  */
35
- addForm({ key, formInstance }: {
39
+ addForm({ key, params }: {
36
40
  key: string;
37
- formInstance: TFormCore;
41
+ params: TFormEntry;
38
42
  }): void;
39
43
  /**
40
44
  * Retrieves a form instance from the form group.
@@ -9,7 +9,7 @@ import { TFormValues } from './form';
9
9
  * const event: TEvents = 'ON_FIELD_CHANGE';
10
10
  * ```
11
11
  */
12
- type TEvents = 'ON_FIELD_MOUNT' | 'ON_FIELD_CHANGE' | 'ON_FIELD_BLUR' | 'ON_FIELD_FOCUS' | 'ON_FIELD_CLICK' | 'ON_FIELD_KEYUP' | 'ON_FIELD_KEYDOWN' | 'ON_FIELD_CLEARED' | 'ON_FORM_SUBMIT' | 'ON_FIELD_VALIDATION' | 'ON_FORM_MOUNT' | 'ON_API_FIELD_RESPONSE';
12
+ type TEvents = 'ON_FIELD_MOUNT' | 'ON_FIELD_UNMOUNT' | 'ON_FIELD_CHANGE' | 'ON_FIELD_BLUR' | 'ON_FIELD_FOCUS' | 'ON_FIELD_CLICK' | 'ON_FIELD_KEYUP' | 'ON_FIELD_KEYDOWN' | 'ON_FIELD_CLEARED' | 'ON_FORM_SUBMIT' | 'ON_FIELD_VALIDATION' | 'ON_FORM_MOUNT' | 'ON_API_FIELD_REQUEST' | 'ON_API_FIELD_RESPONSE';
13
13
  /**
14
14
  * @type TMutationEvents
15
15
  * Represents the different types of events that can occur internally that triggers templating.
@@ -19,7 +19,7 @@ type TEvents = 'ON_FIELD_MOUNT' | 'ON_FIELD_CHANGE' | 'ON_FIELD_BLUR' | 'ON_FIEL
19
19
  * const event: TMutationEvents = 'ON_VALUE';
20
20
  * ```
21
21
  */
22
- type TMutationEvents = 'ON_VALUE' | 'ON_PROPS' | 'ON_VISIBILITY' | 'ON_API' | 'ON_IVARS' | 'ON_FIELDS' | 'ON_RESET';
22
+ type TMutationEvents = 'ON_VALUE' | 'ON_PROPS' | 'ON_VISIBILITY' | 'ON_API_REQUEST' | 'ON_API_RESPONSE' | 'ON_IVARS' | 'ON_FIELDS' | 'ON_RESET' | 'ON_FORM';
23
23
  declare enum TMutationEnum {
24
24
  ON_VALUE = "value",
25
25
  ON_PROPS = "props",
@@ -51,14 +51,38 @@ type TFieldEvent = {
51
51
  fieldName: string;
52
52
  fieldInstance?: IFormField;
53
53
  };
54
+ /**
55
+ * @type TFormDataPayload
56
+ * Event emitted to formGroup instance to capture onData form events
57
+ */
58
+ type TFormDataPayload = {
59
+ formIndex: string;
60
+ fieldIndex: string;
61
+ event: TEvents;
62
+ };
63
+ /**
64
+ * @type TFormSubmitPayload
65
+ * Event emitted to formGroup instance to capture onSubmit form events
66
+ */
67
+ type TFormSubmitPayload<T> = {
68
+ formIndex: string;
69
+ values: TFormValues<T>;
70
+ };
54
71
  /**
55
72
  * @type TFormValidationPayload
56
73
  * Form onValid event emmited payload on callback function parameter
57
74
  */
58
75
  type TFormValidationPayload = {
59
- fieldTrigger: string;
76
+ formIndex: string;
60
77
  valid: boolean;
61
78
  };
79
+ /**
80
+ * @type TFieldValidationPayload
81
+ * field event emmited payload on field validation
82
+ */
83
+ type TFieldValidationPayload = {
84
+ fieldTrigger: string;
85
+ };
62
86
  /**
63
87
  * @type TFormGroupOnDataEventPayload
64
88
  * Form Group onData event emitted payload on callback function parameter
@@ -81,4 +105,4 @@ type TFormGroupOnValidEventPayload = {
81
105
  * Form Group onSubmit event emitted payload on callback function parameter
82
106
  */
83
107
  type TFormGroupOnSubmitEventPayload<T> = Record<string, TFormValues<T> | undefined>;
84
- export { TEvents, TMutationEvents, TMutationEnum, TValueChangeEvent, TFieldEvent, TFormGroupOnDataEventPayload, TFormGroupOnValidEventPayload, TFormGroupOnSubmitEventPayload, TFormValidationPayload, };
108
+ export { TEvents, TMutationEvents, TMutationEnum, TValueChangeEvent, TFieldEvent, TFormDataPayload, TFormSubmitPayload, TFormGroupOnDataEventPayload, TFormGroupOnValidEventPayload, TFormGroupOnSubmitEventPayload, TFormValidationPayload, TFieldValidationPayload, };
@@ -1,5 +1,7 @@
1
+ import { Subject } from 'rxjs';
1
2
  import { IFormSchema } from '../interfaces/schema';
2
3
  import { TMapper } from './mapper';
4
+ import { TFormDataPayload, TFormSubmitPayload, TFormValidationPayload } from './event';
3
5
  /**
4
6
  * @type TFormValues<T>
5
7
  * Represents the values and state of a form. It has a generic type that allows the importer to determine which type values key will return.
@@ -30,6 +32,9 @@ type TFormValues<T> = {
30
32
  * @property {IFormSchema} [schema] - The schema defining the structure and behavior of the form.
31
33
  * @property {Record<string, unknown>} [initialValues] - The initial values for the form fields.
32
34
  * @property {(data: TFormValues) => void} [onSubmit] - Callback function to handle form submission.
35
+ * @property {Subject<TFormDataPayload>} [dataSubject$] - data subject passed from formGroup instance
36
+ * @property {Subject<TFormValidationPayload>} [formValidSubject$] - formValid subject passed from formGroup instance
37
+ * @property {Subject<TFormSubmitPayload<unknown>>} [submitSubject$] - submit subject passed from formGroup instance
33
38
  *
34
39
  * @example
35
40
  * ```typescript
@@ -43,5 +48,8 @@ type TFormValues<T> = {
43
48
  type TFormEntry = Omit<IFormSchema, 'components'> & {
44
49
  schema?: IFormSchema;
45
50
  mappers?: TMapper<unknown>[];
51
+ dataSubject$?: Subject<TFormDataPayload>;
52
+ formValidSubject$?: Subject<TFormValidationPayload>;
53
+ submitSubject$?: Subject<TFormSubmitPayload<unknown>>;
46
54
  };
47
55
  export { TFormValues, TFormEntry };
@@ -667,7 +667,7 @@ type TResetValueMethods = Omit<TVisibility, 'showOnlyIfTrue' | 'validations'> &
667
667
  validations?: TSchemaValidation;
668
668
  };
669
669
  type TResetPathMethods = {
670
- property: typeof ALLOWED_RESET_PROPS_MUTATIONS[number];
670
+ property: (typeof ALLOWED_RESET_PROPS_MUTATIONS)[number];
671
671
  path: string;
672
672
  field: string;
673
673
  resettledValue: unknown;
@@ -816,6 +816,10 @@ type TApiResponsePayload = {
816
816
  type TApiResponse = {
817
817
  default: TApiResponsePayload;
818
818
  named?: Record<string, TApiResponsePayload>;
819
+ apiState: {
820
+ loading: boolean;
821
+ lastEvent?: TEvents;
822
+ };
819
823
  };
820
824
  /**
821
825
  * Represents the schema config structure