@inseefr/lunatic 3.7.7-rc.0 → 3.8.0-rc.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (69) hide show
  1. package/components/Suggester/Suggester.spec.d.ts +1 -0
  2. package/components/Suggester/Suggester.spec.js +58 -0
  3. package/components/Suggester/Suggester.spec.js.map +1 -0
  4. package/esm/components/Suggester/Suggester.spec.d.ts +1 -0
  5. package/esm/components/Suggester/Suggester.spec.js +56 -0
  6. package/esm/components/Suggester/Suggester.spec.js.map +1 -0
  7. package/esm/type.source.d.ts +9 -0
  8. package/esm/use-lunatic/commons/compile-controls.js +2 -16
  9. package/esm/use-lunatic/commons/compile-controls.js.map +1 -1
  10. package/esm/use-lunatic/commons/component.d.ts +33 -0
  11. package/esm/use-lunatic/commons/component.js +37 -0
  12. package/esm/use-lunatic/commons/component.js.map +1 -1
  13. package/esm/use-lunatic/commons/variables/behaviours/cleaning-behaviour.js.map +1 -1
  14. package/esm/use-lunatic/commons/variables/global-variables.d.ts +5 -0
  15. package/esm/use-lunatic/commons/variables/global-variables.js +7 -0
  16. package/esm/use-lunatic/commons/variables/global-variables.js.map +1 -0
  17. package/esm/use-lunatic/commons/variables/lunatic-variables-store.d.ts +21 -9
  18. package/esm/use-lunatic/commons/variables/lunatic-variables-store.js +67 -49
  19. package/esm/use-lunatic/commons/variables/lunatic-variables-store.js.map +1 -1
  20. package/esm/use-lunatic/commons/variables/lunatic-variables-store.spec.js +137 -6
  21. package/esm/use-lunatic/commons/variables/lunatic-variables-store.spec.js.map +1 -1
  22. package/esm/use-lunatic/commons/variables/models.d.ts +1 -0
  23. package/esm/use-lunatic/commons/variables/models.js +2 -0
  24. package/esm/use-lunatic/commons/variables/models.js.map +1 -0
  25. package/esm/use-lunatic/commons/variables/pairwise-variables.d.ts +29 -0
  26. package/esm/use-lunatic/commons/variables/pairwise-variables.js +196 -0
  27. package/esm/use-lunatic/commons/variables/pairwise-variables.js.map +1 -0
  28. package/esm/use-lunatic/props/getComponentTypeProps.d.ts +1 -1
  29. package/esm/use-lunatic/reducer/reducerInitializer.js +5 -1
  30. package/esm/use-lunatic/reducer/reducerInitializer.js.map +1 -1
  31. package/package.json +30 -1
  32. package/src/components/Suggester/Suggester.spec.tsx +62 -0
  33. package/src/stories/pairwise/pairwise.stories.tsx +7 -0
  34. package/src/stories/pairwise/sourceGlobalVariables.json +337 -0
  35. package/src/type.source.ts +9 -0
  36. package/src/use-lunatic/commons/compile-controls.ts +10 -42
  37. package/src/use-lunatic/commons/component.ts +79 -0
  38. package/src/use-lunatic/commons/variables/behaviours/cleaning-behaviour.ts +2 -4
  39. package/src/use-lunatic/commons/variables/global-variables.ts +9 -0
  40. package/src/use-lunatic/commons/variables/lunatic-variables-store.spec.ts +149 -6
  41. package/src/use-lunatic/commons/variables/lunatic-variables-store.ts +113 -50
  42. package/src/use-lunatic/commons/variables/models.ts +1 -0
  43. package/src/use-lunatic/commons/variables/pairwise-variables.ts +251 -0
  44. package/src/use-lunatic/reducer/reducerInitializer.tsx +5 -7
  45. package/tsconfig.build.tsbuildinfo +1 -1
  46. package/type.source.d.ts +9 -0
  47. package/use-lunatic/commons/compile-controls.js +4 -18
  48. package/use-lunatic/commons/compile-controls.js.map +1 -1
  49. package/use-lunatic/commons/component.d.ts +33 -0
  50. package/use-lunatic/commons/component.js +42 -0
  51. package/use-lunatic/commons/component.js.map +1 -1
  52. package/use-lunatic/commons/variables/behaviours/cleaning-behaviour.js.map +1 -1
  53. package/use-lunatic/commons/variables/global-variables.d.ts +5 -0
  54. package/use-lunatic/commons/variables/global-variables.js +11 -0
  55. package/use-lunatic/commons/variables/global-variables.js.map +1 -0
  56. package/use-lunatic/commons/variables/lunatic-variables-store.d.ts +21 -9
  57. package/use-lunatic/commons/variables/lunatic-variables-store.js +72 -50
  58. package/use-lunatic/commons/variables/lunatic-variables-store.js.map +1 -1
  59. package/use-lunatic/commons/variables/lunatic-variables-store.spec.js +137 -6
  60. package/use-lunatic/commons/variables/lunatic-variables-store.spec.js.map +1 -1
  61. package/use-lunatic/commons/variables/models.d.ts +1 -0
  62. package/use-lunatic/commons/variables/models.js +3 -0
  63. package/use-lunatic/commons/variables/models.js.map +1 -0
  64. package/use-lunatic/commons/variables/pairwise-variables.d.ts +29 -0
  65. package/use-lunatic/commons/variables/pairwise-variables.js +199 -0
  66. package/use-lunatic/commons/variables/pairwise-variables.js.map +1 -0
  67. package/use-lunatic/props/getComponentTypeProps.d.ts +1 -1
  68. package/use-lunatic/reducer/reducerInitializer.js +5 -1
  69. package/use-lunatic/reducer/reducerInitializer.js.map +1 -1
@@ -0,0 +1,337 @@
1
+ {
2
+ "id": "mkdupypp",
3
+ "label": { "type": "VTL|MD", "value": "Pairwise global variables" },
4
+ "modele": "PAIRWISEGL",
5
+ "maxPage": "5",
6
+ "cleaning": {
7
+ "PRENOM": {
8
+ "LIENS_HABITANTS": [
9
+ {
10
+ "shapeFrom": "PRENOM",
11
+ "expression": "nvl(PRENOM, \"\") <> \"\"",
12
+ "isAggregatorUsed": false
13
+ }
14
+ ]
15
+ }
16
+ },
17
+ "resizing": {
18
+ "PRENOM": {
19
+ "size": "count(PRENOM)",
20
+ "variables": ["VERIF"],
21
+ "linksVariables": ["LIENS_HABITANTS"],
22
+ "sizeForLinksVariables": {
23
+ "xAxisSize": "count(PRENOM)",
24
+ "yAxisSize": "count(PRENOM)"
25
+ }
26
+ }
27
+ },
28
+ "variables": [
29
+ {
30
+ "name": "PRENOM",
31
+ "values": { "COLLECTED": [] },
32
+ "dimension": 1,
33
+ "variableType": "COLLECTED",
34
+ "iterationReference": "mkdulmx2"
35
+ },
36
+ {
37
+ "name": "SEXE",
38
+ "values": { "COLLECTED": [] },
39
+ "dimension": 1,
40
+ "variableType": "COLLECTED",
41
+ "iterationReference": "mkdulmx2"
42
+ },
43
+ {
44
+ "name": "LIENS_HABITANTS",
45
+ "values": { "COLLECTED": [[]] },
46
+ "dimension": 2,
47
+ "variableType": "COLLECTED",
48
+ "iterationReference": "mkdulmx2"
49
+ },
50
+ {
51
+ "name": "VERIF",
52
+ "values": { "COLLECTED": [] },
53
+ "dimension": 1,
54
+ "variableType": "COLLECTED",
55
+ "iterationReference": "mkdulmx2"
56
+ },
57
+ {
58
+ "name": "xAxis",
59
+ "shapeFrom": ["PRENOM"],
60
+ "expression": { "type": "VTL", "value": "PRENOM" },
61
+ "variableType": "CALCULATED",
62
+ "bindingDependencies": ["PRENOM"]
63
+ },
64
+ {
65
+ "name": "yAxis",
66
+ "shapeFrom": ["PRENOM"],
67
+ "expression": { "type": "VTL", "value": "PRENOM" },
68
+ "variableType": "CALCULATED",
69
+ "bindingDependencies": ["PRENOM"]
70
+ },
71
+ {
72
+ "name": "FILTER_RESULT_PRENOM",
73
+ "dimension": 1,
74
+ "shapeFrom": ["PRENOM", "SEXE"],
75
+ "expression": { "type": "VTL", "value": "true" },
76
+ "variableType": "CALCULATED",
77
+ "isIgnoredByLunatic": true,
78
+ "iterationReference": "mkdulmx2"
79
+ },
80
+ {
81
+ "name": "FILTER_RESULT_SEXE",
82
+ "dimension": 1,
83
+ "shapeFrom": ["PRENOM", "SEXE"],
84
+ "expression": { "type": "VTL", "value": "true" },
85
+ "variableType": "CALCULATED",
86
+ "isIgnoredByLunatic": true,
87
+ "iterationReference": "mkdulmx2"
88
+ },
89
+ {
90
+ "name": "FILTER_RESULT_LIENS_HABITANTS",
91
+ "dimension": 2,
92
+ "shapeFrom": ["PRENOM", "SEXE"],
93
+ "expression": {
94
+ "type": "VTL",
95
+ "value": "(nvl(xAxis, \"\") <> \"\") and (nvl(yAxis, \"\") <> \"\")"
96
+ },
97
+ "variableType": "CALCULATED",
98
+ "isIgnoredByLunatic": true,
99
+ "iterationReference": "mkdulmx2"
100
+ },
101
+ {
102
+ "name": "FILTER_RESULT_VERIF",
103
+ "dimension": 1,
104
+ "shapeFrom": ["PRENOM", "SEXE"],
105
+ "expression": { "type": "VTL", "value": "true" },
106
+ "variableType": "CALCULATED",
107
+ "isIgnoredByLunatic": true,
108
+ "iterationReference": "mkdulmx2"
109
+ }
110
+ ],
111
+ "components": [
112
+ {
113
+ "id": "mkdulmx2",
114
+ "page": "1",
115
+ "depth": 1,
116
+ "label": { "type": "VTL|MD", "value": "Ajouter un habitant" },
117
+ "lines": {
118
+ "max": { "type": "VTL", "value": "10" },
119
+ "min": { "type": "VTL", "value": "1" }
120
+ },
121
+ "components": [
122
+ {
123
+ "id": "mkdumm9l",
124
+ "page": "1",
125
+ "label": {
126
+ "type": "VTL",
127
+ "value": "\"I - \" || \"Habitants du logement\"",
128
+ "shapeFrom": "PRENOM"
129
+ },
130
+ "componentType": "Sequence",
131
+ "conditionFilter": {
132
+ "type": "VTL",
133
+ "value": "true",
134
+ "shapeFrom": "PRENOM"
135
+ }
136
+ },
137
+ {
138
+ "id": "question-mkduvzxm",
139
+ "page": "1",
140
+ "label": { "type": "VTL|MD", "value": "\"Prénom:\"" },
141
+ "components": [
142
+ {
143
+ "id": "mkduvzxm",
144
+ "page": "1",
145
+ "response": { "name": "PRENOM" },
146
+ "maxLength": 249,
147
+ "isMandatory": false,
148
+ "componentType": "Input"
149
+ }
150
+ ],
151
+ "componentType": "Question",
152
+ "conditionFilter": { "type": "VTL", "value": "true" }
153
+ },
154
+ {
155
+ "id": "question-mkdujzn9",
156
+ "page": "1",
157
+ "label": { "type": "VTL|MD", "value": "\"Sexe:\"" },
158
+ "components": [
159
+ {
160
+ "id": "mkdujzn9",
161
+ "page": "1",
162
+ "options": [
163
+ {
164
+ "label": { "type": "VTL|MD", "value": "\"Homme\"" },
165
+ "value": "1"
166
+ },
167
+ {
168
+ "label": { "type": "VTL|MD", "value": "\"Femme\"" },
169
+ "value": "2"
170
+ }
171
+ ],
172
+ "response": { "name": "SEXE" },
173
+ "isMandatory": false,
174
+ "orientation": "vertical",
175
+ "componentType": "Radio"
176
+ }
177
+ ],
178
+ "componentType": "Question",
179
+ "conditionFilter": { "type": "VTL", "value": "true" }
180
+ }
181
+ ],
182
+ "componentType": "Loop",
183
+ "paginatedLoop": false,
184
+ "conditionFilter": { "type": "VTL", "value": "(true)" }
185
+ },
186
+ {
187
+ "id": "mkdus3wr",
188
+ "page": "2",
189
+ "label": {
190
+ "type": "VTL",
191
+ "value": "\"II - \" || \"Liens entre les habitants du logement\"",
192
+ "shapeFrom": "PRENOM"
193
+ },
194
+ "componentType": "Sequence",
195
+ "conditionFilter": {
196
+ "type": "VTL",
197
+ "value": "true",
198
+ "shapeFrom": "PRENOM"
199
+ }
200
+ },
201
+ {
202
+ "id": "question-mkdv8ihy",
203
+ "page": "3",
204
+ "components": [
205
+ {
206
+ "id": "mkdv8ihy",
207
+ "page": "3",
208
+ "symLinks": {
209
+ "LIENS_HABITANTS": {
210
+ "1": "1",
211
+ "2": "3",
212
+ "3": "2",
213
+ "4": "4",
214
+ "5": "6",
215
+ "6": "5",
216
+ "7": "8",
217
+ "8": "7",
218
+ "9": "10",
219
+ "10": "9",
220
+ "11": "13",
221
+ "12": "12",
222
+ "13": "11",
223
+ "14": null,
224
+ "15": "15",
225
+ "16": "16",
226
+ "17": "17",
227
+ "18": "18"
228
+ }
229
+ },
230
+ "components": [
231
+ {
232
+ "id": "mkdv8ihy-pairwise-dropdown",
233
+ "page": "3",
234
+ "label": {
235
+ "type": "VTL|MD",
236
+ "value": "\"Qui est \" || yAxis || \" pour \" || xAxis || \" ?\""
237
+ },
238
+ "options": [
239
+ {
240
+ "label": { "type": "VTL", "value": "\"Conjoint\"" },
241
+ "value": "1"
242
+ },
243
+ {
244
+ "label": { "type": "VTL", "value": "\"Parent\"" },
245
+ "value": "2"
246
+ },
247
+ {
248
+ "label": { "type": "VTL", "value": "\"Enfant\"" },
249
+ "value": "3"
250
+ },
251
+ {
252
+ "label": { "type": "VTL", "value": "\"Autre\"" },
253
+ "value": "4"
254
+ }
255
+ ],
256
+ "response": { "name": "LIENS_HABITANTS" },
257
+ "isMandatory": false,
258
+ "componentType": "Dropdown",
259
+ "conditionFilter": {
260
+ "type": "VTL",
261
+ "value": "(nvl(xAxis, \"\") <> \"\") and (nvl(yAxis, \"\") <> \"\")"
262
+ }
263
+ }
264
+ ],
265
+ "sourceVariables": {
266
+ "name": "PRENOM",
267
+ "gender": "SEXE"
268
+ },
269
+ "componentType": "PairwiseLinks",
270
+ "xAxisIterations": { "type": "VTL", "value": "count(PRENOM)" },
271
+ "yAxisIterations": { "type": "VTL", "value": "count(PRENOM)" }
272
+ }
273
+ ],
274
+ "componentType": "Question",
275
+ "conditionFilter": { "type": "VTL", "value": "true" }
276
+ },
277
+ {
278
+ "id": "mkduz03e",
279
+ "page": "4",
280
+ "depth": 1,
281
+ "maxPage": "2",
282
+ "components": [
283
+ {
284
+ "id": "mkdusamd",
285
+ "page": "4.1",
286
+ "label": {
287
+ "type": "VTL",
288
+ "value": "\"III - \" || \"Variables globales\"",
289
+ "shapeFrom": "PRENOM"
290
+ },
291
+ "componentType": "Sequence",
292
+ "conditionFilter": {
293
+ "type": "VTL",
294
+ "value": "true",
295
+ "shapeFrom": "PRENOM"
296
+ }
297
+ },
298
+ {
299
+ "id": "question-mkdvcykn",
300
+ "page": "4.2",
301
+ "label": {
302
+ "type": "VTL|MD",
303
+ "value": "PRENOM || \": votre premier parent est \" || GLOBAL_PARENT1_PRENOM || \" (\" || GLOBAL_PARENT1_SEXE || \"), votre second parent est \" || GLOBAL_PARENT2_PRENOM || \" (\" || GLOBAL_PARENT2_SEXE || \"), votre partenaire est \" || GLOBAL_CONJOINT_PRENOM || \", vos enfants sont \" || GLOBAL_ENFANTS_PRENOMS"
304
+ },
305
+ "components": [
306
+ {
307
+ "id": "mkdvcykn",
308
+ "page": "4.2",
309
+ "response": { "name": "VERIF" },
310
+ "isMandatory": false,
311
+ "componentType": "CheckboxBoolean"
312
+ }
313
+ ],
314
+ "componentType": "Question",
315
+ "conditionFilter": { "type": "VTL", "value": "true" }
316
+ }
317
+ ],
318
+ "iterations": { "type": "VTL", "value": "count(PRENOM)" },
319
+ "componentType": "Loop",
320
+ "paginatedLoop": true,
321
+ "conditionFilter": { "type": "VTL", "value": "(true)" },
322
+ "loopDependencies": ["PRENOM"]
323
+ },
324
+ {
325
+ "id": "mkdvgmn0",
326
+ "page": "5",
327
+ "label": { "type": "VTL", "value": "\"IV - \" || \"Fin\"" },
328
+ "componentType": "Sequence",
329
+ "conditionFilter": { "type": "VTL", "value": "true" }
330
+ }
331
+ ],
332
+ "pagination": "question",
333
+ "componentType": "Questionnaire",
334
+ "enoCoreVersion": "3.59.0",
335
+ "generatingDate": "14-01-2026 10:14:03",
336
+ "lunaticModelVersion": "5.11.0"
337
+ }
@@ -223,6 +223,15 @@ export type ComponentPairWiseLinksDefinition = ComponentDefinitionBase & {
223
223
  [k: string]: string | null;
224
224
  };
225
225
  };
226
+ sourceVariables?: {
227
+ /** Name of the variable containing the name of the respondent */
228
+ name?: string;
229
+ /**
230
+ * Name of the variable containing the gender of the respondent
231
+ * (value of variable -> 1:male, 2: female)
232
+ */
233
+ gender?: string;
234
+ };
226
235
  components: ComponentDefinition[];
227
236
  };
228
237
  export type ComponentSummaryDefinition = ComponentDefinitionBase & {
@@ -1,59 +1,27 @@
1
1
  import type {
2
- LunaticComponentDefinition,
3
2
  LunaticControl,
4
3
  LunaticError,
5
4
  LunaticReducerState,
6
5
  } from '../type';
7
- import {
8
- fillComponentExpressions,
9
- type DeepTranslateExpression,
10
- } from './fill-components/fill-component-expressions';
6
+ import { fillComponentExpressions } from './fill-components/fill-component-expressions';
11
7
  import { checkRoundaboutControl } from '../reducer/controls/check-roundabout-control';
12
8
  import { checkBaseControl } from '../reducer/controls/check-base-control';
13
9
  import { getComponentsFromState } from './get-components-from-state';
10
+ import {
11
+ InterpretedLoopComponent,
12
+ InterpretedRoundaboutComponent,
13
+ isLoopComponent,
14
+ isQuestionComponent,
15
+ isRoundaboutComponent,
16
+ type ComponentDefinition,
17
+ type InterpretedComponent,
18
+ } from './component';
14
19
 
15
20
  export type StateForControls = Pick<
16
21
  LunaticReducerState,
17
22
  'pager' | 'pages' | 'isInLoop' | 'executeExpression'
18
23
  >;
19
24
 
20
- type ComponentDefinition = LunaticComponentDefinition;
21
- type InterpretedComponent = DeepTranslateExpression<LunaticComponentDefinition>;
22
- type InterpretedLoopComponent = DeepTranslateExpression<
23
- ComponentDefinition & {
24
- componentType: 'Loop' | 'RosterForLoop';
25
- }
26
- >;
27
- type InterpretedRoundaboutComponent = DeepTranslateExpression<
28
- ComponentDefinition & {
29
- componentType: 'Roundabout';
30
- }
31
- >;
32
-
33
- /**
34
- * Check if the component is a Loop or a RosterForLoop
35
- */
36
- const isLoopComponent = (
37
- component: ComponentDefinition | InterpretedComponent
38
- ): component is InterpretedLoopComponent => {
39
- return ['Loop', 'RosterForLoop'].includes(component.componentType);
40
- };
41
-
42
- /**
43
- * Check if the component is a Roundabout
44
- */
45
- const isRoundaboutComponent = (
46
- component: ComponentDefinition | InterpretedComponent
47
- ): component is InterpretedRoundaboutComponent => {
48
- return component.componentType === 'Roundabout';
49
- };
50
-
51
- const isQuestionComponent = (
52
- component: ComponentDefinition | InterpretedComponent
53
- ) => {
54
- return 'Question' === component.componentType;
55
- };
56
-
57
25
  /**
58
26
  * Check if components of the current page have errors, and return a map of
59
27
  * errors (indexed by component ID).
@@ -1,6 +1,35 @@
1
+ /*
2
+ Various utils function about what a component is or is not.
3
+ */
1
4
  import type { ReactNode } from 'react';
2
5
  import type { LunaticComponentDefinition } from '../type';
6
+ import { type DeepTranslateExpression } from './fill-components/fill-component-expressions';
3
7
 
8
+ export type ComponentDefinition = LunaticComponentDefinition;
9
+ export type InterpretedComponent =
10
+ DeepTranslateExpression<LunaticComponentDefinition>;
11
+ export type InterpretedLoopComponent = DeepTranslateExpression<
12
+ ComponentDefinition & {
13
+ componentType: 'Loop' | 'RosterForLoop';
14
+ }
15
+ >;
16
+ export type InterpretedRoundaboutComponent = DeepTranslateExpression<
17
+ ComponentDefinition & {
18
+ componentType: 'Roundabout';
19
+ }
20
+ >;
21
+ export type InterpretedQuestionComponent = DeepTranslateExpression<
22
+ ComponentDefinition & {
23
+ componentType: 'Question';
24
+ }
25
+ >;
26
+ export type InterpretedPairwiseLinksComponent = DeepTranslateExpression<
27
+ ComponentDefinition & {
28
+ componentType: 'PairwiseLinks';
29
+ }
30
+ >;
31
+
32
+ /** Whether the component has a response attribute. */
4
33
  export function hasResponse(
5
34
  component: unknown
6
35
  ): component is { response: { name: string } } {
@@ -12,6 +41,7 @@ export function hasResponse(
12
41
  );
13
42
  }
14
43
 
44
+ /** Whether the component has a responses attribute. */
15
45
  export function hasResponses(component: unknown): component is {
16
46
  responses?: Array<{
17
47
  label: ReactNode;
@@ -24,6 +54,7 @@ export function hasResponses(component: unknown): component is {
24
54
  );
25
55
  }
26
56
 
57
+ /** Whether the component has a body attribute. */
27
58
  export function hasBody(component: unknown): component is {
28
59
  body: LunaticComponentDefinition<'Table'>['body'];
29
60
  } {
@@ -35,6 +66,7 @@ export function hasBody(component: unknown): component is {
35
66
  );
36
67
  }
37
68
 
69
+ /** Whether the component has a componentType attribute. */
38
70
  export function hasComponentType(
39
71
  component: unknown
40
72
  ): component is { componentType: string } {
@@ -45,3 +77,50 @@ export function hasComponentType(
45
77
  typeof component.componentType === 'string'
46
78
  );
47
79
  }
80
+
81
+ /** Whether the component is a Loop or a RosterForLoop. */
82
+ export function isLoopComponent(
83
+ component: ComponentDefinition | InterpretedComponent
84
+ ): component is InterpretedLoopComponent {
85
+ return ['Loop', 'RosterForLoop'].includes(component.componentType);
86
+ }
87
+
88
+ /** Whether the component is a Roundabout. */
89
+ export function isRoundaboutComponent(
90
+ component: ComponentDefinition | InterpretedComponent
91
+ ): component is InterpretedRoundaboutComponent {
92
+ return component.componentType === 'Roundabout';
93
+ }
94
+
95
+ /** Whether the component is a Question. */
96
+ export function isQuestionComponent(
97
+ component: ComponentDefinition | InterpretedComponent
98
+ ): component is InterpretedQuestionComponent {
99
+ return component.componentType === 'Question';
100
+ }
101
+
102
+ /** Whether the component is a PairwiseLinks. */
103
+ export function isPairwiseLinksComponent(
104
+ component: ComponentDefinition | InterpretedComponent
105
+ ): component is InterpretedPairwiseLinksComponent {
106
+ return component.componentType === 'PairwiseLinks';
107
+ }
108
+
109
+ /**
110
+ * Get the pairwise component if it exists.
111
+ *
112
+ * There should only be one so we return the first one we find.
113
+ */
114
+ export function getPairwiseComponent(
115
+ components: ComponentDefinition[]
116
+ ): InterpretedPairwiseLinksComponent | undefined {
117
+ for (const component of components) {
118
+ if (isPairwiseLinksComponent(component)) return component;
119
+ if (isQuestionComponent(component)) {
120
+ const childComponent = getPairwiseComponent(component.components);
121
+ if (childComponent) return childComponent;
122
+ }
123
+ }
124
+
125
+ return undefined;
126
+ }
@@ -1,10 +1,8 @@
1
- import type {
2
- IterationLevel,
3
- LunaticVariablesStore,
4
- } from '../lunatic-variables-store';
1
+ import type { LunaticVariablesStore } from '../lunatic-variables-store';
5
2
  import type { LunaticSource } from '../../../type';
6
3
  import { depth, setAtIndex } from '../../../../utils/array';
7
4
  import { castBool } from '../../../../utils/cast';
5
+ import { IterationLevel } from '../models';
8
6
 
9
7
  /**
10
8
  * Implements the cleaning behavior for the variable store.
@@ -0,0 +1,9 @@
1
+ import { IterationLevel } from './models';
2
+
3
+ /** Special variable that will take the current iteration value. */
4
+ export const GLOBAL_ITERATION_INDEX = 'GLOBAL_ITERATION_INDEX';
5
+
6
+ /** Manually compute the global iteration index from current iteration level. */
7
+ export function computeGlobalIterationIndexValue(iteration: IterationLevel) {
8
+ return [GLOBAL_ITERATION_INDEX, iteration[0] + 1];
9
+ }