@flowerforce/flower-core 3.3.1-beta.1 → 4.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.
Files changed (35) hide show
  1. package/dist/index.cjs.js +241 -271
  2. package/dist/index.esm.js +231 -270
  3. package/dist/src/constants/index.d.ts +5 -0
  4. package/dist/src/event-emitter/index.d.ts +1 -0
  5. package/dist/src/index.d.ts +6 -8
  6. package/dist/src/interfaces/CoreInterface.d.ts +23 -17
  7. package/dist/src/interfaces/ReducerInterface.d.ts +117 -99
  8. package/dist/src/{rules-matcher/interface.d.ts → interfaces/RulesMatcherInterface.d.ts} +1 -1
  9. package/dist/src/interfaces/SelectorsInterface.d.ts +21 -12
  10. package/dist/src/interfaces/Store.d.ts +2 -10
  11. package/dist/src/interfaces/UtilsInterface.d.ts +1 -1
  12. package/dist/src/interfaces/index.d.ts +3 -0
  13. package/dist/src/rules-matcher/RulesMatcher.d.ts +2 -0
  14. package/dist/src/rules-matcher/index.d.ts +2 -0
  15. package/dist/src/rules-matcher/utils.d.ts +2 -3
  16. package/dist/src/state-manager/index.d.ts +2 -0
  17. package/dist/src/state-manager/state-functions/FlowerCoreMergedReducers.d.ts +2 -0
  18. package/dist/src/state-manager/state-functions/FlowerCoreStateFunctions.d.ts +5 -0
  19. package/dist/src/state-manager/state-functions/FlowerDataStateFunctions.d.ts +13 -0
  20. package/dist/src/state-manager/state-functions/index.d.ts +4 -0
  21. package/dist/src/state-manager/state-selectors/FlowerCoreStateSelectors.d.ts +2 -0
  22. package/dist/src/state-manager/state-selectors/FlowerFormStateSelectors.d.ts +2 -0
  23. package/dist/src/state-manager/state-selectors/FlowerSelectorsMerged.d.ts +2 -0
  24. package/dist/src/state-manager/state-selectors/index.d.ts +4 -0
  25. package/dist/src/{FlowerCoreStateUtils.d.ts → utils/FlowerCoreStateUtils.d.ts} +2 -2
  26. package/dist/src/{CoreUtils.d.ts → utils/FlowerCoreUtils.d.ts} +1 -2
  27. package/dist/src/utils/FlowerFlowUtils.d.ts +3 -0
  28. package/dist/src/utils/FlowerFormCoreUtils.d.ts +2 -0
  29. package/dist/src/utils/index.d.ts +4 -0
  30. package/package.json +1 -1
  31. package/dist/src/FlowerCoreStateFunctions.d.ts +0 -5
  32. package/dist/src/FlowerCoreStateSelectors.d.ts +0 -2
  33. package/dist/src/RulesMatcher.d.ts +0 -5
  34. package/dist/src/devtoolState.d.ts +0 -2
  35. /package/dist/src/{Emitter.d.ts → event-emitter/Emitter.d.ts} +0 -0
package/dist/index.esm.js CHANGED
@@ -1,11 +1,5 @@
1
1
  import { TinyEmitter } from 'tiny-emitter';
2
- import _set from 'lodash/set';
3
- import _unset from 'lodash/unset';
4
2
  import _get from 'lodash/get';
5
- import _last from 'lodash/last';
6
- import _slice from 'lodash/slice';
7
- import _cloneDeep from 'lodash/cloneDeep';
8
- import lastIndexOf from 'lodash/lastIndexOf';
9
3
  import find from 'lodash/find';
10
4
  import keyBy from 'lodash/keyBy';
11
5
  import has from 'lodash/has';
@@ -16,10 +10,56 @@ import mapKeys from 'lodash/mapKeys';
16
10
  import mapValues from 'lodash/mapValues';
17
11
  import _trimStart from 'lodash/trimStart';
18
12
  import _intersection from 'lodash/intersection';
13
+ import _set from 'lodash/set';
14
+ import _last from 'lodash/last';
15
+ import _slice from 'lodash/slice';
16
+ import _cloneDeep from 'lodash/cloneDeep';
17
+ import lastIndexOf from 'lodash/lastIndexOf';
18
+ import _unset from 'lodash/unset';
19
19
  import { unflatten } from 'flat';
20
20
 
21
21
  const Emitter = new TinyEmitter();
22
22
 
23
+ var REDUCER_NAME;
24
+ (function (REDUCER_NAME) {
25
+ REDUCER_NAME["FLOWER_FLOW"] = "FlowerFlow";
26
+ REDUCER_NAME["FLOWER_DATA"] = "FlowerData";
27
+ })(REDUCER_NAME || (REDUCER_NAME = {}));
28
+ const devtoolState = {};
29
+
30
+ const FlowerStateUtils = {
31
+ getAllData: (state) => state &&
32
+ Object.entries(state ?? {}).reduce((acc, [k, v]) => ({ ...acc, [k]: v?.data ?? v }), {}),
33
+ selectFlowerFormNode: (name) => (state) => _get(state, name),
34
+ makeSelectCurrentNextRules: (name) => (state) => {
35
+ const nextRules = _get(state, [name, 'nextRules']);
36
+ const currentNodeId = FlowerStateUtils.makeSelectCurrentNodeId(name)(state);
37
+ return _get(nextRules, [currentNodeId]);
38
+ },
39
+ makeSelectCurrentNodeId: (name) => (state) => {
40
+ const subState = _get(state, [name]);
41
+ const startId = _get(state, ['startId']);
42
+ return _get(subState, ['current']) || startId;
43
+ },
44
+ makeSelectNodeErrors: (name) => (state) => {
45
+ const form = FlowerStateUtils.selectFlowerFormNode(name)(state);
46
+ return createFormData(form);
47
+ }
48
+ };
49
+ const createFormData = (form) => {
50
+ const validationErrors = form && form.errors;
51
+ const allErrors = Object.values(validationErrors || {});
52
+ return {
53
+ isSubmitted: form?.isSubmitted || false,
54
+ isDirty: Object.values(form?.dirty || {}).some(Boolean) || false,
55
+ hasFocus: form?.hasFocus,
56
+ errors: form?.errors,
57
+ customErrors: form?.customErrors,
58
+ isValidating: form?.isValidating,
59
+ isValid: allErrors.flat().length === 0
60
+ };
61
+ };
62
+
23
63
  const EMPTY_STRING_REGEXP = /^\s*$/;
24
64
  /**
25
65
  * Defines a utility object named rulesMatcherUtils, which contains various helper functions used for processing rules and data in a rule-matching context.
@@ -240,10 +280,6 @@ const rulesMatcher = (rules, formValue = {}, apply = true, options) => {
240
280
  const valid = rulesMatcherUtils.checkRule(conditions, formValue, options ?? {});
241
281
  return [valid === apply];
242
282
  };
243
- const MatchRules = {
244
- rulesMatcher,
245
- utils: rulesMatcherUtils
246
- };
247
283
 
248
284
  /* eslint-disable no-useless-escape */
249
285
  // TODO align this set of functions to selectors and reducers functions
@@ -266,36 +302,12 @@ const flattenRules = (ob) => {
266
302
  }
267
303
  return result;
268
304
  };
269
- // export const searchEmptyKeyRecursively = <T extends object>(
270
- // _key: "$and" | "$or",
271
- // obj: T
272
- // ) => {
273
- // if (
274
- // isEmpty(obj) ||
275
- // typeof obj !== "object" ||
276
- // Object.keys(obj).length === 0
277
- // ) {
278
- // return true;
279
- // }
280
- // if (Object.keys(obj).includes(_key)) {
281
- // if (obj[_key] && obj[_key].length === 0) return true;
282
- // return Object.keys(obj).map((key) =>
283
- // searchEmptyKeyRecursively(_key, obj[key])
284
- // );
285
- // }
286
- // return Object.keys(obj)
287
- // .map((key) => searchEmptyKeyRecursively(_key, obj[key]))
288
- // .every((v) => v === true);
289
- // };
290
305
  const getRulesExists = (rules) => {
291
- return Object.keys(rules).length ? CoreUtils.mapEdge(rules) : undefined;
306
+ return Object.keys(rules).length ? FlowUtils.mapEdge(rules) : undefined;
292
307
  };
293
- /**
294
- * Defines a collection of utility functions for processing rules, nodes and graph-like structures
295
- */
296
- const CoreUtils = {
308
+ const FlowUtils = {
297
309
  generateRulesName: (nextRules) => {
298
- const a = nextRules.reduce((acc, inc) => {
310
+ return nextRules.reduce((acc, inc) => {
299
311
  const n = typeof inc.rules === 'string'
300
312
  ? inc.rules || '__ERROR_NAME__'
301
313
  : inc.rules?.name || '__ERROR_NAME__';
@@ -304,7 +316,6 @@ const CoreUtils = {
304
316
  [n]: inc.nodeId
305
317
  };
306
318
  }, {});
307
- return a;
308
319
  },
309
320
  mapKeysDeepLodash: (obj, cb, isRecursive) => {
310
321
  /* istanbul ignore next */
@@ -320,13 +331,13 @@ const CoreUtils = {
320
331
  }
321
332
  }
322
333
  if (Array.isArray(obj)) {
323
- return obj.map((item) => CoreUtils.mapKeysDeepLodash(item, cb, true));
334
+ return obj.map((item) => FlowUtils.mapKeysDeepLodash(item, cb, true));
324
335
  }
325
336
  if (!isPlainObject(obj)) {
326
337
  return obj;
327
338
  }
328
339
  const result = mapKeys(obj, cb);
329
- return mapValues(result, (value) => CoreUtils.mapKeysDeepLodash(value, cb, true));
340
+ return mapValues(result, (value) => FlowUtils.mapKeysDeepLodash(value, cb, true));
330
341
  },
331
342
  generateNodes: (nodes) => keyBy(nodes.map((s) => omit(s, 'nextRules')), 'nodeId'),
332
343
  makeObjectRules: (nodes) => nodes.reduce((acc, inc) => ({ ...acc, [inc.nodeId]: inc.nextRules }), {}),
@@ -343,17 +354,18 @@ const CoreUtils = {
343
354
  },
344
355
  mapEdge: (nextNode) => {
345
356
  const res = nextNode.sort((a, b) => {
346
- const x = CoreUtils.isEmptyRules(a.rules);
347
- const y = CoreUtils.isEmptyRules(b.rules);
357
+ const x = FlowUtils.isEmptyRules(a.rules);
358
+ const y = FlowUtils.isEmptyRules(b.rules);
348
359
  return Number(x) - Number(y);
349
360
  });
350
361
  return res;
351
362
  },
352
363
  makeRules: (rules) => Object.entries(rules).reduce((acc2, [k, v]) => [...acc2, { nodeId: k, rules: v }], []),
364
+ // TODO: This function is strictly related to React nodes, could make sense to move it in the flower-react folder
353
365
  generateNodesForFlowerJson: (nodes) => nodes
354
366
  .filter((e) => !!_get(e, 'props.id'))
355
367
  .map((e) => {
356
- const rules = CoreUtils.makeRules(e.props.to ?? {});
368
+ const rules = FlowUtils.makeRules(e.props.to ?? {});
357
369
  const nextRules = getRulesExists(rules);
358
370
  const children = e.props.data?.children;
359
371
  return {
@@ -366,29 +378,6 @@ const CoreUtils = {
366
378
  disabled: e.props.disabled
367
379
  };
368
380
  }),
369
- cleanPath: (name, char = '^') => _trimStart(name, char),
370
- getPath: (idValue) => {
371
- if (!idValue) {
372
- return {
373
- path: []
374
- };
375
- }
376
- if (idValue === '*') {
377
- return {
378
- path: '*'
379
- };
380
- }
381
- if (idValue.indexOf('^') === 0) {
382
- const [flowNameFromPath, ...rest] = CoreUtils.cleanPath(idValue).split('.');
383
- return {
384
- flowNameFromPath,
385
- path: rest
386
- };
387
- }
388
- return {
389
- path: idValue.split('.')
390
- };
391
- },
392
381
  allEqual: (arr, arr2) => arr.length === arr2.length && arr.every((v) => arr2.includes(v)),
393
382
  findValidRule: (nextRules, value, prefix) => find(nextRules, (rule) => {
394
383
  // fix per evitare di entrare in un nodo senza regole, ma con un name,
@@ -408,53 +397,52 @@ const CoreUtils = {
408
397
  if (typeof rule.rules.rules === 'string') {
409
398
  return false;
410
399
  }
411
- const [valid] = MatchRules.rulesMatcher(rule.rules.rules, value, true, {
400
+ const [valid] = rulesMatcher(rule.rules.rules, value, true, {
412
401
  prefix
413
402
  });
414
403
  return valid;
415
404
  })
416
405
  };
417
406
 
418
- const FlowerStateUtils = {
419
- getAllData: (state) => state &&
420
- Object.entries(state ?? {}).reduce((acc, [k, v]) => ({ ...acc, [k]: v.data }), {}),
421
- selectFlowerFormNode: (name, id) => (state) => _get(state, [name, 'form', id]),
422
- makeSelectCurrentNextRules: (name) => (state) => {
423
- const nextRules = _get(state, [name, 'nextRules']);
424
- const currentNodeId = FlowerStateUtils.makeSelectCurrentNodeId(name)(state);
425
- return _get(nextRules, [currentNodeId]);
426
- },
427
- makeSelectCurrentNodeId: (name) => (state) => {
428
- const subState = _get(state, [name]);
429
- const startId = _get(state, ['startId']);
430
- return _get(subState, ['current']) || startId;
431
- },
432
- makeSelectNodeErrors: (name, currentNodeId) => (state) => {
433
- const form = FlowerStateUtils.selectFlowerFormNode(name, currentNodeId)(state);
434
- return createFormData(form);
407
+ const FormUtils = {
408
+ cleanPath: (name, char = '^') => _trimStart(name, char),
409
+ getPath: (idValue) => {
410
+ if (!idValue) {
411
+ return {
412
+ path: []
413
+ };
414
+ }
415
+ if (idValue === '*') {
416
+ return {
417
+ path: '*'
418
+ };
419
+ }
420
+ if (idValue.indexOf('^') === 0) {
421
+ const [formName, ...rest] = FormUtils.cleanPath(idValue).split('.');
422
+ return {
423
+ formName,
424
+ path: rest
425
+ };
426
+ }
427
+ return {
428
+ path: idValue.split('.')
429
+ };
435
430
  }
436
431
  };
437
- const createFormData = (form) => {
438
- const validationErrors = form && form.errors;
439
- const allErrors = Object.values(validationErrors || {});
440
- return {
441
- isSubmitted: form?.isSubmitted || false,
442
- isDirty: form?.isDirty || false,
443
- hasFocus: form?.hasFocus,
444
- errors: form?.errors,
445
- customErrors: form?.customErrors,
446
- isValidating: form?.isValidating,
447
- isValid: allErrors.flat().length === 0
448
- };
449
- };
450
432
 
451
- const devtoolState = {};
433
+ /**
434
+ * Defines a collection of utility functions for processing rules, nodes and graph-like structures
435
+ */
436
+ const CoreUtils = {
437
+ ...FlowUtils,
438
+ ...FormUtils
439
+ };
452
440
 
453
- const { generateNodes, hasNode, makeObjectRules, generateRulesName, findValidRule, getPath } = CoreUtils;
441
+ const { generateNodes, hasNode, makeObjectRules, generateRulesName, findValidRule } = CoreUtils;
454
442
  /**
455
443
  * These functions are Redux reducers used in a Flux architecture for managing state transitions and updates in a Flower application.
456
444
  */
457
- const FlowerCoreReducers = {
445
+ const FlowerCoreBaseReducers = {
458
446
  historyAdd: (state, { payload }) => {
459
447
  if (hasNode(state, payload.name, payload.node)) {
460
448
  state[payload.name].history.push(payload.node);
@@ -473,27 +461,11 @@ const FlowerCoreReducers = {
473
461
  }
474
462
  return state;
475
463
  },
476
- setFormTouched: (state, { payload }) => {
477
- if (!_get(state, [
478
- typeof payload === 'string' ? payload : payload.flowName,
479
- 'nodes',
480
- typeof payload === 'string' ? payload : payload.currentNode
481
- ])) {
482
- return state;
483
- }
484
- _set(state, [
485
- typeof payload === 'string' ? payload : payload.flowName,
486
- 'form',
487
- typeof payload === 'string' ? payload : payload.currentNode,
488
- 'isSubmitted'
489
- ], true);
490
- return state;
491
- },
492
464
  // TODO check internal logic and use case
493
465
  /* istanbul ignore next */
494
466
  forceAddHistory: (state, { payload }) => {
495
467
  const { name, flowName, history } = payload;
496
- const key = name || flowName || '' || '';
468
+ const key = name || flowName || '';
497
469
  const resultHistory = history.slice(1, -1);
498
470
  state[key].history.push(...resultHistory);
499
471
  return state;
@@ -566,7 +538,8 @@ const FlowerCoreReducers = {
566
538
  return state;
567
539
  },
568
540
  destroy: (state, { payload }) => {
569
- _set(state, [payload.name], {});
541
+ delete state[payload.name];
542
+ return state;
570
543
  },
571
544
  initNodes: (state, { payload }) => {
572
545
  if (payload.persist && _get(state, [payload.name, 'persist']))
@@ -589,8 +562,7 @@ const FlowerCoreReducers = {
589
562
  current,
590
563
  history,
591
564
  nodes: generateNodes(payload.nodes),
592
- nextRules: makeObjectRules(payload.nodes),
593
- data: payload.initialData
565
+ nextRules: makeObjectRules(payload.nodes)
594
566
  });
595
567
  },
596
568
  // TODO usato solo da flower su vscode
@@ -607,105 +579,14 @@ const FlowerCoreReducers = {
607
579
  }
608
580
  }
609
581
  },
610
- formAddCustomErrors: (state, { payload }) => {
611
- _set(state, [payload.name, 'form', payload.currentNode, 'customErrors', payload.id], payload.errors);
612
- },
613
- formAddErrors: (state, { payload }) => {
614
- _set(state, [payload.name, 'form', payload.currentNode, 'errors', payload.id], payload.errors);
615
- },
616
- formRemoveErrors: (state, { payload }) => {
617
- _unset(state, [
618
- payload.name,
619
- 'form',
620
- payload.currentNode,
621
- 'errors',
622
- payload.id
623
- ]);
624
- _unset(state, [
625
- payload.name,
626
- 'form',
627
- payload.currentNode,
628
- 'customErrors',
629
- payload.id
630
- ]);
631
- _unset(state, [payload.name, 'form', payload.currentNode, 'isValidating']);
632
- },
633
- formFieldTouch: (state, { payload }) => {
634
- _set(state, [payload.name, 'form', payload.currentNode, 'touches', payload.id], payload.touched);
635
- },
636
- formFieldFocus: (state, { payload }) => {
637
- if (!payload.focused) {
638
- _unset(state, [payload.name, 'form', payload.currentNode, 'hasFocus']);
639
- return;
640
- }
641
- _set(state, [payload.name, 'form', payload.currentNode, 'hasFocus'], payload.id);
642
- },
643
- addData: (state, { payload }) => {
644
- const prevData = _get(state, [payload.flowName, 'data']);
645
- _set(state, [payload.flowName, 'data'], { ...prevData, ...payload.value });
646
- },
647
- addDataByPath: (state, { payload }) => {
648
- const { path: newpath } = getPath(payload.id);
649
- const currentNode = FlowerStateUtils.makeSelectCurrentNodeId(payload.flowName)(state);
650
- if (payload.id && payload.id.length) {
651
- _set(state, [payload.flowName, 'data', ...newpath], payload.value);
652
- if (payload && payload.dirty) {
653
- _set(state, [payload.flowName, 'form', currentNode, 'dirty', payload.id], payload.dirty);
654
- _set(state, [payload.flowName, 'form', currentNode, 'isDirty'], true);
655
- }
656
- }
657
- },
658
- // TODO usato al momento solo il devtool
659
- replaceData: /* istanbul ignore next */ (state, { payload }) => {
660
- /* istanbul ignore next */
661
- _set(state, [payload.flowName, 'data'], payload.value);
662
- },
663
- unsetData: (state, { payload }) => {
664
- const currentNode = FlowerStateUtils.makeSelectCurrentNodeId(payload.flowName)(state);
665
- _unset(state, [
666
- payload.flowName,
667
- 'form',
668
- currentNode,
669
- 'dirty',
670
- ...payload.id
671
- ]);
672
- _unset(state, [
673
- payload.flowName,
674
- 'form',
675
- currentNode,
676
- 'touches',
677
- ...payload.id
678
- ]);
679
- _unset(state, [payload.flowName, 'data', ...payload.id]);
680
- },
681
- setFormIsValidating: (state, { payload }) => {
682
- _set(state, [payload.name, 'form', payload.currentNode, 'isValidating'], payload.isValidating);
683
- },
684
- resetForm: (state, { payload }) => {
685
- const touchedFields = _get(state, [payload.flowName, 'form', payload.id, 'errors'], {});
686
- Object.keys(touchedFields).forEach((key) => {
687
- const { flowNameFromPath = payload.flowName, path } = getPath(key);
688
- _unset(state, [flowNameFromPath, 'data', ...path]);
689
- });
690
- _unset(state, [payload.flowName, 'form', payload.id, 'touches']);
691
- _unset(state, [payload.flowName, 'form', payload.id, 'dirty']);
692
- _unset(state, [payload.flowName, 'form', payload.id, 'isDirty']);
693
- _unset(state, [payload.flowName, 'form', payload.id, 'isSubmitted']);
694
- },
695
582
  node: (state, { payload }) => {
696
583
  const { name, history } = payload;
697
584
  const node = payload.nodeId || payload.node || '';
698
585
  const flowName = name || payload.flowName || '';
699
- const startNode = _get(state, [payload.name, 'startId']);
700
- const currentNodeId = _get(state, [payload.name, 'current'], startNode);
701
- FlowerCoreReducers.setFormTouched(state, {
702
- type: 'setFormTouched',
703
- payload: { flowName, currentNode: currentNodeId }
704
- });
705
586
  /* istanbul ignore next */
706
587
  // eslint-disable-next-line no-underscore-dangle
707
588
  if (devtoolState && _get(devtoolState, '__FLOWER_DEVTOOLS__') && history) {
708
- FlowerCoreReducers.forceAddHistory(state, {
589
+ FlowerCoreBaseReducers.forceAddHistory(state, {
709
590
  type: 'forceAddHistory',
710
591
  payload: {
711
592
  name,
@@ -714,34 +595,35 @@ const FlowerCoreReducers = {
714
595
  }
715
596
  });
716
597
  }
717
- FlowerCoreReducers.historyAdd(state, {
598
+ FlowerCoreBaseReducers.historyAdd(state, {
718
599
  type: 'historyAdd',
719
600
  payload: { name: name || flowName || '', node }
720
601
  });
721
602
  },
722
603
  prevToNode: (state, { payload }) => {
723
604
  const { node, name, flowName } = payload;
724
- FlowerCoreReducers.historyPrevToNode(state, {
605
+ FlowerCoreBaseReducers.historyPrevToNode(state, {
725
606
  type: 'historyPrevToNode',
726
607
  payload: { name: name || flowName || '', node }
727
608
  });
728
609
  },
729
610
  next: (state, { payload }) => {
730
- const { name, data = {}, route } = payload;
731
- const flowName = name || payload.flowName || '';
611
+ const { name, route, flowName: flow, data = {}, dataIn = {} } = payload;
612
+ const flowName = name || flow || '';
613
+ const { FlowerData, FlowerFlow, ...external } = data;
732
614
  const currentNodeId = FlowerStateUtils.makeSelectCurrentNodeId(flowName)(state);
733
615
  const currentNextRules = FlowerStateUtils.makeSelectCurrentNextRules(flowName)(state);
734
- const form = FlowerStateUtils.makeSelectNodeErrors(flowName, currentNodeId)(state);
735
- const clonedData = _cloneDeep(FlowerStateUtils.getAllData(state));
616
+ const $data = FlowerStateUtils.makeSelectNodeErrors(flowName, currentNodeId)(FlowerData);
617
+ const internalClonedData = _cloneDeep(FlowerStateUtils.getAllData(FlowerData));
618
+ const externalClonedData = _cloneDeep(FlowerStateUtils.getAllData(external));
736
619
  const stateWithNodeData = {
737
- $in: data,
738
- $form: form,
739
- ...clonedData
620
+ $in: dataIn,
621
+ /** @deprecated use $data instead */
622
+ $form: $data,
623
+ $data,
624
+ ...externalClonedData,
625
+ ...internalClonedData
740
626
  };
741
- FlowerCoreReducers.setFormTouched(state, {
742
- type: 'setFormTouched',
743
- payload: { flowName, currentNode: currentNodeId }
744
- });
745
627
  if (!currentNextRules) {
746
628
  return;
747
629
  }
@@ -750,7 +632,7 @@ const FlowerCoreReducers = {
750
632
  if (!rulesByName[route]) {
751
633
  return;
752
634
  }
753
- FlowerCoreReducers.historyAdd(state, {
635
+ FlowerCoreBaseReducers.historyAdd(state, {
754
636
  type: 'historyAdd',
755
637
  payload: { name: flowName, node: rulesByName[route] }
756
638
  });
@@ -761,51 +643,132 @@ const FlowerCoreReducers = {
761
643
  if (!nextNumberNode) {
762
644
  return;
763
645
  }
764
- FlowerCoreReducers.historyAdd(state, {
646
+ FlowerCoreBaseReducers.historyAdd(state, {
765
647
  type: 'historyAdd',
766
648
  payload: { name: flowName, node: nextNumberNode }
767
649
  });
768
650
  },
769
651
  prev: (state, { payload }) => {
770
652
  const { name, flowName } = payload;
771
- FlowerCoreReducers.historyPop(state, {
653
+ FlowerCoreBaseReducers.historyPop(state, {
772
654
  type: 'historyPop',
773
655
  payload: { name: name || flowName || '' }
774
656
  });
775
657
  },
776
658
  restart: (state, { payload }) => {
777
659
  const { name, flowName } = payload;
778
- FlowerCoreReducers.restoreHistory(state, {
660
+ FlowerCoreBaseReducers.restoreHistory(state, {
779
661
  type: 'restoreHistory',
780
662
  payload: { name: name || flowName || '' }
781
663
  });
782
664
  },
783
665
  reset: (state, { payload }) => {
784
- const { name, flowName, initialData } = payload;
785
- FlowerCoreReducers.restoreHistory(state, {
666
+ const { name, flowName } = payload;
667
+ FlowerCoreBaseReducers.restoreHistory(state, {
786
668
  type: 'restoreHistory',
787
669
  payload: { name: name || flowName || '' }
788
670
  });
789
- _set(state, [name || flowName || '', 'form'], {});
790
- _set(state, [name || flowName || '', 'data'], initialData);
791
671
  }
792
672
  };
793
673
 
794
- const FlowerCoreStateSelectors = {
795
- selectGlobal: (state) => state && state.flower,
674
+ const { getPath } = CoreUtils;
675
+ /**
676
+ * formName => FlowerForm
677
+ * initialData => FlowerForm
678
+ * fieldName => FlowerField
679
+ * fieldValue => FlowerField
680
+ * errors => FlowerField
681
+ * customErrors => FlowerField
682
+ * fieldTouched => FlowerField
683
+ * fieldDirty => FlowerField
684
+ * fieldHasFocus => FlowerField
685
+ */
686
+ const FlowerCoreDataReducers = {
687
+ setFormTouched: (state, { payload }) => {
688
+ if (!_get(state, typeof payload === 'string' ? payload : payload.formName)) {
689
+ return state;
690
+ }
691
+ _set(state, typeof payload === 'string' ? payload : payload.formName, true);
692
+ return state;
693
+ },
694
+ formAddCustomErrors: (state, { payload }) => {
695
+ _set(state, [payload.formName, 'customErrors', payload.id], payload.errors);
696
+ },
697
+ formAddErrors: (state, { payload }) => {
698
+ _set(state, [payload.formName, 'errors', payload.id], payload.errors);
699
+ },
700
+ formRemoveErrors: (state, { payload }) => {
701
+ _unset(state, [payload.formName, 'errors', payload.id]);
702
+ _unset(state, [payload.formName, 'customErrors', payload.id]);
703
+ _unset(state, [payload.formName, 'isValidating']);
704
+ },
705
+ formFieldTouch: (state, { payload }) => {
706
+ _set(state, [payload.formName, 'touches', payload.id], payload.touched);
707
+ },
708
+ formFieldDirty: (state, { payload }) => {
709
+ _set(state, [payload.formName, 'dirty', payload.id], payload.dirty);
710
+ },
711
+ formFieldFocus: (state, { payload }) => {
712
+ if (!payload.focused) {
713
+ _unset(state, [payload.formName, 'hasFocus']);
714
+ return;
715
+ }
716
+ _set(state, [payload.formName, 'hasFocus'], payload.id);
717
+ },
718
+ addData: (state, { payload }) => {
719
+ const prevData = _get(state, [payload.formName, 'data'], {});
720
+ _set(state, [payload.formName, 'data'], { ...prevData, ...payload.value });
721
+ },
722
+ addDataByPath: (state, { payload }) => {
723
+ const { path: newpath } = getPath(payload.id);
724
+ if (payload.id && payload.id.length) {
725
+ _set(state, [payload.formName, 'data', ...newpath], payload.value);
726
+ if (payload && payload.dirty) {
727
+ _set(state, [payload.formName, 'dirty', payload.id], payload.dirty);
728
+ }
729
+ }
730
+ },
731
+ // TODO usato al momento solo il devtool
732
+ replaceData: /* istanbul ignore next */ (state, { payload }) => {
733
+ /* istanbul ignore next */
734
+ _set(state, [payload.formName, 'data'], payload.value);
735
+ },
736
+ unsetData: (state, { payload }) => {
737
+ _unset(state, [payload.formName, 'data', ...payload.id]);
738
+ },
739
+ setFormIsValidating: (state, { payload }) => {
740
+ _set(state, [payload.formName, 'isValidating'], payload.isValidating);
741
+ },
742
+ resetForm: (state, { payload: { formName, initialData } }) => {
743
+ const touchedFields = _get(state, [formName, 'errors'], {});
744
+ const newStateData = initialData
745
+ ? Object.keys(touchedFields).reduce((acc, key) => {
746
+ const { path } = getPath(key);
747
+ const initialDataByPath = _get(initialData, [...path], undefined);
748
+ _set(acc, [...path], initialDataByPath);
749
+ return acc;
750
+ }, {})
751
+ : {};
752
+ _set(state, [formName, 'data'], newStateData);
753
+ _unset(state, [formName, 'touches']);
754
+ _unset(state, [formName, 'dirty']);
755
+ _unset(state, [formName, 'isSubmitted']);
756
+ },
757
+ initForm: (state, { payload: { formName, initialData } }) => {
758
+ _set(state, [formName, 'data'], initialData);
759
+ }
760
+ };
761
+
762
+ const FlowerCoreReducers = { ...FlowerCoreBaseReducers, ...FlowerCoreDataReducers };
763
+
764
+ const FlowerCoreStateBaseSelectors = {
765
+ selectGlobal: (state) => state && state[REDUCER_NAME.FLOWER_FLOW],
796
766
  selectFlower: (name) => (state) => _get(state, [name]),
797
- selectFlowerFormNode: (id) => (state) => _get(state, ['form', id]),
767
+ // selectFlowerFormNode: (id) => (state) =>
768
+ // _get(state, [REDUCER_NAME.FLOWER_DATA, id]),
798
769
  selectFlowerHistory: (flower) => _get(flower, ['history'], []),
799
770
  makeSelectNodesIds: (flower) => _get(flower, ['nodes']),
800
771
  makeSelectStartNodeId: (flower) => _get(flower, ['startId']),
801
- getDataByFlow: (flower) => _get(flower, ['data']) ?? {},
802
- getDataFromState: (id) => (data) => (id === '*' ? data : _get(data, id)),
803
- makeSelectNodeFormSubmitted: (form) => form && form.isSubmitted,
804
- makeSelectNodeFormFieldTouched: (id) => (form) => form && form.touches && form.touches[id],
805
- makeSelectNodeFormFieldFocused: (id) => (form) => {
806
- return form && form.hasFocus === id ? id : undefined;
807
- },
808
- makeSelectNodeFormFieldDirty: (id) => (form) => form && form.dirty && form.dirty[id],
809
772
  makeSelectCurrentNodeId: (flower, startNodeId) => _get(flower, ['current']) || startNodeId,
810
773
  makeSelectCurrentNodeDisabled: (nodes, current) => !!_get(nodes, [current, 'disabled']),
811
774
  makeSelectPrevNodeRetain: (nodes, history, current) => {
@@ -826,7 +789,22 @@ const FlowerCoreStateSelectors = {
826
789
  return nodes[prevFlowerNode] && nodes[prevFlowerNode].retain
827
790
  ? prevFlowerNode
828
791
  : undefined;
792
+ }
793
+ };
794
+
795
+ const FlowerCoreStateDataSelectors = {
796
+ selectGlobalReducerByName: (name) => (state) => state[name] ?? state[REDUCER_NAME.FLOWER_DATA][name],
797
+ selectGlobalForm: (state) => {
798
+ return state && state[REDUCER_NAME.FLOWER_DATA];
829
799
  },
800
+ // getDataByFlow: (flower) => _get(flower, 'data') ?? {},
801
+ getDataFromState: (id) => (data) => (id === '*' ? data : _get(data, id)),
802
+ makeSelectNodeFormSubmitted: (form) => form && form.isSubmitted,
803
+ makeSelectNodeFormFieldTouched: (id) => (form) => form && form.touches && form.touches[id],
804
+ makeSelectNodeFormFieldFocused: (id) => (form) => {
805
+ return form && form.hasFocus === id ? id : undefined;
806
+ },
807
+ makeSelectNodeFormFieldDirty: (id) => (form) => form && form.dirty && form.dirty[id],
830
808
  makeSelectNodeErrors: createFormData,
831
809
  makeSelectFieldError: (name, id, validate) => (data, form) => {
832
810
  const customErrors = Object.entries((form && form.customErrors) || {})
@@ -841,7 +819,7 @@ const FlowerCoreStateSelectors = {
841
819
  if (!rule.rules)
842
820
  return true;
843
821
  const transformSelf = CoreUtils.mapKeysDeepLodash(rule.rules, (v, key) => key === '$self' ? id : key);
844
- const [hasError] = MatchRules.rulesMatcher(transformSelf, data, false, {
822
+ const [hasError] = rulesMatcher(transformSelf, data, false, {
845
823
  prefix: name
846
824
  });
847
825
  return hasError;
@@ -863,33 +841,16 @@ const FlowerCoreStateSelectors = {
863
841
  const k = inc;
864
842
  return Object.assign(acc, { [k]: _get(state, k) });
865
843
  }, {});
866
- const [disabled] = MatchRules.rulesMatcher(rules, { ...unflatten(res) }, false, { prefix: flowName });
844
+ const [disabled] = rulesMatcher(rules, { ...unflatten(res) }, false, {
845
+ prefix: flowName
846
+ });
867
847
  return disabled;
868
848
  }
869
849
  };
870
850
 
871
- var RulesOperators;
872
- (function (RulesOperators) {
873
- RulesOperators["$exists"] = "$exists";
874
- RulesOperators["$eq"] = "$eq";
875
- RulesOperators["$ne"] = "$ne";
876
- RulesOperators["$gt"] = "$gt";
877
- RulesOperators["$gte"] = "$gte";
878
- RulesOperators["$lt"] = "$lt";
879
- RulesOperators["$lte"] = "$lte";
880
- RulesOperators["$strGt"] = "$strGt";
881
- RulesOperators["$strGte"] = "$strGte";
882
- RulesOperators["$strLt"] = "$strLt";
883
- RulesOperators["$strLte"] = "$strLte";
884
- RulesOperators["$in"] = "$in";
885
- RulesOperators["$nin"] = "$nin";
886
- RulesOperators["$all"] = "$all";
887
- RulesOperators["$regex"] = "$regex";
888
- })(RulesOperators || (RulesOperators = {}));
889
- var RulesModes;
890
- (function (RulesModes) {
891
- RulesModes["$and"] = "$and";
892
- RulesModes["$or"] = "$or";
893
- })(RulesModes || (RulesModes = {}));
851
+ const FlowerCoreStateSelectors = {
852
+ ...FlowerCoreStateBaseSelectors,
853
+ ...FlowerCoreStateDataSelectors
854
+ };
894
855
 
895
- export { CoreUtils, Emitter, FlowerCoreReducers, FlowerStateUtils, MatchRules, RulesModes, RulesOperators, FlowerCoreStateSelectors as Selectors, devtoolState };
856
+ export { CoreUtils, Emitter, FlowUtils, FlowerCoreBaseReducers, FlowerCoreDataReducers, FlowerCoreReducers, FlowerCoreStateBaseSelectors, FlowerCoreStateDataSelectors, FlowerCoreStateSelectors, FlowerStateUtils, FormUtils, REDUCER_NAME, createFormData, devtoolState, flattenRules, rulesMatcher, rulesMatcherUtils };