@inseefr/lunatic 0.3.1-experimental → 0.3.2-experimental

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 (51) hide show
  1. package/lib/index.js +192 -189
  2. package/lib/index.js.map +1 -1
  3. package/package.json +2 -2
  4. package/src/components/component-wrapper/controls/validators/datepicker.js +25 -14
  5. package/src/components/component-wrapper/missing/component.js +37 -17
  6. package/src/components/datepicker/component.js +8 -12
  7. package/src/components/declarations/wrappers/input-declarations-wrapper.js +3 -2
  8. package/src/components/loop-constructor/block/index.js +1 -1
  9. package/src/components/loop-constructor/index.js +1 -1
  10. package/src/components/loop-constructor/roster/index.js +1 -1
  11. package/src/components/loop-constructor/wrapper/body-component.js +3 -0
  12. package/src/components/loop-constructor/wrapper/build-components.js +33 -33
  13. package/src/components/loop-constructor/wrapper/index.js +1 -1
  14. package/src/components/suggester/components/panel/option-container.js +1 -1
  15. package/src/components/suggester/suggester-wrapper.js +3 -3
  16. package/src/components/table/table.js +3 -1
  17. package/src/stories/loop-constructor/README.md +27 -27
  18. package/src/stories/loop-constructor/data-input-forced.json +64 -64
  19. package/src/stories/loop-constructor/data-input.json +100 -100
  20. package/src/stories/loop-constructor/data-loop-forced.json +66 -66
  21. package/src/stories/loop-constructor/data-loop-static-forced.json +66 -66
  22. package/src/stories/loop-constructor/data-loop-static.json +81 -81
  23. package/src/stories/loop-constructor/data-loop.json +81 -81
  24. package/src/stories/loop-constructor/data-roster-forced.json +68 -68
  25. package/src/stories/loop-constructor/data-roster.json +83 -83
  26. package/src/stories/loop-constructor/loop-constructor.stories.js +180 -180
  27. package/src/stories/questionnaire/arithmetic-management.json +47 -0
  28. package/src/stories/questionnaire/logement-queen.json +23390 -22706
  29. package/src/stories/questionnaire/questionnaire.stories.js +14 -14
  30. package/src/stories/suggester/data.json +4 -1
  31. package/src/stories/suggester/suggester-workers.stories.js +4 -1
  32. package/src/stories/utils/orchestrator-split.js +117 -0
  33. package/src/tests/utils/to-expose/handler/results/res-input-edited.json +1 -1
  34. package/src/tests/utils/to-expose/state/state.spec.js +59 -59
  35. package/src/utils/lib/index.js +1 -0
  36. package/src/utils/lib/pagination/navigation/shared.js +5 -5
  37. package/src/utils/lib/splitting.js +110 -0
  38. package/src/utils/suggester-workers/commons-tokenizer/create-entity-tokenizer.js +4 -2
  39. package/src/utils/suggester-workers/commons-tokenizer/filters/{filter-accents-to-lower.js → filter-accents.js} +2 -2
  40. package/src/utils/suggester-workers/commons-tokenizer/filters/{filter-accents-to-lower.spec.js → filter-accents.spec.js} +1 -1
  41. package/src/utils/suggester-workers/commons-tokenizer/filters/filter-synonyms.js +27 -1
  42. package/src/utils/suggester-workers/commons-tokenizer/filters/filter-to-lower.js +10 -0
  43. package/src/utils/suggester-workers/commons-tokenizer/filters/filter-to-lower.spec.js +12 -0
  44. package/src/utils/suggester-workers/commons-tokenizer/index.js +1 -1
  45. package/src/utils/to-expose/handler.js +47 -28
  46. package/src/utils/to-expose/hooks/filter-components.js +106 -106
  47. package/src/utils/to-expose/hooks/index.js +2 -1
  48. package/src/utils/to-expose/hooks/lunatic-split.js +407 -0
  49. package/src/utils/to-expose/hooks/lunatic.js +16 -2
  50. package/src/utils/to-expose/index.js +11 -11
  51. package/src/utils/to-expose/state.js +23 -15
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inseefr/lunatic",
3
- "version": "0.3.1-experimental",
3
+ "version": "0.3.2-experimental",
4
4
  "workersVersion": "0.2.1-experimental",
5
5
  "description": "Library of questionnaire components",
6
6
  "repository": {
@@ -50,7 +50,7 @@
50
50
  "library"
51
51
  ],
52
52
  "dependencies": {
53
- "@inseefr/trevas": "^0.1.10",
53
+ "@inseefr/trevas": "^0.1.11",
54
54
  "date-fns": "^2.25.0",
55
55
  "lodash.camelcase": "^4.3.0",
56
56
  "lodash.debounce": "^4.0.8",
@@ -13,21 +13,32 @@ const getMessage = (min, max, value) => {
13
13
  if (!value) {
14
14
  return undefined;
15
15
  }
16
- const dateFormat = 'dd/MM/yyyy';
16
+ const dateFormat = 'dd-MM-yyyy';
17
17
  const date = new Date(value);
18
- if (isNaN(Date.parse(min))) return undefined;
19
- if (isNaN(Date.parse(max))) return undefined;
20
- const minDate = new Date(min);
21
- const maxDate = new Date(max);
22
- const minDateAsString = minDate ? format(minDate, dateFormat) : '';
23
- const maxDateAsString = maxDate ? format(maxDate, dateFormat) : '';
24
- if (!min && isDef(max) && compareAsc(date, maxDate) > 0)
25
- return `La date doit être inférieure au ${maxDateAsString}`;
26
- else if (isDef(min) && !max && compareAsc(date, minDate) > 0)
27
- return `La date doit être supérieure au ${minDateAsString}`;
28
- else if (isDef(min) && isDef(max) && (date < minDate || date > maxDate))
29
- return `La date doit être comprise entre le ${minDateAsString} et le ${maxDateAsString}`;
18
+ if (isDef(min) && isDef(max)) {
19
+ const minDate = new Date(min);
20
+ const maxDate = new Date(max);
21
+ if (date < minDate || date > maxDate) {
22
+ const minDateAsString = minDate ? format(minDate, dateFormat) : '';
23
+ const maxDateAsString = maxDate ? format(maxDate, dateFormat) : '';
24
+ return `La date doit être comprise entre le ${minDateAsString} et le ${maxDateAsString}`;
25
+ }
26
+ }
27
+ if (isDef(min)) {
28
+ const minDate = new Date(min);
29
+ if (compareAsc(date, minDate) < 0) {
30
+ const minDateAsString = minDate ? format(minDate, dateFormat) : '';
31
+ return `La date doit être supérieure au ${minDateAsString}`;
32
+ }
33
+ }
34
+ if (isDef(max)) {
35
+ const maxDate = new Date(max);
36
+ if (compareAsc(date, maxDate) > 0) {
37
+ const maxDateAsString = maxDate ? format(maxDate, dateFormat) : '';
38
+ return `La date doit être inférieure au ${maxDateAsString}`;
39
+ }
40
+ }
30
41
  return undefined;
31
42
  };
32
43
 
33
- const isDef = (d) => d;
44
+ const isDef = (d) => !isNaN(Date.parse(d));
@@ -1,4 +1,4 @@
1
- import React, { useEffect } from 'react';
1
+ import React, { useEffect, useState } from 'react';
2
2
  import KeyboardEventHandler from 'react-keyboard-event-handler';
3
3
  import Button from '../../button';
4
4
  import * as U from '../../../utils/lib';
@@ -21,10 +21,33 @@ const Missing = ({ Component, props }) => {
21
21
  bindings,
22
22
  shortcut,
23
23
  componentType,
24
- missingLoopIteration,
24
+ paginatedLoop,
25
25
  } = props;
26
26
 
27
+ const missingResponseName = U.getResponseName(missingResponse);
27
28
  const buttonState = U.getResponseByPreference(preferences)(missingResponse);
29
+ const [oldMissingValue] = useState(() => buttonState);
30
+
31
+ const [bindingsForMissingStrategy, setBindingsForMissingStrategy] =
32
+ useState(null);
33
+
34
+ /**
35
+ * Sources split: use MissingStragy only if missingResponse has been updated
36
+ * Ensures that missingResponse is persisted when the source has to be changed
37
+ */
38
+ useEffect(() => {
39
+ const isSameValue = buttonState === oldMissingValue;
40
+ if (bindingsForMissingStrategy && !isSameValue) {
41
+ if (U.isFunction(missingStrategy))
42
+ missingStrategy(bindingsForMissingStrategy);
43
+ setBindingsForMissingStrategy(null);
44
+ }
45
+ }, [
46
+ bindingsForMissingStrategy,
47
+ missingStrategy,
48
+ buttonState,
49
+ oldMissingValue,
50
+ ]);
28
51
 
29
52
  useEffect(() => {
30
53
  if (
@@ -36,7 +59,7 @@ const Missing = ({ Component, props }) => {
36
59
  components,
37
60
  })
38
61
  ) {
39
- handleChange({ [U.getResponseName(missingResponse)]: null });
62
+ handleChange({ [missingResponseName]: null });
40
63
  }
41
64
  }, [
42
65
  buttonState,
@@ -46,7 +69,7 @@ const Missing = ({ Component, props }) => {
46
69
  responses,
47
70
  cells,
48
71
  components,
49
- missingResponse,
72
+ missingResponseName,
50
73
  ]);
51
74
 
52
75
  const getVarsToClean = () =>
@@ -62,10 +85,9 @@ const Missing = ({ Component, props }) => {
62
85
  if (!isSameValue) {
63
86
  const toClean = getVarsToClean();
64
87
  if (Object.keys(toClean)) {
65
- const { missingLoopIteration, currentPage } = props;
88
+ const { currentPage } = props;
66
89
  const currentIterationIndex = getCurrentIterationIndex({
67
90
  currentPage,
68
- missingLoopIteration,
69
91
  });
70
92
  handleChange(toClean);
71
93
  if (U.isFunction(missingStrategy)) {
@@ -81,20 +103,17 @@ const Missing = ({ Component, props }) => {
81
103
  fullBindings,
82
104
  toHandle,
83
105
  });
84
- missingStrategy(missingBindings);
106
+ setBindingsForMissingStrategy(missingBindings);
85
107
  }
86
108
  } else {
87
- if (U.isFunction(missingStrategy)) missingStrategy(bindings);
109
+ if (U.isFunction(missingStrategy))
110
+ setBindingsForMissingStrategy(bindings);
88
111
  }
89
- handleChange({ [U.getResponseName(missingResponse)]: value });
112
+ handleChange({ [missingResponseName]: value });
90
113
  }
91
114
  };
92
115
 
93
- if (
94
- componentType === 'Loop' ||
95
- missingLoopIteration ||
96
- missingLoopIteration === 0
97
- )
116
+ if ((componentType === 'Loop' && paginatedLoop) || !missingResponse)
98
117
  return <Component {...props} />;
99
118
 
100
119
  return (
@@ -111,6 +130,7 @@ const Missing = ({ Component, props }) => {
111
130
  <Button
112
131
  label="dont-know-button"
113
132
  value={dontKnowButton}
133
+ disabled={!missingResponseName || missingResponseName?.length === 0}
114
134
  onClick={onClick(U.DK)}
115
135
  />
116
136
  </span>
@@ -122,11 +142,13 @@ const Missing = ({ Component, props }) => {
122
142
  <Button
123
143
  label="refused-button"
124
144
  value={refusedButton}
145
+ disabled={!missingResponseName || missingResponseName?.length === 0}
125
146
  onClick={onClick(U.RF)}
126
147
  />
127
148
  </span>
128
149
  </div>
129
150
  {shortcut &&
151
+ missingResponseName?.length > 0 &&
130
152
  missingShortcut &&
131
153
  missingShortcut.dontKnow &&
132
154
  missingShortcut.refused && (
@@ -147,11 +169,9 @@ const Missing = ({ Component, props }) => {
147
169
  export default Missing;
148
170
 
149
171
  // TODO: make it recursive for Loop into Loop
150
- const getCurrentIterationIndex = ({ currentPage, missingLoopIteration }) => {
172
+ const getCurrentIterationIndex = ({ currentPage }) => {
151
173
  const { currentIteration } = U.splitPage(currentPage, 1);
152
174
  if (currentIteration) return currentIteration - 1;
153
- if (missingLoopIteration || missingLoopIteration === 0)
154
- return missingLoopIteration;
155
175
  return null;
156
176
  };
157
177
 
@@ -6,18 +6,14 @@ import { areEqual } from '../../utils/lib';
6
6
  import { getTypeControls } from '../component-wrapper/controls/validators';
7
7
  import './datepicker.scss';
8
8
 
9
- const Datepicker = (props) => {
10
- const { max } = props;
11
- return (
12
- <InputDeclarationsWrapper
13
- type="date"
14
- roleType="datepicker"
15
- {...props}
16
- validators={[getTypeControls]}
17
- max={max || '1979-12-31'}
18
- />
19
- );
20
- };
9
+ const Datepicker = (props) => (
10
+ <InputDeclarationsWrapper
11
+ type="date"
12
+ roleType="datepicker"
13
+ {...props}
14
+ validators={[getTypeControls]}
15
+ />
16
+ );
21
17
 
22
18
  Datepicker.defaultProps = {
23
19
  validators: [],
@@ -173,8 +173,9 @@ const InputDeclarationsWrapper = ({
173
173
  onChange={(e) => {
174
174
  const v = e.target.value;
175
175
  if (
176
- ([null, ''].includes(v) && value.length > 0) ||
177
- ([null, ''].includes(value) && v.length > 0)
176
+ (([null, ''].includes(v) && value.length > 0) ||
177
+ ([null, ''].includes(value) && v.length > 0)) &&
178
+ componentType !== 'Datepicker'
178
179
  ) {
179
180
  setValue(v);
180
181
  handleChange({
@@ -1 +1 @@
1
- export { default } from './component';
1
+ export { default } from './component';
@@ -1 +1 @@
1
- export { default as RosterForLoop } from './roster';
1
+ export { default as RosterForLoop } from './roster';
@@ -1 +1 @@
1
- export { default } from './component';
1
+ export { default } from './component';
@@ -100,11 +100,14 @@ const BodyComponent = ({
100
100
  const Component = lunatic[componentType];
101
101
  const localBindings =
102
102
  U.buildBindingsForDeeperComponents(i)(bindings);
103
+ // ensure to have only N-1 missingResponse
104
+ const { missingResponse } = componentProps;
103
105
  return (
104
106
  <div className="block-component" key={`${id}-row-${i}`}>
105
107
  <Component
106
108
  {...otherProps}
107
109
  {...componentProps}
110
+ missingResponse={missingResponse}
108
111
  id={`${id}-row-${i}`}
109
112
  label={label}
110
113
  handleChange={(up) => {
@@ -1,33 +1,33 @@
1
- import * as C from '../../../constants';
2
-
3
- export const buildContentForLoopConstructor = ({ components, headers }) => {
4
- // Start hack to find interation number
5
- // Refactor if we have to handle complex components (vector, matrix)
6
- const iterations =
7
- components.find((c) => c.response).response.values[C.COLLECTED].length || 1;
8
- // End
9
- const initialArray = [...Array(iterations).keys()];
10
- const uiComponents = components.map((comp) => {
11
- const { response, ...other } = comp;
12
- if (!response) return initialArray.map(() => comp);
13
- // Handle reponses & cells components ?
14
- const { name, values } = response;
15
- return initialArray.map((rowNumber) => {
16
- const newValues = Object.entries(values).reduce(
17
- (acc, [key, value]) => ({
18
- ...acc,
19
- [key]: value ? value[rowNumber] : null,
20
- }),
21
- {}
22
- );
23
- return {
24
- ...other,
25
- response: { name, values: newValues },
26
- rowNumber,
27
- };
28
- });
29
- }, []);
30
- const transpose = (m) => m[0].map((_, i) => m.map((x) => x[i]));
31
- const rows = transpose(uiComponents);
32
- return headers ? [headers, ...rows] : rows;
33
- };
1
+ import * as C from '../../../constants';
2
+
3
+ export const buildContentForLoopConstructor = ({ components, headers }) => {
4
+ // Start hack to find interation number
5
+ // Refactor if we have to handle complex components (vector, matrix)
6
+ const iterations =
7
+ components.find((c) => c.response).response.values[C.COLLECTED].length || 1;
8
+ // End
9
+ const initialArray = [...Array(iterations).keys()];
10
+ const uiComponents = components.map((comp) => {
11
+ const { response, ...other } = comp;
12
+ if (!response) return initialArray.map(() => comp);
13
+ // Handle reponses & cells components ?
14
+ const { name, values } = response;
15
+ return initialArray.map((rowNumber) => {
16
+ const newValues = Object.entries(values).reduce(
17
+ (acc, [key, value]) => ({
18
+ ...acc,
19
+ [key]: value ? value[rowNumber] : null,
20
+ }),
21
+ {}
22
+ );
23
+ return {
24
+ ...other,
25
+ response: { name, values: newValues },
26
+ rowNumber,
27
+ };
28
+ });
29
+ }, []);
30
+ const transpose = (m) => m[0].map((_, i) => m.map((x) => x[i]));
31
+ const rows = transpose(uiComponents);
32
+ return headers ? [headers, ...rows] : rows;
33
+ };
@@ -1 +1 @@
1
- export { default } from './component';
1
+ export { default } from './component';
@@ -50,7 +50,7 @@ function OptionContainer({ children, index, selected }) {
50
50
  className={classnames('lunatic-suggester-option', { selected })}
51
51
  role="option"
52
52
  aria-selected={selected}
53
- onClick={onClick}
53
+ onMouseDown={onClick}
54
54
  ref={ref}
55
55
  >
56
56
  {children}
@@ -32,7 +32,7 @@ function SuggesterWrapper({
32
32
  value,
33
33
  }) {
34
34
  const [state, dispatch] = useReducer(reducer, INITIAL_STATE);
35
- const { search, selectedIndex, options } = state;
35
+ const { search, selectedIndex, options, expended } = state;
36
36
 
37
37
  useEffect(
38
38
  function () {
@@ -57,11 +57,11 @@ function SuggesterWrapper({
57
57
 
58
58
  useEffect(
59
59
  function () {
60
- if (selectedIndex !== undefined) {
60
+ if (selectedIndex !== undefined && !expended) {
61
61
  onSelect(options[selectedIndex], selectedIndex);
62
62
  }
63
63
  },
64
- [selectedIndex, onSelect, options]
64
+ [selectedIndex, onSelect, options, expended]
65
65
  );
66
66
 
67
67
  useEffect(
@@ -24,6 +24,7 @@ const Table = ({
24
24
  management,
25
25
  numberAsTextfield,
26
26
  logFunction,
27
+ ...rest
27
28
  }) => {
28
29
  const minLines = initLines
29
30
  ? Math.max(initLines.min, U.getRosterInitLines(cells))
@@ -79,6 +80,7 @@ const Table = ({
79
80
  style={{ width }}
80
81
  >
81
82
  <Component
83
+ {...rest}
82
84
  label={label || ' '}
83
85
  handleChange={handleChange}
84
86
  preferences={preferences}
@@ -88,7 +90,7 @@ const Table = ({
88
90
  bindings={bindings}
89
91
  {...componentProps}
90
92
  zIndex={cells.length - i || 0}
91
- numberAsTextfield
93
+ numberAsTextfield={numberAsTextfield}
92
94
  logFunction={logFunction}
93
95
  shortcut={false}
94
96
  />
@@ -1,27 +1,27 @@
1
- # LoopConstructor component
2
-
3
- `RosterForLoop` is a LoopConstructor component.
4
-
5
- ## Props
6
-
7
- | Props | Type | Default value | Required | Description |
8
- | :-------------: | :----: | :-----------: | :------: | ------------------------------------- |
9
- | id | string | - | ✓ | Id of the table |
10
- | label | string | "" | | Label of the table |
11
- | preferences \* | array | ["COLLECTED"] | | Preferences to manage table response |
12
- | cells \* | array | [] | | Table cells |
13
- | handleChange | func | - | ✓ | Handler of the table |
14
- | lines | object | {} | | Min and max lines for evolutive table |
15
- | declarations \* | array | [] | | Declarations of the table |
16
- | features | array | [ ] | | Component features for labels |
17
- | bindings | object | [ ] | | Questionnaire bindings |
18
- | positioning \* | string | "DEFAULT" | | Cell options positioning |
19
- | addBtnLabel | string | "Add a line" | | Label of the button to add lines |
20
- | hideBtn | bool | false | | Hide the add button |
21
- | management | bool | false | | Management mode of the table |
22
- | style | object | {} | | Style of the table |
23
-
24
- - `preferences` props has to be an ordered array of `COLLECTED`, `FORCED` or `EDITED`
25
- - `cells` props has to be an array of array's components
26
- - `positioning` props has to be one of `DEFAULT`, `HORIZONTAL` or `VERTICAL`
27
- - `declarations` are documented in the `Declarations` component
1
+ # LoopConstructor component
2
+
3
+ `RosterForLoop` is a LoopConstructor component.
4
+
5
+ ## Props
6
+
7
+ | Props | Type | Default value | Required | Description |
8
+ | :-------------: | :----: | :-----------: | :------: | ------------------------------------- |
9
+ | id | string | - | ✓ | Id of the table |
10
+ | label | string | "" | | Label of the table |
11
+ | preferences \* | array | ["COLLECTED"] | | Preferences to manage table response |
12
+ | cells \* | array | [] | | Table cells |
13
+ | handleChange | func | - | ✓ | Handler of the table |
14
+ | lines | object | {} | | Min and max lines for evolutive table |
15
+ | declarations \* | array | [] | | Declarations of the table |
16
+ | features | array | [ ] | | Component features for labels |
17
+ | bindings | object | [ ] | | Questionnaire bindings |
18
+ | positioning \* | string | "DEFAULT" | | Cell options positioning |
19
+ | addBtnLabel | string | "Add a line" | | Label of the button to add lines |
20
+ | hideBtn | bool | false | | Hide the add button |
21
+ | management | bool | false | | Management mode of the table |
22
+ | style | object | {} | | Style of the table |
23
+
24
+ - `preferences` props has to be an ordered array of `COLLECTED`, `FORCED` or `EDITED`
25
+ - `cells` props has to be an array of array's components
26
+ - `positioning` props has to be one of `DEFAULT`, `HORIZONTAL` or `VERTICAL`
27
+ - `declarations` are documented in the `Declarations` component
@@ -1,64 +1,64 @@
1
- {
2
- "components": [
3
- {
4
- "id": "nn",
5
- "componentType": "InputNumber",
6
- "mandatory": false,
7
- "min": 1,
8
- "max": 4,
9
- "decimals": 0,
10
- "label": "Loop Num",
11
- "response": {
12
- "name": "NUM"
13
- }
14
- },
15
- {
16
- "id": "idLoop",
17
- "label": "boucle individu",
18
- "componentType": "Loop",
19
- "iterations": "NUM",
20
- "conditionFilter": { "value": "true" },
21
- "loopDependencies": ["NUM"],
22
- "bindingDependencies": ["PRENOM", "NUM"],
23
- "components": [
24
- {
25
- "id": "k3ym6x16",
26
- "label": "Prénom :",
27
- "componentType": "Input",
28
- "conditionFilter": { "value": "true" },
29
- "mandatory": false,
30
- "bindingDependencies": ["PRENOM"],
31
- "response": {
32
- "name": "PRENOM"
33
- }
34
- }
35
- ]
36
- }
37
- ],
38
- "variables": [
39
- {
40
- "variableType": "COLLECTED",
41
- "name": "NUM",
42
- "componentRef": "nn",
43
- "values": {
44
- "PREVIOUS": null,
45
- "COLLECTED": "2",
46
- "FORCED": null,
47
- "EDITED": null,
48
- "INPUTED": null
49
- }
50
- },
51
- {
52
- "variableType": "COLLECTED",
53
- "name": "PRENOM",
54
- "componentRef": "idLoop",
55
- "values": {
56
- "PREVIOUS": [null],
57
- "COLLECTED": ["Mauro", "Marco"],
58
- "FORCED": [null],
59
- "EDITED": [null],
60
- "INPUTED": [null]
61
- }
62
- }
63
- ]
64
- }
1
+ {
2
+ "components": [
3
+ {
4
+ "id": "nn",
5
+ "componentType": "InputNumber",
6
+ "mandatory": false,
7
+ "min": 1,
8
+ "max": 4,
9
+ "decimals": 0,
10
+ "label": "Loop Num",
11
+ "response": {
12
+ "name": "NUM"
13
+ }
14
+ },
15
+ {
16
+ "id": "idLoop",
17
+ "label": "boucle individu",
18
+ "componentType": "Loop",
19
+ "iterations": "NUM",
20
+ "conditionFilter": { "value": "true" },
21
+ "loopDependencies": ["NUM"],
22
+ "bindingDependencies": ["PRENOM", "NUM"],
23
+ "components": [
24
+ {
25
+ "id": "k3ym6x16",
26
+ "label": "Prénom :",
27
+ "componentType": "Input",
28
+ "conditionFilter": { "value": "true" },
29
+ "mandatory": false,
30
+ "bindingDependencies": ["PRENOM"],
31
+ "response": {
32
+ "name": "PRENOM"
33
+ }
34
+ }
35
+ ]
36
+ }
37
+ ],
38
+ "variables": [
39
+ {
40
+ "variableType": "COLLECTED",
41
+ "name": "NUM",
42
+ "componentRef": "nn",
43
+ "values": {
44
+ "PREVIOUS": null,
45
+ "COLLECTED": "2",
46
+ "FORCED": null,
47
+ "EDITED": null,
48
+ "INPUTED": null
49
+ }
50
+ },
51
+ {
52
+ "variableType": "COLLECTED",
53
+ "name": "PRENOM",
54
+ "componentRef": "idLoop",
55
+ "values": {
56
+ "PREVIOUS": [null],
57
+ "COLLECTED": ["Mauro", "Marco"],
58
+ "FORCED": [null],
59
+ "EDITED": [null],
60
+ "INPUTED": [null]
61
+ }
62
+ }
63
+ ]
64
+ }