@flowerforce/flower-core 3.1.2-beta.3 → 3.1.2-beta.4

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/dist/index.cjs.js CHANGED
@@ -433,18 +433,23 @@ const FlowerStateUtils = {
433
433
  },
434
434
  makeSelectNodeErrors: (name, currentNodeId) => (state) => {
435
435
  const form = FlowerStateUtils.selectFlowerFormNode(name, currentNodeId)(state);
436
- return {
437
- touched: form?.touched || false,
438
- errors: form?.errors,
439
- isValidating: form?.isValidating,
440
- isValid: form && form.errors
441
- ? Object.values(form.errors).flat().length === 0
442
- : true
443
- };
436
+ return createFormData(form);
444
437
  }
445
438
  };
439
+ const createFormData = (form) => {
440
+ const validationErrors = form && form.errors;
441
+ const customErrors = form && form.customErrors;
442
+ const allErrors = { ...(validationErrors || {}), ...(customErrors || {}) };
443
+ return {
444
+ touched: form?.touched || false,
445
+ errors: form?.errors,
446
+ customErrors: form?.customErrors,
447
+ isValidating: form?.isValidating,
448
+ isValid: allErrors ? Object.values(allErrors).flat().length === 0 : true
449
+ };
450
+ };
446
451
 
447
- const { generateNodes, hasNode, makeObjectRules, generateRulesName, findValidRule } = CoreUtils;
452
+ const { generateNodes, hasNode, makeObjectRules, generateRulesName, findValidRule, getPath } = CoreUtils;
448
453
  /**
449
454
  * These functions are Redux reducers used in a Flux architecture for managing state transitions and updates in a Flower application.
450
455
  */
@@ -601,6 +606,9 @@ const FlowerCoreReducers = {
601
606
  }
602
607
  }
603
608
  },
609
+ formAddCustomErrors: (state, { payload }) => {
610
+ _set(state, [payload.name, 'form', payload.currentNode, 'customErrors', payload.id], payload.errors);
611
+ },
604
612
  formAddErrors: (state, { payload }) => {
605
613
  _set(state, [payload.name, 'form', payload.currentNode, 'errors', payload.id], payload.errors);
606
614
  },
@@ -614,6 +622,9 @@ const FlowerCoreReducers = {
614
622
  ]);
615
623
  _unset(state, [payload.name, 'form', payload.currentNode, 'isValidating']);
616
624
  },
625
+ formFieldTouch: (state, { payload }) => {
626
+ _set(state, [payload.name, 'form', payload.currentNode, 'touches', payload.id], payload.touched);
627
+ },
617
628
  addData: (state, { payload }) => {
618
629
  const prevData = _get(state, [payload.flowName, 'data']);
619
630
  _set(state, [payload.flowName, 'data'], { ...prevData, ...payload.value });
@@ -634,6 +645,14 @@ const FlowerCoreReducers = {
634
645
  setFormIsValidating: (state, { payload }) => {
635
646
  _set(state, [payload.name, 'form', payload.currentNode, 'isValidating'], payload.isValidating);
636
647
  },
648
+ resetForm: (state, { payload }) => {
649
+ const touchedFields = _get(state, [payload.flowName, 'form', payload.id, 'touches'], {});
650
+ Object.keys(touchedFields).forEach((key) => {
651
+ const { flowNameFromPath = payload.flowName, path } = getPath(key);
652
+ _unset(state, [flowNameFromPath, 'data', ...path]);
653
+ });
654
+ _unset(state, [payload.flowName, 'form', payload.id]);
655
+ },
637
656
  node: (state, { payload }) => {
638
657
  const { name, history } = payload;
639
658
  const node = payload.nodeId || payload.node || '';
@@ -743,6 +762,7 @@ const FlowerCoreStateSelectors = {
743
762
  getDataByFlow: (flower) => _get(flower, ['data']) ?? {},
744
763
  getDataFromState: (id) => (data) => (id === '*' ? data : _get(data, id)),
745
764
  makeSelectNodeFormTouched: (form) => form && form.touched,
765
+ makeSelectNodeFormFieldTouched: (id) => (form) => form && form.touches && form.touches[id],
746
766
  makeSelectCurrentNodeId: (flower, startNodeId) => _get(flower, ['current']) || startNodeId,
747
767
  makeSelectCurrentNodeDisabled: (nodes, current) => !!_get(nodes, [current, 'disabled']),
748
768
  makeSelectPrevNodeRetain: (nodes, history, current) => {
@@ -762,17 +782,12 @@ const FlowerCoreStateSelectors = {
762
782
  // eslint-disable-next-line consistent-return
763
783
  return (nodes[prevFlowerNode] && nodes[prevFlowerNode].retain && prevFlowerNode);
764
784
  },
765
- makeSelectNodeErrors: (form) => {
766
- return {
767
- touched: form?.touched || false,
768
- errors: form?.errors,
769
- isValidating: form?.isValidating,
770
- isValid: form && form.errors
771
- ? Object.values(form.errors).flat().length === 0
772
- : true
773
- };
774
- },
775
- makeSelectFieldError: (name, id, validate) => (data) => {
785
+ makeSelectNodeErrors: createFormData,
786
+ makeSelectFieldError: (name, id, validate) => (data, form) => {
787
+ const customErrors = Object.entries((form && form.customErrors) || {})
788
+ .filter(([k]) => k === id)
789
+ .map(([, v]) => v)
790
+ .flat();
776
791
  if (!validate || !data)
777
792
  return [];
778
793
  const errors = validate.filter((rule) => {
@@ -787,7 +802,7 @@ const FlowerCoreStateSelectors = {
787
802
  return hasError;
788
803
  });
789
804
  const result = errors.map((r) => (r && r.message) || 'error');
790
- return result.length === 0 ? [] : result;
805
+ return [...customErrors, ...(result.length === 0 ? [] : result)];
791
806
  },
792
807
  selectorRulesDisabled: (id, rules, keys, flowName, value) => (data, form) => {
793
808
  const newState = { ...data, ...value, $form: form };
package/dist/index.esm.js CHANGED
@@ -431,18 +431,23 @@ const FlowerStateUtils = {
431
431
  },
432
432
  makeSelectNodeErrors: (name, currentNodeId) => (state) => {
433
433
  const form = FlowerStateUtils.selectFlowerFormNode(name, currentNodeId)(state);
434
- return {
435
- touched: form?.touched || false,
436
- errors: form?.errors,
437
- isValidating: form?.isValidating,
438
- isValid: form && form.errors
439
- ? Object.values(form.errors).flat().length === 0
440
- : true
441
- };
434
+ return createFormData(form);
442
435
  }
443
436
  };
437
+ const createFormData = (form) => {
438
+ const validationErrors = form && form.errors;
439
+ const customErrors = form && form.customErrors;
440
+ const allErrors = { ...(validationErrors || {}), ...(customErrors || {}) };
441
+ return {
442
+ touched: form?.touched || false,
443
+ errors: form?.errors,
444
+ customErrors: form?.customErrors,
445
+ isValidating: form?.isValidating,
446
+ isValid: allErrors ? Object.values(allErrors).flat().length === 0 : true
447
+ };
448
+ };
444
449
 
445
- const { generateNodes, hasNode, makeObjectRules, generateRulesName, findValidRule } = CoreUtils;
450
+ const { generateNodes, hasNode, makeObjectRules, generateRulesName, findValidRule, getPath } = CoreUtils;
446
451
  /**
447
452
  * These functions are Redux reducers used in a Flux architecture for managing state transitions and updates in a Flower application.
448
453
  */
@@ -599,6 +604,9 @@ const FlowerCoreReducers = {
599
604
  }
600
605
  }
601
606
  },
607
+ formAddCustomErrors: (state, { payload }) => {
608
+ _set(state, [payload.name, 'form', payload.currentNode, 'customErrors', payload.id], payload.errors);
609
+ },
602
610
  formAddErrors: (state, { payload }) => {
603
611
  _set(state, [payload.name, 'form', payload.currentNode, 'errors', payload.id], payload.errors);
604
612
  },
@@ -612,6 +620,9 @@ const FlowerCoreReducers = {
612
620
  ]);
613
621
  _unset(state, [payload.name, 'form', payload.currentNode, 'isValidating']);
614
622
  },
623
+ formFieldTouch: (state, { payload }) => {
624
+ _set(state, [payload.name, 'form', payload.currentNode, 'touches', payload.id], payload.touched);
625
+ },
615
626
  addData: (state, { payload }) => {
616
627
  const prevData = _get(state, [payload.flowName, 'data']);
617
628
  _set(state, [payload.flowName, 'data'], { ...prevData, ...payload.value });
@@ -632,6 +643,14 @@ const FlowerCoreReducers = {
632
643
  setFormIsValidating: (state, { payload }) => {
633
644
  _set(state, [payload.name, 'form', payload.currentNode, 'isValidating'], payload.isValidating);
634
645
  },
646
+ resetForm: (state, { payload }) => {
647
+ const touchedFields = _get(state, [payload.flowName, 'form', payload.id, 'touches'], {});
648
+ Object.keys(touchedFields).forEach((key) => {
649
+ const { flowNameFromPath = payload.flowName, path } = getPath(key);
650
+ _unset(state, [flowNameFromPath, 'data', ...path]);
651
+ });
652
+ _unset(state, [payload.flowName, 'form', payload.id]);
653
+ },
635
654
  node: (state, { payload }) => {
636
655
  const { name, history } = payload;
637
656
  const node = payload.nodeId || payload.node || '';
@@ -741,6 +760,7 @@ const FlowerCoreStateSelectors = {
741
760
  getDataByFlow: (flower) => _get(flower, ['data']) ?? {},
742
761
  getDataFromState: (id) => (data) => (id === '*' ? data : _get(data, id)),
743
762
  makeSelectNodeFormTouched: (form) => form && form.touched,
763
+ makeSelectNodeFormFieldTouched: (id) => (form) => form && form.touches && form.touches[id],
744
764
  makeSelectCurrentNodeId: (flower, startNodeId) => _get(flower, ['current']) || startNodeId,
745
765
  makeSelectCurrentNodeDisabled: (nodes, current) => !!_get(nodes, [current, 'disabled']),
746
766
  makeSelectPrevNodeRetain: (nodes, history, current) => {
@@ -760,17 +780,12 @@ const FlowerCoreStateSelectors = {
760
780
  // eslint-disable-next-line consistent-return
761
781
  return (nodes[prevFlowerNode] && nodes[prevFlowerNode].retain && prevFlowerNode);
762
782
  },
763
- makeSelectNodeErrors: (form) => {
764
- return {
765
- touched: form?.touched || false,
766
- errors: form?.errors,
767
- isValidating: form?.isValidating,
768
- isValid: form && form.errors
769
- ? Object.values(form.errors).flat().length === 0
770
- : true
771
- };
772
- },
773
- makeSelectFieldError: (name, id, validate) => (data) => {
783
+ makeSelectNodeErrors: createFormData,
784
+ makeSelectFieldError: (name, id, validate) => (data, form) => {
785
+ const customErrors = Object.entries((form && form.customErrors) || {})
786
+ .filter(([k]) => k === id)
787
+ .map(([, v]) => v)
788
+ .flat();
774
789
  if (!validate || !data)
775
790
  return [];
776
791
  const errors = validate.filter((rule) => {
@@ -785,7 +800,7 @@ const FlowerCoreStateSelectors = {
785
800
  return hasError;
786
801
  });
787
802
  const result = errors.map((r) => (r && r.message) || 'error');
788
- return result.length === 0 ? [] : result;
803
+ return [...customErrors, ...(result.length === 0 ? [] : result)];
789
804
  },
790
805
  selectorRulesDisabled: (id, rules, keys, flowName, value) => (data, form) => {
791
806
  const newState = { ...data, ...value, $form: form };
@@ -1,2 +1,9 @@
1
1
  import { CoreStateUtils } from './interfaces/UtilsInterface';
2
2
  export declare const FlowerStateUtils: CoreStateUtils;
3
+ export declare const createFormData: (form: Record<string, any>) => {
4
+ touched: any;
5
+ errors: any;
6
+ customErrors: any;
7
+ isValidating: any;
8
+ isValid: boolean;
9
+ };
@@ -5,7 +5,7 @@ export type ActionWithPayload<T> = {
5
5
  payload: T;
6
6
  };
7
7
  type ReducerFunctionSign<T extends object, R> = (state: Record<string, Flower<T>>, action: ActionWithPayload<R>) => Record<string, Flower<T>> | void;
8
- export type ActionsTypes = 'historyAdd' | 'historyPrevToNode' | 'setFormTouched' | 'forceAddHistory' | 'historyPop' | 'restoreHistory' | 'replaceNode' | 'initializeFromNode' | 'forceResetHistory' | 'destroy' | 'initNodes' | 'setCurrentNode' | 'formAddErrors' | 'formRemoveErrors' | 'addData' | 'addDataByPath' | 'replaceData' | 'unsetData' | 'setFormIsValidating' | 'node' | 'prevToNode' | 'next' | 'prev' | 'reset';
8
+ export type ActionsTypes = 'historyAdd' | 'historyPrevToNode' | 'setFormTouched' | 'forceAddHistory' | 'historyPop' | 'restoreHistory' | 'replaceNode' | 'initializeFromNode' | 'forceResetHistory' | 'destroy' | 'initNodes' | 'setCurrentNode' | 'formAddErrors' | 'formRemoveErrors' | 'addData' | 'addDataByPath' | 'replaceData' | 'unsetData' | 'setFormIsValidating' | 'resetForm' | 'formFieldTouch' | 'node' | 'prevToNode' | 'next' | 'prev' | 'reset';
9
9
  /**
10
10
  * These functions are Redux reducers used in a Flux architecture for managing state transitions and updates in a Flower application.
11
11
  */
@@ -162,6 +162,20 @@ export type ReducersFunctions<T extends Record<string, any> = Record<string, Flo
162
162
  name: string;
163
163
  node: string;
164
164
  }>;
165
+ /**
166
+ * @param state
167
+ * @param action
168
+ *
169
+ * Adds errors to a form node in a flow.
170
+ *
171
+ * @returns state
172
+ */
173
+ formAddCustomErrors: ReducerFunctionSign<T, {
174
+ name: string;
175
+ currentNode: string;
176
+ id: string;
177
+ errors: string[];
178
+ }>;
165
179
  /**
166
180
  * @param state
167
181
  * @param action
@@ -178,6 +192,20 @@ export type ReducersFunctions<T extends Record<string, any> = Record<string, Flo
178
192
  [x: string]: string[];
179
193
  } | string[];
180
194
  }>;
195
+ /**
196
+ * @param state
197
+ * @param action
198
+ *
199
+ * Set touch form single field
200
+ *
201
+ * @returns state
202
+ */
203
+ formFieldTouch: ReducerFunctionSign<T, {
204
+ name: string;
205
+ currentNode: string;
206
+ id: string;
207
+ touched?: boolean;
208
+ }>;
181
209
  /**
182
210
  * @param state
183
211
  * @param action
@@ -331,6 +359,19 @@ export type ReducersFunctions<T extends Record<string, any> = Record<string, Flo
331
359
  name?: string;
332
360
  flowName?: string;
333
361
  initialData?: Record<string, any>;
362
+ }
363
+ /**
364
+ * @param state
365
+ * @param action
366
+ *
367
+ * Reset form.
368
+ *
369
+ * @returns state
370
+ */
371
+ >;
372
+ resetForm: ReducerFunctionSign<T, {
373
+ id: string;
374
+ flowName: string;
334
375
  }>;
335
376
  };
336
377
  export {};
@@ -67,9 +67,15 @@ export interface ISelectors {
67
67
  makeSelectNodeErrors<T extends Record<string, any>>(form: Form<T> | undefined): {
68
68
  touched: boolean;
69
69
  errors: any;
70
+ customErrors: any;
70
71
  isValid: boolean;
71
72
  isValidating?: boolean;
72
73
  };
74
+ /**
75
+ * @param form
76
+ * @returns
77
+ */
78
+ makeSelectNodeFormFieldTouched<T extends Record<string, any>>(id: string): (form: Form<T> | undefined) => boolean | undefined;
73
79
  /**
74
80
  * @param flower
75
81
  * @returns
@@ -94,7 +100,7 @@ export interface ISelectors {
94
100
  makeSelectFieldError<T extends Record<string, any>>(name: string, id: string, validate: {
95
101
  rules?: RulesObject<any>;
96
102
  message?: string;
97
- }[] | null): (data?: T) => Array<string>;
103
+ }[] | null): (data: T | undefined, form: Form<T>) => Array<string>;
98
104
  /**
99
105
  * @param id
100
106
  * @param rules
@@ -103,10 +109,5 @@ export interface ISelectors {
103
109
  * @param value
104
110
  * @returns
105
111
  */
106
- selectorRulesDisabled<T extends Record<string, any>>(id: string, rules: any, keys: string[] | null, flowName: string, value: any): (data: T | undefined, form: {
107
- touched: boolean;
108
- errors: any;
109
- isValid: boolean;
110
- isValidating?: boolean;
111
- }) => boolean;
112
+ selectorRulesDisabled<T extends Record<string, any>>(id: string, rules: any, keys: string[] | null, flowName: string, value: any): (data: T | undefined, form: Form<T>) => boolean;
112
113
  }
@@ -49,4 +49,10 @@ export type Form<T> = {
49
49
  errors?: {
50
50
  [K in keyof T]: Array<string>;
51
51
  };
52
+ customErrors?: {
53
+ [K in keyof T]: Array<string>;
54
+ };
55
+ touches?: {
56
+ [K in keyof T]: boolean;
57
+ };
52
58
  };
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flowerforce/flower-core",
3
- "version": "3.1.2-beta.3",
3
+ "version": "3.1.2-beta.4",
4
4
  "description": "Core functions for flowerJS",
5
5
  "repository": {
6
6
  "type": "git",