@flowerforce/flower-core 3.3.1-beta.2 → 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 -257
  2. package/dist/index.esm.js +231 -256
  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 +109 -105
  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} +1 -1
  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: Object.values(form?.dirty || {}).some(Boolean) || 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,91 +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
- formFieldDirty: (state, { payload }) => {
637
- _set(state, [payload.name, 'form', payload.currentNode, 'dirty', payload.id], payload.dirty);
638
- },
639
- formFieldFocus: (state, { payload }) => {
640
- if (!payload.focused) {
641
- _unset(state, [payload.name, 'form', payload.currentNode, 'hasFocus']);
642
- return;
643
- }
644
- _set(state, [payload.name, 'form', payload.currentNode, 'hasFocus'], payload.id);
645
- },
646
- addData: (state, { payload }) => {
647
- const prevData = _get(state, [payload.flowName, 'data']);
648
- _set(state, [payload.flowName, 'data'], { ...prevData, ...payload.value });
649
- },
650
- addDataByPath: (state, { payload }) => {
651
- const { path: newpath } = getPath(payload.id);
652
- const currentNode = FlowerStateUtils.makeSelectCurrentNodeId(payload.flowName)(state);
653
- if (payload.id && payload.id.length) {
654
- _set(state, [payload.flowName, 'data', ...newpath], payload.value);
655
- if (payload && payload.dirty) {
656
- _set(state, [payload.flowName, 'form', currentNode, 'dirty', payload.id], payload.dirty);
657
- }
658
- }
659
- },
660
- // TODO usato al momento solo il devtool
661
- replaceData: /* istanbul ignore next */ (state, { payload }) => {
662
- /* istanbul ignore next */
663
- _set(state, [payload.flowName, 'data'], payload.value);
664
- },
665
- unsetData: (state, { payload }) => {
666
- _unset(state, [payload.flowName, 'data', ...payload.id]);
667
- },
668
- setFormIsValidating: (state, { payload }) => {
669
- _set(state, [payload.name, 'form', payload.currentNode, 'isValidating'], payload.isValidating);
670
- },
671
- resetForm: (state, { payload }) => {
672
- const touchedFields = _get(state, [payload.flowName, 'form', payload.id, 'errors'], {});
673
- Object.keys(touchedFields).forEach((key) => {
674
- const { flowNameFromPath = payload.flowName, path } = getPath(key);
675
- _unset(state, [flowNameFromPath, 'data', ...path]);
676
- });
677
- _unset(state, [payload.flowName, 'form', payload.id, 'touches']);
678
- _unset(state, [payload.flowName, 'form', payload.id, 'dirty']);
679
- _unset(state, [payload.flowName, 'form', payload.id, 'isSubmitted']);
680
- },
681
582
  node: (state, { payload }) => {
682
583
  const { name, history } = payload;
683
584
  const node = payload.nodeId || payload.node || '';
684
585
  const flowName = name || payload.flowName || '';
685
- const startNode = _get(state, [payload.name, 'startId']);
686
- const currentNodeId = _get(state, [payload.name, 'current'], startNode);
687
- FlowerCoreReducers.setFormTouched(state, {
688
- type: 'setFormTouched',
689
- payload: { flowName, currentNode: currentNodeId }
690
- });
691
586
  /* istanbul ignore next */
692
587
  // eslint-disable-next-line no-underscore-dangle
693
588
  if (devtoolState && _get(devtoolState, '__FLOWER_DEVTOOLS__') && history) {
694
- FlowerCoreReducers.forceAddHistory(state, {
589
+ FlowerCoreBaseReducers.forceAddHistory(state, {
695
590
  type: 'forceAddHistory',
696
591
  payload: {
697
592
  name,
@@ -700,34 +595,35 @@ const FlowerCoreReducers = {
700
595
  }
701
596
  });
702
597
  }
703
- FlowerCoreReducers.historyAdd(state, {
598
+ FlowerCoreBaseReducers.historyAdd(state, {
704
599
  type: 'historyAdd',
705
600
  payload: { name: name || flowName || '', node }
706
601
  });
707
602
  },
708
603
  prevToNode: (state, { payload }) => {
709
604
  const { node, name, flowName } = payload;
710
- FlowerCoreReducers.historyPrevToNode(state, {
605
+ FlowerCoreBaseReducers.historyPrevToNode(state, {
711
606
  type: 'historyPrevToNode',
712
607
  payload: { name: name || flowName || '', node }
713
608
  });
714
609
  },
715
610
  next: (state, { payload }) => {
716
- const { name, data = {}, route } = payload;
717
- 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;
718
614
  const currentNodeId = FlowerStateUtils.makeSelectCurrentNodeId(flowName)(state);
719
615
  const currentNextRules = FlowerStateUtils.makeSelectCurrentNextRules(flowName)(state);
720
- const form = FlowerStateUtils.makeSelectNodeErrors(flowName, currentNodeId)(state);
721
- 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));
722
619
  const stateWithNodeData = {
723
- $in: data,
724
- $form: form,
725
- ...clonedData
620
+ $in: dataIn,
621
+ /** @deprecated use $data instead */
622
+ $form: $data,
623
+ $data,
624
+ ...externalClonedData,
625
+ ...internalClonedData
726
626
  };
727
- FlowerCoreReducers.setFormTouched(state, {
728
- type: 'setFormTouched',
729
- payload: { flowName, currentNode: currentNodeId }
730
- });
731
627
  if (!currentNextRules) {
732
628
  return;
733
629
  }
@@ -736,7 +632,7 @@ const FlowerCoreReducers = {
736
632
  if (!rulesByName[route]) {
737
633
  return;
738
634
  }
739
- FlowerCoreReducers.historyAdd(state, {
635
+ FlowerCoreBaseReducers.historyAdd(state, {
740
636
  type: 'historyAdd',
741
637
  payload: { name: flowName, node: rulesByName[route] }
742
638
  });
@@ -747,51 +643,132 @@ const FlowerCoreReducers = {
747
643
  if (!nextNumberNode) {
748
644
  return;
749
645
  }
750
- FlowerCoreReducers.historyAdd(state, {
646
+ FlowerCoreBaseReducers.historyAdd(state, {
751
647
  type: 'historyAdd',
752
648
  payload: { name: flowName, node: nextNumberNode }
753
649
  });
754
650
  },
755
651
  prev: (state, { payload }) => {
756
652
  const { name, flowName } = payload;
757
- FlowerCoreReducers.historyPop(state, {
653
+ FlowerCoreBaseReducers.historyPop(state, {
758
654
  type: 'historyPop',
759
655
  payload: { name: name || flowName || '' }
760
656
  });
761
657
  },
762
658
  restart: (state, { payload }) => {
763
659
  const { name, flowName } = payload;
764
- FlowerCoreReducers.restoreHistory(state, {
660
+ FlowerCoreBaseReducers.restoreHistory(state, {
765
661
  type: 'restoreHistory',
766
662
  payload: { name: name || flowName || '' }
767
663
  });
768
664
  },
769
665
  reset: (state, { payload }) => {
770
- const { name, flowName, initialData } = payload;
771
- FlowerCoreReducers.restoreHistory(state, {
666
+ const { name, flowName } = payload;
667
+ FlowerCoreBaseReducers.restoreHistory(state, {
772
668
  type: 'restoreHistory',
773
669
  payload: { name: name || flowName || '' }
774
670
  });
775
- _set(state, [name || flowName || '', 'form'], {});
776
- _set(state, [name || flowName || '', 'data'], initialData);
777
671
  }
778
672
  };
779
673
 
780
- const FlowerCoreStateSelectors = {
781
- 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],
782
766
  selectFlower: (name) => (state) => _get(state, [name]),
783
- selectFlowerFormNode: (id) => (state) => _get(state, ['form', id]),
767
+ // selectFlowerFormNode: (id) => (state) =>
768
+ // _get(state, [REDUCER_NAME.FLOWER_DATA, id]),
784
769
  selectFlowerHistory: (flower) => _get(flower, ['history'], []),
785
770
  makeSelectNodesIds: (flower) => _get(flower, ['nodes']),
786
771
  makeSelectStartNodeId: (flower) => _get(flower, ['startId']),
787
- getDataByFlow: (flower) => _get(flower, ['data']) ?? {},
788
- getDataFromState: (id) => (data) => (id === '*' ? data : _get(data, id)),
789
- makeSelectNodeFormSubmitted: (form) => form && form.isSubmitted,
790
- makeSelectNodeFormFieldTouched: (id) => (form) => form && form.touches && form.touches[id],
791
- makeSelectNodeFormFieldFocused: (id) => (form) => {
792
- return form && form.hasFocus === id ? id : undefined;
793
- },
794
- makeSelectNodeFormFieldDirty: (id) => (form) => form && form.dirty && form.dirty[id],
795
772
  makeSelectCurrentNodeId: (flower, startNodeId) => _get(flower, ['current']) || startNodeId,
796
773
  makeSelectCurrentNodeDisabled: (nodes, current) => !!_get(nodes, [current, 'disabled']),
797
774
  makeSelectPrevNodeRetain: (nodes, history, current) => {
@@ -812,7 +789,22 @@ const FlowerCoreStateSelectors = {
812
789
  return nodes[prevFlowerNode] && nodes[prevFlowerNode].retain
813
790
  ? prevFlowerNode
814
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];
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;
815
806
  },
807
+ makeSelectNodeFormFieldDirty: (id) => (form) => form && form.dirty && form.dirty[id],
816
808
  makeSelectNodeErrors: createFormData,
817
809
  makeSelectFieldError: (name, id, validate) => (data, form) => {
818
810
  const customErrors = Object.entries((form && form.customErrors) || {})
@@ -827,7 +819,7 @@ const FlowerCoreStateSelectors = {
827
819
  if (!rule.rules)
828
820
  return true;
829
821
  const transformSelf = CoreUtils.mapKeysDeepLodash(rule.rules, (v, key) => key === '$self' ? id : key);
830
- const [hasError] = MatchRules.rulesMatcher(transformSelf, data, false, {
822
+ const [hasError] = rulesMatcher(transformSelf, data, false, {
831
823
  prefix: name
832
824
  });
833
825
  return hasError;
@@ -849,33 +841,16 @@ const FlowerCoreStateSelectors = {
849
841
  const k = inc;
850
842
  return Object.assign(acc, { [k]: _get(state, k) });
851
843
  }, {});
852
- const [disabled] = MatchRules.rulesMatcher(rules, { ...unflatten(res) }, false, { prefix: flowName });
844
+ const [disabled] = rulesMatcher(rules, { ...unflatten(res) }, false, {
845
+ prefix: flowName
846
+ });
853
847
  return disabled;
854
848
  }
855
849
  };
856
850
 
857
- var RulesOperators;
858
- (function (RulesOperators) {
859
- RulesOperators["$exists"] = "$exists";
860
- RulesOperators["$eq"] = "$eq";
861
- RulesOperators["$ne"] = "$ne";
862
- RulesOperators["$gt"] = "$gt";
863
- RulesOperators["$gte"] = "$gte";
864
- RulesOperators["$lt"] = "$lt";
865
- RulesOperators["$lte"] = "$lte";
866
- RulesOperators["$strGt"] = "$strGt";
867
- RulesOperators["$strGte"] = "$strGte";
868
- RulesOperators["$strLt"] = "$strLt";
869
- RulesOperators["$strLte"] = "$strLte";
870
- RulesOperators["$in"] = "$in";
871
- RulesOperators["$nin"] = "$nin";
872
- RulesOperators["$all"] = "$all";
873
- RulesOperators["$regex"] = "$regex";
874
- })(RulesOperators || (RulesOperators = {}));
875
- var RulesModes;
876
- (function (RulesModes) {
877
- RulesModes["$and"] = "$and";
878
- RulesModes["$or"] = "$or";
879
- })(RulesModes || (RulesModes = {}));
851
+ const FlowerCoreStateSelectors = {
852
+ ...FlowerCoreStateBaseSelectors,
853
+ ...FlowerCoreStateDataSelectors
854
+ };
880
855
 
881
- 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 };