@flowerforce/flower-react 3.1.1 → 3.1.2-beta.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/dist/index.cjs.js CHANGED
@@ -14,6 +14,7 @@ const context = _context;
14
14
  const Provider = _context.Provider;
15
15
  const Consumer = _context.Consumer;
16
16
 
17
+ // eslint-disable-next-line import/prefer-default-export
17
18
  const convertElements = nodes => {
18
19
  const res = flowerCore.CoreUtils.generateNodesForFlowerJson(nodes);
19
20
  return res;
@@ -45,7 +46,9 @@ const makeSelectStartNodeId = name => reselect.createSelector(selectFlower(name)
45
46
  const makeSelectCurrentNodeId = name => reselect.createSelector(selectFlower(name), makeSelectStartNodeId(name), flowerCore.Selectors.makeSelectCurrentNodeId);
46
47
  const makeSelectPrevNodeRetain = name => reselect.createSelector(makeSelectNodesIds(name), selectFlowerHistory(name), makeSelectCurrentNodeId(name), flowerCore.Selectors.makeSelectPrevNodeRetain);
47
48
  const makeSelectCurrentNodeDisabled = name => reselect.createSelector(makeSelectNodesIds(name), makeSelectCurrentNodeId(name), flowerCore.Selectors.makeSelectCurrentNodeDisabled);
49
+ // dati nel flow selezionato
48
50
  const getDataByFlow = name => reselect.createSelector(selectFlower(name), flowerCore.Selectors.getDataByFlow);
51
+ // selettore per recuperare i dati di un flow specifico e id specifico
49
52
  const getDataFromState = (name, id) => reselect.createSelector(getDataByFlow(name), flowerCore.Selectors.getDataFromState(id));
50
53
  const makeSelectNodeErrors = (name, currentNodeId) => reselect.createSelector(selectFlowerFormNode(name, currentNodeId), flowerCore.Selectors.makeSelectNodeErrors);
51
54
  const makeSelectNodeFormTouched = (name, currentNodeId) => reselect.createSelector(selectFlowerFormNode(name, currentNodeId), flowerCore.Selectors.makeSelectNodeFormTouched);
@@ -53,6 +56,7 @@ const getAllData = reselect.createSelector(selectGlobal, mapData);
53
56
  const makeSelectFieldError = (name, id, validate) => reselect.createSelector(getAllData, flowerCore.Selectors.makeSelectFieldError(name, id, validate));
54
57
  const selectorRulesDisabled = (id, rules, keys, flowName, value, currentNode) => reselect.createSelector(getAllData, makeSelectNodeErrors(flowName, currentNode), flowerCore.Selectors.selectorRulesDisabled(id, rules, keys, flowName, value));
55
58
 
59
+ //TODO check reduxContext type due to remove all any types
56
60
  const reduxContext = /*#__PURE__*/React.createContext(null);
57
61
  const useDispatch = reactRedux.createDispatchHook(reduxContext);
58
62
  const useSelector = reactRedux.createSelectorHook(reduxContext);
@@ -83,6 +87,11 @@ class FlowerProvider extends React.PureComponent {
83
87
  }
84
88
  }
85
89
 
90
+ /* eslint-disable no-undef */
91
+ /* eslint-disable no-underscore-dangle */
92
+ /**
93
+ * FlowerClient
94
+ */
86
95
  const FlowerClient = ({
87
96
  children,
88
97
  name,
@@ -93,7 +102,9 @@ const FlowerClient = ({
93
102
  const flowName = name;
94
103
  const dispatch = useDispatch();
95
104
  const one = React.useRef(false);
96
- const [wsDevtools, setWsDevtools] = React.useState(global.window && _get(global.window, '__FLOWER_DEVTOOLS_INITIALIZED__', false));
105
+ const [wsDevtools, setWsDevtools] = React.useState(flowerCore.devtoolState && _get(flowerCore.devtoolState, '__FLOWER_DEVTOOLS_INITIALIZED__', false));
106
+ // TODO rivedere il giro, potremmo fare le trasformazioni in CoreUtils.generateNodesForFlowerJson
107
+ // eslint-disable-next-line react-hooks/exhaustive-deps, max-len
97
108
  const nodes = React.useMemo(() => convertElements(React.Children.toArray(children)), [children]);
98
109
  const nodeById = React.useMemo(() => _keyBy(React.Children.toArray(children), 'props.id'), [children]);
99
110
  const isInitialized = useSelector(makeSelectStartNodeId(name));
@@ -107,6 +118,7 @@ const FlowerClient = ({
107
118
  one.current = true;
108
119
  dispatch(actions.initNodes({
109
120
  name: flowName,
121
+ // @ts-expect-error FIX ME
110
122
  nodes,
111
123
  startId: _startId != null ? _startId : '',
112
124
  persist: _destroyOnUnmount === false,
@@ -115,6 +127,7 @@ const FlowerClient = ({
115
127
  }
116
128
  }, [dispatch, flowName, nodes, _startId, _initialData, _destroyOnUnmount]);
117
129
  React.useEffect(() => {
130
+ /* istanbul ignore next */
118
131
  const eventCb = msg => {
119
132
  if (msg.source !== 'flower-devtool') return;
120
133
  if (msg.action === 'FLOWER_EXTENSION_INIT' || msg.action === 'FLOWER_DEVTOOL_WEB_INIT') {
@@ -139,16 +152,19 @@ const FlowerClient = ({
139
152
  }));
140
153
  }
141
154
  };
142
- if (global.window && _get(global.window, '__FLOWER_DEVTOOLS__')) {
155
+ /* istanbul ignore next */
156
+ if (flowerCore.devtoolState && _get(flowerCore.devtoolState, '__FLOWER_DEVTOOLS__')) {
143
157
  flowerCore.Emitter.on('flower-devtool-to-client', eventCb);
144
158
  }
145
159
  return () => {
146
- if (global.window && _get(global.window, '__FLOWER_DEVTOOLS__')) {
160
+ /* istanbul ignore next */
161
+ if (flowerCore.devtoolState && _get(flowerCore.devtoolState, '__FLOWER_DEVTOOLS__')) {
147
162
  flowerCore.Emitter.off('flower-devtool-to-client', eventCb);
148
163
  }
149
164
  };
150
165
  }, [dispatch, flowName]);
151
166
  React.useEffect(() => () => {
167
+ // unmount function
152
168
  if (_destroyOnUnmount && one.current === true) {
153
169
  one.current = false;
154
170
  dispatch(actions.destroy({
@@ -157,7 +173,8 @@ const FlowerClient = ({
157
173
  }
158
174
  }, [dispatch, flowName, _destroyOnUnmount]);
159
175
  React.useEffect(() => {
160
- if (isInitialized && wsDevtools && global.window && _get(global.window, '__FLOWER_DEVTOOLS__')) {
176
+ /* istanbul ignore next */
177
+ if (isInitialized && wsDevtools && flowerCore.devtoolState && _get(flowerCore.devtoolState, '__FLOWER_DEVTOOLS__')) {
161
178
  flowerCore.Emitter.emit('flower-devtool-from-client', {
162
179
  source: 'flower-client',
163
180
  action: 'FLOWER_CLIENT_INIT',
@@ -169,7 +186,8 @@ const FlowerClient = ({
169
186
  }
170
187
  }, [dispatch, flowName, wsDevtools, isInitialized, store]);
171
188
  React.useEffect(() => {
172
- if (isInitialized && wsDevtools && global.window && _get(global.window, '__FLOWER_DEVTOOLS__')) {
189
+ /* istanbul ignore next */
190
+ if (isInitialized && wsDevtools && flowerCore.devtoolState && _get(flowerCore.devtoolState, '__FLOWER_DEVTOOLS__')) {
173
191
  flowerCore.Emitter.emit('flower-devtool-from-client', {
174
192
  source: 'flower-client',
175
193
  action: 'SET_HISTORY',
@@ -180,8 +198,10 @@ const FlowerClient = ({
180
198
  }, [dispatch, flowName, history, wsDevtools, isInitialized]);
181
199
  React.useEffect(() => {
182
200
  if (!current) return;
201
+ /* istanbul ignore next */
183
202
  if (!isInitialized) return;
184
- if (isInitialized && wsDevtools && global.window && _get(global.window, '__FLOWER_DEVTOOLS__')) {
203
+ /* istanbul ignore next */
204
+ if (isInitialized && wsDevtools && flowerCore.devtoolState && _get(flowerCore.devtoolState, '__FLOWER_DEVTOOLS__')) {
185
205
  flowerCore.Emitter.emit('flower-devtool-from-client', {
186
206
  source: 'flower-client',
187
207
  action: 'SET_CURRENT',
@@ -192,6 +212,7 @@ const FlowerClient = ({
192
212
  }, [flowName, current, wsDevtools, isInitialized]);
193
213
  React.useEffect(() => {
194
214
  if (!current) return;
215
+ /* istanbul ignore next */
195
216
  if (!isInitialized) return;
196
217
  if (isDisabled) {
197
218
  dispatch({
@@ -201,7 +222,9 @@ const FlowerClient = ({
201
222
  disabled: true
202
223
  }
203
224
  });
204
- if (wsDevtools && global.window && _get(global.window, '__FLOWER_DEVTOOLS__')) {
225
+ // eslint-disable-next-line no-underscore-dangle, no-undef
226
+ /* istanbul ignore next */
227
+ if (wsDevtools && flowerCore.devtoolState && _get(flowerCore.devtoolState, '__FLOWER_DEVTOOLS__')) {
205
228
  flowerCore.Emitter.emit('flower-devtool-from-client', {
206
229
  source: 'flower-client',
207
230
  action: 'FLOWER_NAVIGATE',
@@ -219,8 +242,10 @@ const FlowerClient = ({
219
242
  }
220
243
  return;
221
244
  }
222
- if (wsDevtools && global.window && _get(global.window, '__FLOWER_DEVTOOLS__')) {
223
- if (isInitialized === current) return;
245
+ // eslint-disable-next-line no-underscore-dangle, no-undef
246
+ /* istanbul ignore next */
247
+ if (wsDevtools && flowerCore.devtoolState && _get(flowerCore.devtoolState, '__FLOWER_DEVTOOLS__')) {
248
+ if (isInitialized === current) return; // salto il primo evento
224
249
  flowerCore.Emitter.emit('flower-devtool-from-client', {
225
250
  source: 'flower-client',
226
251
  action: 'SET_SELECTED',
@@ -316,6 +341,15 @@ function FlowerStart() {
316
341
  isStart: true
317
342
  }
318
343
  });
344
+ // if (global.window
345
+ // // eslint-disable-next-line no-underscore-dangle, no-undef
346
+ // && global.window.__FLOWER_DEVTOOLS__ && global.window.__FLOWER_DEVTOOLS__AUTO) {
347
+ // Emitter.emit('flower-devtool-from-client', {
348
+ // source: 'flower-client',
349
+ // action: 'START_FLOWER',
350
+ // name: flowName,
351
+ // });
352
+ // }
319
353
  }
320
354
  }, [dispatch, autostart, startNodeId, currentNode, flowName]);
321
355
  return null;
@@ -417,6 +451,7 @@ const FlowerRule = ({
417
451
  type
418
452
  } = child;
419
453
  const Component = type;
454
+ // eslint-disable-next-line react/jsx-props-no-spreading
420
455
  return Component && /*#__PURE__*/React.createElement(Component, _extends({
421
456
  key: i,
422
457
  hidden: true
@@ -432,6 +467,7 @@ const FlowerRule = ({
432
467
  type
433
468
  } = child;
434
469
  const Component = type;
470
+ // eslint-disable-next-line react/jsx-props-no-spreading
435
471
  return Component && /*#__PURE__*/React.createElement(Component, _extends({
436
472
  key: i
437
473
  }, props));
@@ -446,6 +482,7 @@ const _excluded$3 = ["Component", "id", "flowName", "currentNode", "validate", "
446
482
  function isIntrinsicElement$1(x) {
447
483
  return typeof x === 'string';
448
484
  }
485
+ //TODO make types for wrapper function props
449
486
  function Wrapper$1(_ref) {
450
487
  let {
451
488
  Component,
@@ -544,6 +581,7 @@ function Wrapper$1(_ref) {
544
581
  });
545
582
  }, [flowName, currentNode, isValidating]);
546
583
  React.useLayoutEffect(() => {
584
+ // destroy
547
585
  return () => {
548
586
  if (destroyValue) {
549
587
  dispatch({
@@ -585,6 +623,8 @@ function Wrapper$1(_ref) {
585
623
  if (typeof Component === 'function') {
586
624
  return Component(newProps);
587
625
  }
626
+ // TODO si arriva in questa condizione quando si passa un componente primitivo es. div
627
+ // in questo caso non posso props custom di flower
588
628
  if (isIntrinsicElement$1(Component)) {
589
629
  return /*#__PURE__*/React.createElement(Component, _extends({
590
630
  id: id
@@ -677,6 +717,7 @@ component$4.displayName = 'FlowerField';
677
717
 
678
718
  const _excluded$2 = ["Component", "id", "flowName", "spreadValue", "hidden", "onUpdate"],
679
719
  _excluded2 = ["id", "alwaysDisplay", "rules", "value", "Component", "spreadValue", "flowName", "onUpdate"];
720
+ //TODO make types for wrapper function
680
721
  function Wrapper(_ref) {
681
722
  let {
682
723
  Component,
@@ -769,6 +810,7 @@ const FlowerValue = ({
769
810
  props
770
811
  } = child;
771
812
  const Component = type;
813
+ // eslint-disable-next-line react/jsx-props-no-spreading
772
814
  return /*#__PURE__*/React.createElement(RenderRules$1, _extends({
773
815
  key: i,
774
816
  id: _id,
@@ -818,6 +860,24 @@ const makeActionPayloadOnReset = makeActionPayload(ACTION_TYPES.reset, PAYLAOAD_
818
860
  const makeActionPayloadOnNode = makeActionPayload(ACTION_TYPES.jump, PAYLAOAD_KEYS_NEEDED.jump);
819
861
  const makeActionPayloadOnNext = makeActionPayload(ACTION_TYPES.next, PAYLAOAD_KEYS_NEEDED.next);
820
862
  const makeActionPayloadOnRestart = makeActionPayload(ACTION_TYPES.restart, PAYLAOAD_KEYS_NEEDED.restart);
863
+ /** This hook allows you to read flow informations, such as the flowName and ID of the current node.
864
+ *
865
+ * It also exposes all the functions to navigate within the flow:
866
+ *
867
+ * - next
868
+ *
869
+ * - back
870
+ *
871
+ * - jump
872
+ *
873
+ * - reset
874
+ *
875
+ * - restart
876
+ *
877
+ * @param {string} flowName - first optional parameter
878
+ *
879
+ * @param {string} name - optional parameter, if flowName exist, name is not used
880
+ */
821
881
  const useFlower = ({
822
882
  flowName: customFlowName,
823
883
  name
@@ -829,8 +889,13 @@ const useFlower = ({
829
889
  } = React.useContext(context);
830
890
  const flowName = customFlowName || name || flowNameDefault;
831
891
  const nodeId = useSelector(makeSelectCurrentNodeId(flowName != null ? flowName : ''));
832
- const emitNavigateEvent = React.useCallback(params => {
833
- if (_get(global.window, '__FLOWER_DEVTOOLS__')) {
892
+ const startId = useSelector(makeSelectStartNodeId(flowName != null ? flowName : ''));
893
+ const emitNavigateEvent = React.useCallback(
894
+ //TODO check this function is needed
895
+ params => {
896
+ /* istanbul ignore next */
897
+ // eslint-disable-next-line no-underscore-dangle, no-undef
898
+ if (_get(flowerCore.devtoolState, '__FLOWER_DEVTOOLS__')) {
834
899
  flowerCore.Emitter.emit('flower-devtool-from-client', {
835
900
  source: 'flower-client',
836
901
  action: 'FLOWER_NAVIGATE',
@@ -924,6 +989,7 @@ const useFlower = ({
924
989
  return {
925
990
  flowName,
926
991
  nodeId,
992
+ startId,
927
993
  next,
928
994
  jump,
929
995
  back,
@@ -932,6 +998,28 @@ const useFlower = ({
932
998
  };
933
999
  };
934
1000
 
1001
+ /* eslint-disable */
1002
+ // {
1003
+ // flowName?: string | undefined;
1004
+ // action?: 'next' | 'back' | 'reset' | 'jump';
1005
+ // } & (
1006
+ // | {
1007
+ // node?: undefined;
1008
+ // route?: Route;
1009
+ // }
1010
+ // | {
1011
+ // node?: RoutePrev;
1012
+ // route?: undefined;
1013
+ // }
1014
+ // | {
1015
+ // node?: RouteReset;
1016
+ // route?: undefined;
1017
+ // }
1018
+ // | {
1019
+ // node?: RouteNode;
1020
+ // route?: undefined;
1021
+ // }
1022
+ // );
935
1023
  const useFlowerNavigate = ({
936
1024
  flowName,
937
1025
  action,
@@ -983,6 +1071,7 @@ const _excluded$1 = ["hidden", "Component", "onNavigate"];
983
1071
  function isIntrinsicElement(x) {
984
1072
  return typeof x === 'string';
985
1073
  }
1074
+ //TODO type FlowerNavigateWrapper props
986
1075
  function FlowerNavigateWrapper(_ref) {
987
1076
  let {
988
1077
  hidden,
@@ -997,16 +1086,22 @@ function FlowerNavigateWrapper(_ref) {
997
1086
  if (typeof Component === 'function') {
998
1087
  return Component(newProps);
999
1088
  }
1089
+ // TODO si arriva in questa condizione quando si passa un componente primitivo es. div
1090
+ // in questo caso non posso props custom di flower
1000
1091
  if (isIntrinsicElement(Component)) {
1001
1092
  return /*#__PURE__*/React.createElement(Component, _extends({}, props, {
1002
1093
  onClick: onNavigate
1003
1094
  }));
1004
1095
  }
1096
+ // TODO in questa condizione si arriva se nel progetto si utilizza Vite, in questo caso i componenti non sono Function ma Object,
1097
+ // oppure nel caso di un testo semplice come children di questo componente
1098
+ /* istanbul ignore next */
1005
1099
  return Component && /*#__PURE__*/React.createElement(Component, _extends({}, newProps));
1006
1100
  }
1007
1101
  const component$2 = /*#__PURE__*/React.memo(FlowerNavigateWrapper);
1008
1102
 
1009
1103
  const _excluded = ["alwaysDisplay", "rules", "Component", "flowName", "onNavigate"];
1104
+ //TODO type RenderRules props
1010
1105
  const RenderRules = _ref => {
1011
1106
  let {
1012
1107
  alwaysDisplay,
@@ -1062,6 +1157,7 @@ const FlowerNavigate = ({
1062
1157
  props
1063
1158
  } = child;
1064
1159
  const Component = type;
1160
+ // eslint-disable-next-line react/jsx-props-no-spreading
1065
1161
  return /*#__PURE__*/React.createElement(RenderRules, _extends({
1066
1162
  key: i,
1067
1163
  alwaysDisplay: alwaysDisplay,
@@ -1080,6 +1176,23 @@ const FlowerComponent = ({
1080
1176
  }) => children;
1081
1177
  const component = /*#__PURE__*/React.memo(FlowerComponent);
1082
1178
 
1179
+ /** This hook allows you to manage and retrieve information about Forms.
1180
+ *
1181
+ * It exposes details regarding the form's state and a set of methods for reading and writing within it:
1182
+ *
1183
+ * - getData
1184
+ *
1185
+ * - setData
1186
+ *
1187
+ * - unSetData
1188
+ *
1189
+ * - replaceData
1190
+ *
1191
+ * @param {string} flowName - first optional parameter
1192
+ *
1193
+ * @param {string} name - optional parameter, if flowName exist, name is not used
1194
+ *
1195
+ */
1083
1196
  const useFlowerForm = ({
1084
1197
  flowName: customFlowName,
1085
1198
  name
package/dist/index.esm.js CHANGED
@@ -1,6 +1,6 @@
1
1
  import React, { createContext, PureComponent, memo, useRef, useState, useMemo, Children, useEffect, useContext, useCallback, useLayoutEffect } from 'react';
2
2
  import _keyBy from 'lodash/keyBy';
3
- import { CoreUtils, FlowerCoreReducers, FlowerStateUtils, Selectors, Emitter, MatchRules } from '@flowerforce/flower-core';
3
+ import { CoreUtils, FlowerCoreReducers, FlowerStateUtils, Selectors, devtoolState, Emitter, MatchRules } from '@flowerforce/flower-core';
4
4
  import _get from 'lodash/get';
5
5
  import { createSlice, configureStore } from '@reduxjs/toolkit';
6
6
  import { createSelector } from 'reselect';
@@ -12,6 +12,7 @@ const context = _context;
12
12
  const Provider = _context.Provider;
13
13
  const Consumer = _context.Consumer;
14
14
 
15
+ // eslint-disable-next-line import/prefer-default-export
15
16
  const convertElements = nodes => {
16
17
  const res = CoreUtils.generateNodesForFlowerJson(nodes);
17
18
  return res;
@@ -43,7 +44,9 @@ const makeSelectStartNodeId = name => createSelector(selectFlower(name), Selecto
43
44
  const makeSelectCurrentNodeId = name => createSelector(selectFlower(name), makeSelectStartNodeId(name), Selectors.makeSelectCurrentNodeId);
44
45
  const makeSelectPrevNodeRetain = name => createSelector(makeSelectNodesIds(name), selectFlowerHistory(name), makeSelectCurrentNodeId(name), Selectors.makeSelectPrevNodeRetain);
45
46
  const makeSelectCurrentNodeDisabled = name => createSelector(makeSelectNodesIds(name), makeSelectCurrentNodeId(name), Selectors.makeSelectCurrentNodeDisabled);
47
+ // dati nel flow selezionato
46
48
  const getDataByFlow = name => createSelector(selectFlower(name), Selectors.getDataByFlow);
49
+ // selettore per recuperare i dati di un flow specifico e id specifico
47
50
  const getDataFromState = (name, id) => createSelector(getDataByFlow(name), Selectors.getDataFromState(id));
48
51
  const makeSelectNodeErrors = (name, currentNodeId) => createSelector(selectFlowerFormNode(name, currentNodeId), Selectors.makeSelectNodeErrors);
49
52
  const makeSelectNodeFormTouched = (name, currentNodeId) => createSelector(selectFlowerFormNode(name, currentNodeId), Selectors.makeSelectNodeFormTouched);
@@ -51,6 +54,7 @@ const getAllData = createSelector(selectGlobal, mapData);
51
54
  const makeSelectFieldError = (name, id, validate) => createSelector(getAllData, Selectors.makeSelectFieldError(name, id, validate));
52
55
  const selectorRulesDisabled = (id, rules, keys, flowName, value, currentNode) => createSelector(getAllData, makeSelectNodeErrors(flowName, currentNode), Selectors.selectorRulesDisabled(id, rules, keys, flowName, value));
53
56
 
57
+ //TODO check reduxContext type due to remove all any types
54
58
  const reduxContext = /*#__PURE__*/createContext(null);
55
59
  const useDispatch = createDispatchHook(reduxContext);
56
60
  const useSelector = createSelectorHook(reduxContext);
@@ -81,6 +85,11 @@ class FlowerProvider extends PureComponent {
81
85
  }
82
86
  }
83
87
 
88
+ /* eslint-disable no-undef */
89
+ /* eslint-disable no-underscore-dangle */
90
+ /**
91
+ * FlowerClient
92
+ */
84
93
  const FlowerClient = ({
85
94
  children,
86
95
  name,
@@ -91,7 +100,9 @@ const FlowerClient = ({
91
100
  const flowName = name;
92
101
  const dispatch = useDispatch();
93
102
  const one = useRef(false);
94
- const [wsDevtools, setWsDevtools] = useState(global.window && _get(global.window, '__FLOWER_DEVTOOLS_INITIALIZED__', false));
103
+ const [wsDevtools, setWsDevtools] = useState(devtoolState && _get(devtoolState, '__FLOWER_DEVTOOLS_INITIALIZED__', false));
104
+ // TODO rivedere il giro, potremmo fare le trasformazioni in CoreUtils.generateNodesForFlowerJson
105
+ // eslint-disable-next-line react-hooks/exhaustive-deps, max-len
95
106
  const nodes = useMemo(() => convertElements(Children.toArray(children)), [children]);
96
107
  const nodeById = useMemo(() => _keyBy(Children.toArray(children), 'props.id'), [children]);
97
108
  const isInitialized = useSelector(makeSelectStartNodeId(name));
@@ -105,6 +116,7 @@ const FlowerClient = ({
105
116
  one.current = true;
106
117
  dispatch(actions.initNodes({
107
118
  name: flowName,
119
+ // @ts-expect-error FIX ME
108
120
  nodes,
109
121
  startId: _startId != null ? _startId : '',
110
122
  persist: _destroyOnUnmount === false,
@@ -113,6 +125,7 @@ const FlowerClient = ({
113
125
  }
114
126
  }, [dispatch, flowName, nodes, _startId, _initialData, _destroyOnUnmount]);
115
127
  useEffect(() => {
128
+ /* istanbul ignore next */
116
129
  const eventCb = msg => {
117
130
  if (msg.source !== 'flower-devtool') return;
118
131
  if (msg.action === 'FLOWER_EXTENSION_INIT' || msg.action === 'FLOWER_DEVTOOL_WEB_INIT') {
@@ -137,16 +150,19 @@ const FlowerClient = ({
137
150
  }));
138
151
  }
139
152
  };
140
- if (global.window && _get(global.window, '__FLOWER_DEVTOOLS__')) {
153
+ /* istanbul ignore next */
154
+ if (devtoolState && _get(devtoolState, '__FLOWER_DEVTOOLS__')) {
141
155
  Emitter.on('flower-devtool-to-client', eventCb);
142
156
  }
143
157
  return () => {
144
- if (global.window && _get(global.window, '__FLOWER_DEVTOOLS__')) {
158
+ /* istanbul ignore next */
159
+ if (devtoolState && _get(devtoolState, '__FLOWER_DEVTOOLS__')) {
145
160
  Emitter.off('flower-devtool-to-client', eventCb);
146
161
  }
147
162
  };
148
163
  }, [dispatch, flowName]);
149
164
  useEffect(() => () => {
165
+ // unmount function
150
166
  if (_destroyOnUnmount && one.current === true) {
151
167
  one.current = false;
152
168
  dispatch(actions.destroy({
@@ -155,7 +171,8 @@ const FlowerClient = ({
155
171
  }
156
172
  }, [dispatch, flowName, _destroyOnUnmount]);
157
173
  useEffect(() => {
158
- if (isInitialized && wsDevtools && global.window && _get(global.window, '__FLOWER_DEVTOOLS__')) {
174
+ /* istanbul ignore next */
175
+ if (isInitialized && wsDevtools && devtoolState && _get(devtoolState, '__FLOWER_DEVTOOLS__')) {
159
176
  Emitter.emit('flower-devtool-from-client', {
160
177
  source: 'flower-client',
161
178
  action: 'FLOWER_CLIENT_INIT',
@@ -167,7 +184,8 @@ const FlowerClient = ({
167
184
  }
168
185
  }, [dispatch, flowName, wsDevtools, isInitialized, store]);
169
186
  useEffect(() => {
170
- if (isInitialized && wsDevtools && global.window && _get(global.window, '__FLOWER_DEVTOOLS__')) {
187
+ /* istanbul ignore next */
188
+ if (isInitialized && wsDevtools && devtoolState && _get(devtoolState, '__FLOWER_DEVTOOLS__')) {
171
189
  Emitter.emit('flower-devtool-from-client', {
172
190
  source: 'flower-client',
173
191
  action: 'SET_HISTORY',
@@ -178,8 +196,10 @@ const FlowerClient = ({
178
196
  }, [dispatch, flowName, history, wsDevtools, isInitialized]);
179
197
  useEffect(() => {
180
198
  if (!current) return;
199
+ /* istanbul ignore next */
181
200
  if (!isInitialized) return;
182
- if (isInitialized && wsDevtools && global.window && _get(global.window, '__FLOWER_DEVTOOLS__')) {
201
+ /* istanbul ignore next */
202
+ if (isInitialized && wsDevtools && devtoolState && _get(devtoolState, '__FLOWER_DEVTOOLS__')) {
183
203
  Emitter.emit('flower-devtool-from-client', {
184
204
  source: 'flower-client',
185
205
  action: 'SET_CURRENT',
@@ -190,6 +210,7 @@ const FlowerClient = ({
190
210
  }, [flowName, current, wsDevtools, isInitialized]);
191
211
  useEffect(() => {
192
212
  if (!current) return;
213
+ /* istanbul ignore next */
193
214
  if (!isInitialized) return;
194
215
  if (isDisabled) {
195
216
  dispatch({
@@ -199,7 +220,9 @@ const FlowerClient = ({
199
220
  disabled: true
200
221
  }
201
222
  });
202
- if (wsDevtools && global.window && _get(global.window, '__FLOWER_DEVTOOLS__')) {
223
+ // eslint-disable-next-line no-underscore-dangle, no-undef
224
+ /* istanbul ignore next */
225
+ if (wsDevtools && devtoolState && _get(devtoolState, '__FLOWER_DEVTOOLS__')) {
203
226
  Emitter.emit('flower-devtool-from-client', {
204
227
  source: 'flower-client',
205
228
  action: 'FLOWER_NAVIGATE',
@@ -217,8 +240,10 @@ const FlowerClient = ({
217
240
  }
218
241
  return;
219
242
  }
220
- if (wsDevtools && global.window && _get(global.window, '__FLOWER_DEVTOOLS__')) {
221
- if (isInitialized === current) return;
243
+ // eslint-disable-next-line no-underscore-dangle, no-undef
244
+ /* istanbul ignore next */
245
+ if (wsDevtools && devtoolState && _get(devtoolState, '__FLOWER_DEVTOOLS__')) {
246
+ if (isInitialized === current) return; // salto il primo evento
222
247
  Emitter.emit('flower-devtool-from-client', {
223
248
  source: 'flower-client',
224
249
  action: 'SET_SELECTED',
@@ -314,6 +339,15 @@ function FlowerStart() {
314
339
  isStart: true
315
340
  }
316
341
  });
342
+ // if (global.window
343
+ // // eslint-disable-next-line no-underscore-dangle, no-undef
344
+ // && global.window.__FLOWER_DEVTOOLS__ && global.window.__FLOWER_DEVTOOLS__AUTO) {
345
+ // Emitter.emit('flower-devtool-from-client', {
346
+ // source: 'flower-client',
347
+ // action: 'START_FLOWER',
348
+ // name: flowName,
349
+ // });
350
+ // }
317
351
  }
318
352
  }, [dispatch, autostart, startNodeId, currentNode, flowName]);
319
353
  return null;
@@ -415,6 +449,7 @@ const FlowerRule = ({
415
449
  type
416
450
  } = child;
417
451
  const Component = type;
452
+ // eslint-disable-next-line react/jsx-props-no-spreading
418
453
  return Component && /*#__PURE__*/React.createElement(Component, _extends({
419
454
  key: i,
420
455
  hidden: true
@@ -430,6 +465,7 @@ const FlowerRule = ({
430
465
  type
431
466
  } = child;
432
467
  const Component = type;
468
+ // eslint-disable-next-line react/jsx-props-no-spreading
433
469
  return Component && /*#__PURE__*/React.createElement(Component, _extends({
434
470
  key: i
435
471
  }, props));
@@ -444,6 +480,7 @@ const _excluded$3 = ["Component", "id", "flowName", "currentNode", "validate", "
444
480
  function isIntrinsicElement$1(x) {
445
481
  return typeof x === 'string';
446
482
  }
483
+ //TODO make types for wrapper function props
447
484
  function Wrapper$1(_ref) {
448
485
  let {
449
486
  Component,
@@ -542,6 +579,7 @@ function Wrapper$1(_ref) {
542
579
  });
543
580
  }, [flowName, currentNode, isValidating]);
544
581
  useLayoutEffect(() => {
582
+ // destroy
545
583
  return () => {
546
584
  if (destroyValue) {
547
585
  dispatch({
@@ -583,6 +621,8 @@ function Wrapper$1(_ref) {
583
621
  if (typeof Component === 'function') {
584
622
  return Component(newProps);
585
623
  }
624
+ // TODO si arriva in questa condizione quando si passa un componente primitivo es. div
625
+ // in questo caso non posso props custom di flower
586
626
  if (isIntrinsicElement$1(Component)) {
587
627
  return /*#__PURE__*/React.createElement(Component, _extends({
588
628
  id: id
@@ -675,6 +715,7 @@ component$4.displayName = 'FlowerField';
675
715
 
676
716
  const _excluded$2 = ["Component", "id", "flowName", "spreadValue", "hidden", "onUpdate"],
677
717
  _excluded2 = ["id", "alwaysDisplay", "rules", "value", "Component", "spreadValue", "flowName", "onUpdate"];
718
+ //TODO make types for wrapper function
678
719
  function Wrapper(_ref) {
679
720
  let {
680
721
  Component,
@@ -767,6 +808,7 @@ const FlowerValue = ({
767
808
  props
768
809
  } = child;
769
810
  const Component = type;
811
+ // eslint-disable-next-line react/jsx-props-no-spreading
770
812
  return /*#__PURE__*/React.createElement(RenderRules$1, _extends({
771
813
  key: i,
772
814
  id: _id,
@@ -816,6 +858,24 @@ const makeActionPayloadOnReset = makeActionPayload(ACTION_TYPES.reset, PAYLAOAD_
816
858
  const makeActionPayloadOnNode = makeActionPayload(ACTION_TYPES.jump, PAYLAOAD_KEYS_NEEDED.jump);
817
859
  const makeActionPayloadOnNext = makeActionPayload(ACTION_TYPES.next, PAYLAOAD_KEYS_NEEDED.next);
818
860
  const makeActionPayloadOnRestart = makeActionPayload(ACTION_TYPES.restart, PAYLAOAD_KEYS_NEEDED.restart);
861
+ /** This hook allows you to read flow informations, such as the flowName and ID of the current node.
862
+ *
863
+ * It also exposes all the functions to navigate within the flow:
864
+ *
865
+ * - next
866
+ *
867
+ * - back
868
+ *
869
+ * - jump
870
+ *
871
+ * - reset
872
+ *
873
+ * - restart
874
+ *
875
+ * @param {string} flowName - first optional parameter
876
+ *
877
+ * @param {string} name - optional parameter, if flowName exist, name is not used
878
+ */
819
879
  const useFlower = ({
820
880
  flowName: customFlowName,
821
881
  name
@@ -827,8 +887,13 @@ const useFlower = ({
827
887
  } = useContext(context);
828
888
  const flowName = customFlowName || name || flowNameDefault;
829
889
  const nodeId = useSelector(makeSelectCurrentNodeId(flowName != null ? flowName : ''));
830
- const emitNavigateEvent = useCallback(params => {
831
- if (_get(global.window, '__FLOWER_DEVTOOLS__')) {
890
+ const startId = useSelector(makeSelectStartNodeId(flowName != null ? flowName : ''));
891
+ const emitNavigateEvent = useCallback(
892
+ //TODO check this function is needed
893
+ params => {
894
+ /* istanbul ignore next */
895
+ // eslint-disable-next-line no-underscore-dangle, no-undef
896
+ if (_get(devtoolState, '__FLOWER_DEVTOOLS__')) {
832
897
  Emitter.emit('flower-devtool-from-client', {
833
898
  source: 'flower-client',
834
899
  action: 'FLOWER_NAVIGATE',
@@ -922,6 +987,7 @@ const useFlower = ({
922
987
  return {
923
988
  flowName,
924
989
  nodeId,
990
+ startId,
925
991
  next,
926
992
  jump,
927
993
  back,
@@ -930,6 +996,28 @@ const useFlower = ({
930
996
  };
931
997
  };
932
998
 
999
+ /* eslint-disable */
1000
+ // {
1001
+ // flowName?: string | undefined;
1002
+ // action?: 'next' | 'back' | 'reset' | 'jump';
1003
+ // } & (
1004
+ // | {
1005
+ // node?: undefined;
1006
+ // route?: Route;
1007
+ // }
1008
+ // | {
1009
+ // node?: RoutePrev;
1010
+ // route?: undefined;
1011
+ // }
1012
+ // | {
1013
+ // node?: RouteReset;
1014
+ // route?: undefined;
1015
+ // }
1016
+ // | {
1017
+ // node?: RouteNode;
1018
+ // route?: undefined;
1019
+ // }
1020
+ // );
933
1021
  const useFlowerNavigate = ({
934
1022
  flowName,
935
1023
  action,
@@ -981,6 +1069,7 @@ const _excluded$1 = ["hidden", "Component", "onNavigate"];
981
1069
  function isIntrinsicElement(x) {
982
1070
  return typeof x === 'string';
983
1071
  }
1072
+ //TODO type FlowerNavigateWrapper props
984
1073
  function FlowerNavigateWrapper(_ref) {
985
1074
  let {
986
1075
  hidden,
@@ -995,16 +1084,22 @@ function FlowerNavigateWrapper(_ref) {
995
1084
  if (typeof Component === 'function') {
996
1085
  return Component(newProps);
997
1086
  }
1087
+ // TODO si arriva in questa condizione quando si passa un componente primitivo es. div
1088
+ // in questo caso non posso props custom di flower
998
1089
  if (isIntrinsicElement(Component)) {
999
1090
  return /*#__PURE__*/React.createElement(Component, _extends({}, props, {
1000
1091
  onClick: onNavigate
1001
1092
  }));
1002
1093
  }
1094
+ // TODO in questa condizione si arriva se nel progetto si utilizza Vite, in questo caso i componenti non sono Function ma Object,
1095
+ // oppure nel caso di un testo semplice come children di questo componente
1096
+ /* istanbul ignore next */
1003
1097
  return Component && /*#__PURE__*/React.createElement(Component, _extends({}, newProps));
1004
1098
  }
1005
1099
  const component$2 = /*#__PURE__*/React.memo(FlowerNavigateWrapper);
1006
1100
 
1007
1101
  const _excluded = ["alwaysDisplay", "rules", "Component", "flowName", "onNavigate"];
1102
+ //TODO type RenderRules props
1008
1103
  const RenderRules = _ref => {
1009
1104
  let {
1010
1105
  alwaysDisplay,
@@ -1060,6 +1155,7 @@ const FlowerNavigate = ({
1060
1155
  props
1061
1156
  } = child;
1062
1157
  const Component = type;
1158
+ // eslint-disable-next-line react/jsx-props-no-spreading
1063
1159
  return /*#__PURE__*/React.createElement(RenderRules, _extends({
1064
1160
  key: i,
1065
1161
  alwaysDisplay: alwaysDisplay,
@@ -1078,6 +1174,23 @@ const FlowerComponent = ({
1078
1174
  }) => children;
1079
1175
  const component = /*#__PURE__*/memo(FlowerComponent);
1080
1176
 
1177
+ /** This hook allows you to manage and retrieve information about Forms.
1178
+ *
1179
+ * It exposes details regarding the form's state and a set of methods for reading and writing within it:
1180
+ *
1181
+ * - getData
1182
+ *
1183
+ * - setData
1184
+ *
1185
+ * - unSetData
1186
+ *
1187
+ * - replaceData
1188
+ *
1189
+ * @param {string} flowName - first optional parameter
1190
+ *
1191
+ * @param {string} name - optional parameter, if flowName exist, name is not used
1192
+ *
1193
+ */
1081
1194
  const useFlowerForm = ({
1082
1195
  flowName: customFlowName,
1083
1196
  name
@@ -1,8 +1,25 @@
1
1
  export type FlowerNodeDefaultProps = {
2
+ /** Unique identifier for the node inside the Flow */
2
3
  id: string;
4
+ /** An object containing the informations about the node's links.
5
+ *
6
+ * Example: to={{ step2: { rules: { $and: [{ name: { $eq: 'John' } }] } } }}
7
+ *
8
+ * In that case, the FlowerNode is linked to the node with the ID 'step2'
9
+ *
10
+ * You can move from the current node to the step2 node only if the rules are satisfied
11
+ *
12
+ * Set it to null when you don't have rules
13
+ *
14
+ * Example: to={{ step2: null}
15
+ */
3
16
  to?: Record<string, any>;
17
+ /** The children of the FlowerNode */
4
18
  children?: React.ReactNode;
19
+ /** The function executed when you enter into this FlowerNode */
5
20
  onEnter?: () => void;
21
+ /** The function executed when you leave this FlowerNode */
6
22
  onExit?: () => void;
23
+ /** When set to true, the FlowerNode is ignored and skipped */
7
24
  disabled?: boolean;
8
25
  };
@@ -1,4 +1,6 @@
1
1
  export type FlowerComponentProps = {
2
+ /** The name of the component */
2
3
  name: string;
4
+ /** The component's children */
3
5
  children: React.ReactNode;
4
6
  };
@@ -1,30 +1,108 @@
1
1
  import { FunctionRule, RulesObject } from '@flowerforce/flower-core';
2
2
  export type FlowerFieldProps<T extends Record<string, any> = Record<string, any>> = {
3
+ /** The path to the value you want to read from the flow's data
4
+ *
5
+ * Example: id="loginForm.name"
6
+ *
7
+ * The FlowerField component reads the value of the key "name" of the loginForm object in the flow's data
8
+ */
3
9
  id?: string;
10
+ /** The FlowerField's children */
4
11
  children: React.ReactNode | ((props: {
12
+ /** The string passed to the "id" FlowerField's prop */
5
13
  id: string;
14
+ /** The value found at the "id" key in the flow data
15
+ *
16
+ * Example: id="loginForm.name"
17
+ *
18
+ * This parameter will hold the value found at the key 'name' of the loginForm object in the flow's data.
19
+ */
6
20
  value: any;
21
+ /** An array of strings containing error messages associated with validation rules that are not satisfied. */
7
22
  errors: undefined | string[];
23
+ /** This parameter will notify you when there are validation errors. */
8
24
  hasError: undefined | boolean;
25
+ /** Use this function to write a new value at the "id" key
26
+ *
27
+ * Example: id="loginForm.name"
28
+ *
29
+ * onChange("John") will write "John" at the key 'name' of the loginForm object in the flow's data.
30
+ */
9
31
  onChange: (props: any) => void;
32
+ /** The function executed to test all the validation rules*/
10
33
  onBlur: () => void;
34
+ /** This parameter will notify you whether the form field has been touched */
11
35
  isTouched: boolean;
36
+ /** true when some of the display rules are not satisfied, and you have passed true to the "alwaysDisplay" FlowerField's prop*/
12
37
  hidden: boolean;
38
+ /** true when you have an async validation in progress */
13
39
  isValidating: boolean | undefined;
14
40
  }) => React.ReactNode | React.ReactElement | undefined);
41
+ /**The validation rules for that field
42
+ *
43
+ * Example: validate={[
44
+ *
45
+ * {
46
+ * rules: {
47
+ * $self: {
48
+ * $regex:
49
+ * '^([A-Z]{6}[0-9LMNPQRSTUV]{2}[ABCDEHLMPRST]{1}[0-9LMNPQRSTUV]{2}[A-Z]{1}[0-9LMNPQRSTUV]{3}[A-Z]{1})$|([0-9]{11})$',
50
+ * },
51
+ * },
52
+ * message: 'Value not valid',
53
+ * },
54
+ * {
55
+ * // Don't use promises
56
+ * rules: (data)=> {
57
+ * return data.name === 'Andrea'
58
+ * },
59
+ * message: 'Value not valid',
60
+ * }
61
+ * ]}
62
+ *
63
+ * For every rule you can pass an error message, that Flower returns when that condition is note satisfied
64
+ */
15
65
  validate?: Record<string, any>[] | string[];
66
+ /** A function to perform an async validation */
16
67
  asyncValidate?: (value: any, data?: Record<string, any>, errors?: undefined | string[]) => string[] | undefined | Promise<string[]> | {
17
68
  message: string;
18
69
  }[] | boolean | Promise<boolean>;
70
+ /** Use this to set a debounce for the async validation
71
+ *
72
+ * The default value is 0
73
+ */
19
74
  asyncDebounce?: number;
75
+ /** The initial error message when you have an async validation
76
+ *
77
+ * The default value is undefined
78
+ */
20
79
  asyncInitialError?: string;
80
+ /** The message that the FlowerField returns while validating*/
21
81
  asyncWaitingError?: string;
82
+ /** An object containing the display rules of that component. When the conditions are not satisfied, the children is hidden.
83
+ *
84
+ * Example: rules={{ $and: [{ name: { $exist: true } }] }}
85
+ */
22
86
  rules?: RulesObject<T> | FunctionRule;
87
+ /** The name of the flow from which read the data
88
+ *
89
+ * - note: the default value is the name of the flow where the component is used
90
+ */
23
91
  flowName?: string;
92
+ /** Initial value field */
24
93
  defaultValue?: unknown;
25
94
  destroyValue?: boolean;
26
95
  value?: any;
96
+ /** When set to true, the children is shown even if the rules are not satisfied
97
+ *
98
+ * The FlowerField returns the boolean variable "hidden" to notify you if the conditions are satisfied or not
99
+ */
27
100
  alwaysDisplay?: boolean;
101
+ /** The function executed when the value found at the path passed to the "id" prop changes */
28
102
  onUpdate?: (value: any) => void;
103
+ /** The function executed at the "onBlur" event, for example for Input components
104
+ *
105
+ * The onBlur function will test all the validation rules
106
+ */
29
107
  onBlur?: (e: any) => void;
30
108
  };
@@ -1,4 +1,14 @@
1
1
  import { FlowerNodeDefaultProps } from './DefaultNode';
2
2
  export type FlowerFlowProps = FlowerNodeDefaultProps & {
3
+ /** A Flower node is visible only when is the current node in the navigation history of the flow.
4
+ *
5
+ * By setting this prop to true, you have the ability to view this node even when it is not the current node.
6
+ *
7
+ * This can only be set to true for FlowerNode and FlowerFlow components.
8
+ *
9
+ * An example use case is when transitioning from a FlowerNode containing a particular screen to an action node.
10
+ *
11
+ * The node with retain set to true will continue to be displayed until a new FlowerNode or FlowerFlow is added to the history
12
+ * */
3
13
  retain?: boolean;
4
14
  };
@@ -3,25 +3,48 @@ export type UseFlowerProps = {
3
3
  [x in 'name' | 'flowName']?: string;
4
4
  };
5
5
  export type UseFlowerForm = (options?: UseFlowerProps) => {
6
+ /** This value is set to true when the form has been touched at least once. */
6
7
  touched: boolean;
8
+ /** An object containing all the form errors */
7
9
  errors: Record<string, any>;
10
+ /** This value is set to true when all the validation rules are satisfied and the form is valid*/
8
11
  isValid: boolean;
12
+ /** This value is set to true during asynchronous validation.*/
9
13
  isValidating: boolean | undefined;
14
+ /** Use this function to read values from the flow's data. */
10
15
  getData: (path?: string) => any;
11
- setData: (value: any, path?: string) => void;
12
- unsetData: (path: string) => void;
16
+ /** Use this function to set values in the flow's data. */
17
+ setData: (
18
+ /** The value that you want to set */
19
+ value: any,
20
+ /** Specify the target path to set the value*/
21
+ path?: string) => void;
22
+ /** Use this function to unset values in the flow's data. */
23
+ unsetData: (
24
+ /** Specify the target path to the value tha you want to unset*/
25
+ path: string) => void;
26
+ /** Use this function to replace a value in the flow's data. */
13
27
  replaceData: (value: any) => void;
14
28
  };
15
29
  type useFlowerActions = {
30
+ /** Use this function to move to the next node inside the flow*/
16
31
  next: (payload?: Route) => void;
32
+ /**Use this function to move to the previous node inside the flow*/
17
33
  back: (payload?: RoutePrev) => void;
34
+ /**Use this function to return to the first node and restore history */
18
35
  reset: (payload?: RouteReset) => void;
36
+ /**Use this function to move to a specific node*/
19
37
  jump: (payload: RouteNode) => void;
38
+ /**Use this function to reset the flow data and history */
20
39
  restart: (payload?: RouteRestart) => void;
21
40
  };
22
41
  export type UseFlower = (options?: UseFlowerProps) => useFlowerActions & {
42
+ /**The flow in which the hook is used.*/
23
43
  flowName?: string;
44
+ /**Current node id*/
24
45
  nodeId: string;
46
+ /**Initial start node id*/
47
+ startId: string;
25
48
  };
26
49
  export type NavigateFunctionParams = string | Record<string, any>;
27
50
  export {};
@@ -3,6 +3,10 @@ export type Route = string | Record<string, any>;
3
3
  export type RouteNode = string | {
4
4
  node: string;
5
5
  flowName?: string;
6
+ /**
7
+ * The flow's history on server component
8
+ * @experimental
9
+ */
6
10
  history?: string[];
7
11
  };
8
12
  export type RouteRestart = string | {
@@ -19,9 +23,19 @@ export type RoutePrev = string | {
19
23
  flowName?: string;
20
24
  };
21
25
  export type FlowerNavigateProps = {
26
+ /** The name of the flow from which read the data
27
+ *
28
+ * - note: the default value is the name of the flow where the component is used
29
+ */
22
30
  flowName?: string | undefined;
31
+ /** The FlowerNavigate's children */
23
32
  children: React.ReactNode | ((props: Record<string, any>) => React.ReactNode | React.ReactElement | undefined);
33
+ /** An object containing the display rules of that component. When the conditions are not satisfied, the children is hidden. */
24
34
  rules?: RulesObject<Record<string, any>> | Record<string, RulesObject<any>>;
35
+ /** When set to true, the children is shown even if the rules are not satisfied
36
+ *
37
+ * The FlowerValue returns the boolean variable "hidden" to notify you if the conditions are satisfied or not
38
+ */
25
39
  alwaysDisplay?: boolean;
26
40
  } & ({
27
41
  action?: 'next';
@@ -1,4 +1,14 @@
1
1
  import { FlowerNodeDefaultProps } from './DefaultNode';
2
2
  export type FlowerNodeProps = FlowerNodeDefaultProps & {
3
+ /** A Flower node is visible only when is the current node in the navigation history of the flow.
4
+ *
5
+ * By setting this prop to true, you have the ability to view this node even when it is not the current node.
6
+ *
7
+ * This can only be set to true for FlowerNode and FlowerFlow components.
8
+ *
9
+ * An example use case is when transitioning from a FlowerNode containing a particular screen to an action node.
10
+ *
11
+ * The node with retain set to true will continue to be displayed until a new FlowerNode or FlowerFlow is added to the history
12
+ * */
3
13
  retain?: boolean;
4
14
  };
@@ -1,8 +1,25 @@
1
1
  export type FlowerRouteProps = {
2
+ /** Unique identifier for the node inside the Flow */
2
3
  id: string;
4
+ /** TODO document what this props does */
3
5
  autostart?: boolean;
6
+ /** An object containing the informations about the node's links.
7
+ *
8
+ * Example: to={{ step2: { rules: { $and: [{ name: { $eq: 'John' } }] } } }}
9
+ *
10
+ * In that case, the FlowerRoute is linked to the node with the ID 'step2'
11
+ *
12
+ * You can move from the current node to the step2 node only if the rules are satisfied
13
+ *
14
+ * Set it to null when you don't have rules
15
+ *
16
+ * Example: to={{ step2: null}
17
+ */
4
18
  to?: Record<string, any>;
19
+ /** The children of the FlowerRoute */
5
20
  children?: React.ReactNode;
21
+ /** The function executed when you enter into this FlowerRoute */
6
22
  onEnter?: () => void;
23
+ /** The function executed when you leave this FlowerRoute */
7
24
  onExit?: () => void;
8
25
  };
@@ -1,11 +1,34 @@
1
1
  import { FunctionRule, RulesObject } from '@flowerforce/flower-core';
2
2
  export type FlowerRuleProps = {
3
+ /** The path to the value you want to read from the flow's data
4
+ *
5
+ * Example: id="loginForm.name"
6
+ *
7
+ * The FlowerRule component reads the value of the key "name" of the loginForm object in the flow's data
8
+ */
3
9
  id?: string;
10
+ /** */
4
11
  value?: any;
12
+ /** An object or function containing the display rules of that component. When the conditions are not satisfied, the children is hidden.
13
+ *
14
+ * Example: rules={{ $and: [{ name: { $exist: true } }] }}
15
+ * Example: rules={(state) => state... === true}
16
+ * if missing it is always visible
17
+ */
5
18
  rules?: RulesObject<any> | FunctionRule;
19
+ /** The name of the flow from which read the data
20
+ *
21
+ * - note: the default value is the name of the flow where the component is used
22
+ */
6
23
  flowName?: string;
24
+ /** When set to true, the children is shown even if the rules are not satisfied
25
+ *
26
+ * The FlowerRule returns the boolean variable "hidden" to notify you if the conditions are satisfied or not
27
+ */
7
28
  alwaysDisplay?: boolean;
29
+ /** The function executed when the value found at the path passed to the "id" prop changes */
8
30
  onUpdate?: (hidden: boolean) => void;
31
+ /** The children of the FlowerRule*/
9
32
  children?: React.ReactNode | ((props: {
10
33
  hidden?: boolean;
11
34
  }) => React.ReactNode | React.ReactElement | undefined);
@@ -1,7 +1,9 @@
1
1
  import { FlowerNodeProps } from './FlowerNode';
2
2
  export type FlowerServerProps = {
3
3
  action?: {
4
+ /** The type of the action */
4
5
  type: string;
6
+ /** The parameters passed to the action */
5
7
  props?: Record<string, any>;
6
8
  };
7
9
  } & FlowerNodeProps;
@@ -1,11 +1,33 @@
1
1
  import { FunctionRule, RulesObject } from '@flowerforce/flower-core';
2
2
  export type FlowerValueProps = {
3
+ /** The path to the value you want to read from the flow's data
4
+ *
5
+ * Example: id="loginForm.name"
6
+ *
7
+ * The FlowerValue component reads the value of the key "name" of the loginForm object in the flow's data
8
+ * If missing, I return all values, which is equivalent to setting id='*'
9
+ */
3
10
  id?: string;
4
11
  value?: any;
12
+ /** An object containing the display rules of that component. When the conditions are not satisfied, the children is hidden.
13
+ *
14
+ * Example: rules={{ $and: [{ name: { $exist: true } }] }}
15
+ */
5
16
  rules?: RulesObject<any> | FunctionRule;
17
+ /** The FlowerValue's children */
6
18
  children: React.ReactNode | ((props: Record<string, any>) => React.ReactNode | React.ReactElement | undefined);
19
+ /** Set this value to true to spread the value into separate values in case it is an object. */
7
20
  spreadValue?: boolean;
21
+ /** The name of the flow from which read the data
22
+ *
23
+ * - note: the default value is the name of the flow where the component is used
24
+ */
8
25
  flowName?: string;
26
+ /** When set to true, the children is shown even if the rules are not satisfied
27
+ *
28
+ * The FlowerValue returns the boolean variable "hidden" to notify you if the conditions are satisfied or not
29
+ */
9
30
  alwaysDisplay?: boolean;
31
+ /** The function executed when the value found at the path passed to the "id" prop changes */
10
32
  onUpdate?: (value: any) => void;
11
33
  };
@@ -1,3 +1,21 @@
1
1
  import { UseFlower } from './types/FlowerHooks';
2
+ /** This hook allows you to read flow informations, such as the flowName and ID of the current node.
3
+ *
4
+ * It also exposes all the functions to navigate within the flow:
5
+ *
6
+ * - next
7
+ *
8
+ * - back
9
+ *
10
+ * - jump
11
+ *
12
+ * - reset
13
+ *
14
+ * - restart
15
+ *
16
+ * @param {string} flowName - first optional parameter
17
+ *
18
+ * @param {string} name - optional parameter, if flowName exist, name is not used
19
+ */
2
20
  declare const useFlower: UseFlower;
3
21
  export default useFlower;
@@ -1,3 +1,20 @@
1
1
  import { UseFlowerForm } from './types/FlowerHooks';
2
+ /** This hook allows you to manage and retrieve information about Forms.
3
+ *
4
+ * It exposes details regarding the form's state and a set of methods for reading and writing within it:
5
+ *
6
+ * - getData
7
+ *
8
+ * - setData
9
+ *
10
+ * - unSetData
11
+ *
12
+ * - replaceData
13
+ *
14
+ * @param {string} flowName - first optional parameter
15
+ *
16
+ * @param {string} name - optional parameter, if flowName exist, name is not used
17
+ *
18
+ */
2
19
  declare const useFlowerForm: UseFlowerForm;
3
20
  export default useFlowerForm;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@flowerforce/flower-react",
3
- "version": "3.1.1",
3
+ "version": "3.1.2-beta.0",
4
4
  "description": "FlowerJS components, hooks and utils for React.",
5
5
  "repository": {
6
6
  "type": "git",
@@ -34,7 +34,7 @@
34
34
  "typescript": "^5.4.5"
35
35
  },
36
36
  "dependencies": {
37
- "@flowerforce/flower-core": "3.1.1",
37
+ "@flowerforce/flower-core": "3.1.2-beta.0",
38
38
  "@reduxjs/toolkit": "^2.2.4",
39
39
  "lodash": "^4.17.21",
40
40
  "react-redux": "^9.1.2",