@flowerforce/flower-core 3.3.1-beta.2 → 4.0.1-beta.1

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 +238 -266
  2. package/dist/index.esm.js +228 -265
  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 -109
  8. package/dist/src/{rules-matcher/interface.d.ts → interfaces/RulesMatcherInterface.d.ts} +1 -1
  9. package/dist/src/interfaces/SelectorsInterface.d.ts +34 -25
  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 +2 -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/FlowerDataStateSelectors.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/FlowerDataCoreUtils.d.ts +2 -0
  28. package/dist/src/utils/FlowerFlowUtils.d.ts +3 -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
+ selectFlowerDataNode: (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 data = FlowerStateUtils.selectFlowerDataNode(name)(state);
46
+ return generateData(data);
47
+ }
48
+ };
49
+ const generateData = (data) => {
50
+ const validationErrors = data && data.errors;
51
+ const allErrors = Object.values(validationErrors || {});
52
+ return {
53
+ isSubmitted: data?.isSubmitted || false,
54
+ isDirty: Object.values(data?.dirty || {}).some(Boolean) || false,
55
+ hasFocus: data?.hasFocus,
56
+ errors: data?.errors,
57
+ customErrors: data?.customErrors,
58
+ isValidating: data?.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.
@@ -225,25 +265,21 @@ const operators = {
225
265
  .some((c) => c instanceof RegExp ? c.test(a) : new RegExp(c, opt).test(a))
226
266
  };
227
267
 
228
- const rulesMatcher = (rules, formValue = {}, apply = true, options) => {
268
+ const rulesMatcher = (rules, dataValue = {}, apply = true, options) => {
229
269
  if (!rules)
230
270
  return [apply];
231
271
  // if (typeof rules !== 'object' && !Array.isArray(rules)) {
232
272
  // throw new Error('Rules accept only array or object');
233
273
  // }
234
274
  if (typeof rules === 'function') {
235
- return [rules(formValue) === apply];
275
+ return [rules(dataValue) === apply];
236
276
  }
237
277
  const conditions = Array.isArray(rules)
238
278
  ? { $and: rules }
239
279
  : rules;
240
- const valid = rulesMatcherUtils.checkRule(conditions, formValue, options ?? {});
280
+ const valid = rulesMatcherUtils.checkRule(conditions, dataValue, 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 DataUtils = {
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 [rootName, ...rest] = DataUtils.cleanPath(idValue).split('.');
422
+ return {
423
+ rootName,
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
+ ...DataUtils
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,120 @@ 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
+ const FlowerCoreDataReducers = {
676
+ setFormSubmitted: (state, { payload }) => {
677
+ const rootPath = typeof payload === 'string' ? payload : payload.rootName;
678
+ if (!_get(state, [rootPath])) {
679
+ return state;
680
+ }
681
+ _set(state, [rootPath, 'isSubmitted'], true);
682
+ return state;
683
+ },
684
+ addCustomDataErrors: (state, { payload }) => {
685
+ _set(state, [payload.rootName, 'customErrors', payload.id], payload.errors);
686
+ },
687
+ addDataErrors: (state, { payload }) => {
688
+ _set(state, [payload.rootName, 'errors', payload.id], payload.errors);
689
+ },
690
+ removeDataErrors: (state, { payload }) => {
691
+ _unset(state, [payload.rootName, 'errors', payload.id]);
692
+ _unset(state, [payload.rootName, 'customErrors', payload.id]);
693
+ _unset(state, [payload.rootName, 'isValidating']);
694
+ },
695
+ fieldTouch: (state, { payload }) => {
696
+ _set(state, [payload.rootName, 'touches', payload.id], payload.touched);
697
+ },
698
+ fieldDirty: (state, { payload }) => {
699
+ _set(state, [payload.rootName, 'dirty', payload.id], payload.dirty);
700
+ },
701
+ fieldFocus: (state, { payload }) => {
702
+ if (!payload.focused) {
703
+ _unset(state, [payload.rootName, 'hasFocus']);
704
+ return;
705
+ }
706
+ _set(state, [payload.rootName, 'hasFocus'], payload.id);
707
+ },
708
+ addData: (state, { payload }) => {
709
+ const prevData = _get(state, [payload.rootName, 'data'], {});
710
+ _set(state, [payload.rootName, 'data'], { ...prevData, ...payload.value });
711
+ },
712
+ addDataByPath: (state, { payload }) => {
713
+ const { path: newpath } = getPath(payload.id);
714
+ if (payload.id && payload.id.length) {
715
+ _set(state, [payload.rootName, 'data', ...newpath], payload.value);
716
+ if (payload && payload.dirty) {
717
+ _set(state, [payload.rootName, 'dirty', payload.id], payload.dirty);
718
+ }
719
+ }
720
+ },
721
+ // TODO usato al momento solo il devtool
722
+ replaceData: /* istanbul ignore next */ (state, { payload }) => {
723
+ /* istanbul ignore next */
724
+ _set(state, [payload.rootName, 'data'], payload.value);
725
+ },
726
+ unsetData: (state, { payload }) => {
727
+ _unset(state, [payload.rootName, 'data', ...payload.id]);
728
+ },
729
+ setIsDataValidating: (state, { payload }) => {
730
+ _set(state, [payload.rootName, 'isValidating'], payload.isValidating);
731
+ },
732
+ resetData: (state, { payload: { rootName, initialData } }) => {
733
+ const touchedFields = _get(state, [rootName, 'errors'], {});
734
+ const newStateData = initialData
735
+ ? Object.keys(touchedFields).reduce((acc, key) => {
736
+ const { path } = getPath(key);
737
+ const initialDataByPath = _get(initialData, [...path], undefined);
738
+ _set(acc, [...path], initialDataByPath);
739
+ return acc;
740
+ }, {})
741
+ : {};
742
+ _set(state, [rootName, 'data'], newStateData);
743
+ _unset(state, [rootName, 'touches']);
744
+ _unset(state, [rootName, 'dirty']);
745
+ _unset(state, [rootName, 'isSubmitted']);
746
+ },
747
+ initData: (state, { payload: { rootName, initialData } }) => {
748
+ _set(state, [rootName, 'data'], initialData);
749
+ }
750
+ };
751
+
752
+ const FlowerCoreReducers = { ...FlowerCoreBaseReducers, ...FlowerCoreDataReducers };
753
+
754
+ const FlowerCoreStateBaseSelectors = {
755
+ selectGlobal: (state) => state && state[REDUCER_NAME.FLOWER_FLOW],
782
756
  selectFlower: (name) => (state) => _get(state, [name]),
783
- selectFlowerFormNode: (id) => (state) => _get(state, ['form', id]),
784
757
  selectFlowerHistory: (flower) => _get(flower, ['history'], []),
785
758
  makeSelectNodesIds: (flower) => _get(flower, ['nodes']),
786
759
  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
760
  makeSelectCurrentNodeId: (flower, startNodeId) => _get(flower, ['current']) || startNodeId,
796
761
  makeSelectCurrentNodeDisabled: (nodes, current) => !!_get(nodes, [current, 'disabled']),
797
762
  makeSelectPrevNodeRetain: (nodes, history, current) => {
@@ -812,14 +777,29 @@ const FlowerCoreStateSelectors = {
812
777
  return nodes[prevFlowerNode] && nodes[prevFlowerNode].retain
813
778
  ? prevFlowerNode
814
779
  : undefined;
780
+ }
781
+ };
782
+
783
+ const FlowerCoreStateDataSelectors = {
784
+ selectGlobalReducerByName: (name) => (state) => state[name] ?? state[REDUCER_NAME.FLOWER_DATA][name],
785
+ selectGlobalData: (state) => {
786
+ return state && state[REDUCER_NAME.FLOWER_DATA];
815
787
  },
816
- makeSelectNodeErrors: createFormData,
817
- makeSelectFieldError: (name, id, validate) => (data, form) => {
818
- const customErrors = Object.entries((form && form.customErrors) || {})
788
+ // getDataByFlow: (flower) => _get(flower, 'data') ?? {},
789
+ getDataFromState: (id) => (data) => (id === '*' ? data : _get(data, id)),
790
+ makeSelectNodeDataSubmitted: (data) => data && data.isSubmitted,
791
+ makeSelectNodeDataFieldTouched: (id) => (data) => data && data.touches && data.touches[id],
792
+ makeSelectNodeDataFieldFocused: (id) => (data) => {
793
+ return data && data.hasFocus === id ? id : undefined;
794
+ },
795
+ makeSelectNodeDataFieldDirty: (id) => (data) => data && data.dirty && data.dirty[id],
796
+ makeSelectNodeErrors: generateData,
797
+ makeSelectFieldError: (name, id, validate) => (globalData, data) => {
798
+ const customErrors = Object.entries((data && data.customErrors) || {})
819
799
  .filter(([k]) => k === id)
820
800
  .map(([, v]) => v)
821
801
  .flat();
822
- if (!validate || !data)
802
+ if (!validate || !globalData)
823
803
  return [];
824
804
  const errors = validate.filter((rule) => {
825
805
  if (!rule)
@@ -827,7 +807,7 @@ const FlowerCoreStateSelectors = {
827
807
  if (!rule.rules)
828
808
  return true;
829
809
  const transformSelf = CoreUtils.mapKeysDeepLodash(rule.rules, (v, key) => key === '$self' ? id : key);
830
- const [hasError] = MatchRules.rulesMatcher(transformSelf, data, false, {
810
+ const [hasError] = rulesMatcher(transformSelf, globalData, false, {
831
811
  prefix: name
832
812
  });
833
813
  return hasError;
@@ -835,8 +815,8 @@ const FlowerCoreStateSelectors = {
835
815
  const result = errors.map((r) => (r && r.message) || 'error');
836
816
  return [...customErrors, ...(result.length === 0 ? [] : result)];
837
817
  },
838
- selectorRulesDisabled: (id, rules, keys, flowName, value) => (data, form) => {
839
- const newState = { ...data, ...value, $form: form };
818
+ selectorRulesDisabled: (id, rules, keys, flowName, value) => (globalData, data) => {
819
+ const newState = { ...globalData, ...value, $data: data, $form: data };
840
820
  const state = Object.assign(newState, id ? { $self: _get(newState, [flowName, ...id.split('.')]) } : {});
841
821
  if (!rules)
842
822
  return false;
@@ -849,33 +829,16 @@ const FlowerCoreStateSelectors = {
849
829
  const k = inc;
850
830
  return Object.assign(acc, { [k]: _get(state, k) });
851
831
  }, {});
852
- const [disabled] = MatchRules.rulesMatcher(rules, { ...unflatten(res) }, false, { prefix: flowName });
832
+ const [disabled] = rulesMatcher(rules, { ...unflatten(res) }, false, {
833
+ prefix: flowName
834
+ });
853
835
  return disabled;
854
836
  }
855
837
  };
856
838
 
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 = {}));
839
+ const FlowerCoreStateSelectors = {
840
+ ...FlowerCoreStateBaseSelectors,
841
+ ...FlowerCoreStateDataSelectors
842
+ };
880
843
 
881
- export { CoreUtils, Emitter, FlowerCoreReducers, FlowerStateUtils, MatchRules, RulesModes, RulesOperators, FlowerCoreStateSelectors as Selectors, devtoolState };
844
+ export { CoreUtils, DataUtils, Emitter, FlowUtils, FlowerCoreBaseReducers, FlowerCoreDataReducers, FlowerCoreReducers, FlowerCoreStateBaseSelectors, FlowerCoreStateDataSelectors, FlowerCoreStateSelectors, FlowerStateUtils, REDUCER_NAME, devtoolState, flattenRules, generateData, rulesMatcher, rulesMatcherUtils };