@inseefr/lunatic 3.4.10-rc.1 → 3.4.11-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 (140) hide show
  1. package/README.md +6 -4
  2. package/components/Loop/Loop.js +27 -7
  3. package/components/Loop/Loop.js.map +1 -1
  4. package/components/LunaticComponents.d.ts +10 -1
  5. package/components/LunaticComponents.js +3 -1
  6. package/components/LunaticComponents.js.map +1 -1
  7. package/components/RosterForLoop/RosterForLoop.js +37 -8
  8. package/components/RosterForLoop/RosterForLoop.js.map +1 -1
  9. package/components/Sequence/Sequence.d.ts +1 -1
  10. package/components/Subsequence/Subsequence.d.ts +1 -1
  11. package/components/library.d.ts +2 -2
  12. package/components/shared/HOC/slottableComponent.d.ts +3 -3
  13. package/components/shared/HOC/slottableComponent.js +2 -2
  14. package/esm/components/Loop/Loop.js +27 -7
  15. package/esm/components/Loop/Loop.js.map +1 -1
  16. package/esm/components/LunaticComponents.d.ts +10 -1
  17. package/esm/components/LunaticComponents.js +3 -1
  18. package/esm/components/LunaticComponents.js.map +1 -1
  19. package/esm/components/RosterForLoop/RosterForLoop.js +34 -8
  20. package/esm/components/RosterForLoop/RosterForLoop.js.map +1 -1
  21. package/esm/components/Sequence/Sequence.d.ts +1 -1
  22. package/esm/components/Subsequence/Subsequence.d.ts +1 -1
  23. package/esm/components/library.d.ts +2 -2
  24. package/esm/components/shared/HOC/slottableComponent.d.ts +3 -3
  25. package/esm/components/shared/HOC/slottableComponent.js +2 -2
  26. package/esm/i18n/dictionary.d.ts +8 -0
  27. package/esm/i18n/dictionary.js +5 -0
  28. package/esm/i18n/dictionary.js.map +1 -1
  29. package/esm/i18n/index.d.ts +1 -1
  30. package/esm/type.source.js +0 -1
  31. package/esm/type.source.js.map +1 -1
  32. package/esm/use-lunatic/commons/compile-controls.d.ts +1 -1
  33. package/esm/use-lunatic/commons/compile-controls.js +4 -3
  34. package/esm/use-lunatic/commons/compile-controls.js.map +1 -1
  35. package/esm/use-lunatic/commons/variables/behaviours/resizing-behaviour.js +23 -7
  36. package/esm/use-lunatic/commons/variables/behaviours/resizing-behaviour.js.map +1 -1
  37. package/esm/use-lunatic/commons/variables/lunatic-variables-store.d.ts +19 -1
  38. package/esm/use-lunatic/commons/variables/lunatic-variables-store.js +6 -6
  39. package/esm/use-lunatic/commons/variables/lunatic-variables-store.js.map +1 -1
  40. package/esm/use-lunatic/commons/variables/lunatic-variables-store.spec.js +66 -1
  41. package/esm/use-lunatic/commons/variables/lunatic-variables-store.spec.js.map +1 -1
  42. package/esm/use-lunatic/hooks/use-loop-variables.d.ts +1 -1
  43. package/esm/use-lunatic/hooks/use-loop-variables.js +1 -1
  44. package/esm/use-lunatic/hooks/use-page-has-response.d.ts +1 -1
  45. package/esm/use-lunatic/hooks/use-page-has-response.js +6 -6
  46. package/esm/use-lunatic/hooks/useOverview.d.ts +1 -1
  47. package/esm/use-lunatic/hooks/useOverview.js +4 -4
  48. package/esm/use-lunatic/hooks/useWarnDepChange.d.ts +3 -2
  49. package/esm/use-lunatic/hooks/useWarnDepChange.js +3 -2
  50. package/esm/use-lunatic/hooks/useWarnDepChange.js.map +1 -1
  51. package/esm/use-lunatic/lunatic-context.d.ts +5 -2
  52. package/esm/use-lunatic/lunatic-context.js +5 -2
  53. package/esm/use-lunatic/lunatic-context.js.map +1 -1
  54. package/esm/use-lunatic/props/getComponentTypeProps.d.ts +4 -4
  55. package/esm/use-lunatic/reducer/commons/index.d.ts +0 -1
  56. package/esm/use-lunatic/reducer/commons/index.js +0 -1
  57. package/esm/use-lunatic/reducer/commons/index.js.map +1 -1
  58. package/esm/use-lunatic/type.d.ts +153 -2
  59. package/esm/use-lunatic/use-lunatic.d.ts +13 -36
  60. package/esm/use-lunatic/use-lunatic.js +13 -2
  61. package/esm/use-lunatic/use-lunatic.js.map +1 -1
  62. package/esm/utils/array.d.ts +4 -0
  63. package/esm/utils/array.js +15 -2
  64. package/esm/utils/array.js.map +1 -1
  65. package/esm/utils/array.spec.js +12 -1
  66. package/esm/utils/array.spec.js.map +1 -1
  67. package/i18n/dictionary.d.ts +8 -0
  68. package/i18n/dictionary.js +5 -0
  69. package/i18n/dictionary.js.map +1 -1
  70. package/i18n/index.d.ts +1 -1
  71. package/package.json +1 -8
  72. package/src/components/Loop/Loop.tsx +42 -12
  73. package/src/components/LunaticComponents.tsx +10 -8
  74. package/src/components/RosterForLoop/RosterForLoop.tsx +42 -2
  75. package/src/components/RosterForLoop/__snapshots__/RosterForLoop.spec.tsx.snap +18 -0
  76. package/src/components/shared/HOC/slottableComponent.tsx +3 -3
  77. package/src/i18n/dictionary.ts +5 -0
  78. package/src/stories/pairwise/data.json +1 -1
  79. package/src/stories/pairwise/source.json +3 -1
  80. package/src/type.source.ts +0 -1
  81. package/src/use-lunatic/__snapshots__/use-lunatic.test.ts.snap +0 -323
  82. package/src/use-lunatic/commons/compile-controls.ts +4 -3
  83. package/src/use-lunatic/commons/variables/behaviours/resizing-behaviour.ts +35 -10
  84. package/src/use-lunatic/commons/variables/lunatic-variables-store.spec.ts +68 -1
  85. package/src/use-lunatic/commons/variables/lunatic-variables-store.ts +21 -19
  86. package/src/use-lunatic/hooks/use-loop-variables.ts +1 -1
  87. package/src/use-lunatic/hooks/use-page-has-response.ts +6 -6
  88. package/src/use-lunatic/hooks/useOverview.ts +4 -4
  89. package/src/use-lunatic/hooks/useWarnDepChange.ts +3 -2
  90. package/src/use-lunatic/lunatic-context.tsx +5 -2
  91. package/src/use-lunatic/reducer/commons/index.ts +0 -1
  92. package/src/use-lunatic/type.ts +154 -17
  93. package/src/use-lunatic/use-lunatic.ts +11 -2
  94. package/src/utils/array.spec.ts +18 -1
  95. package/src/utils/array.ts +21 -3
  96. package/tsconfig.build.tsbuildinfo +1 -1
  97. package/type.source.js +0 -1
  98. package/type.source.js.map +1 -1
  99. package/use-lunatic/commons/compile-controls.d.ts +1 -1
  100. package/use-lunatic/commons/compile-controls.js +4 -3
  101. package/use-lunatic/commons/compile-controls.js.map +1 -1
  102. package/use-lunatic/commons/variables/behaviours/resizing-behaviour.js +22 -6
  103. package/use-lunatic/commons/variables/behaviours/resizing-behaviour.js.map +1 -1
  104. package/use-lunatic/commons/variables/lunatic-variables-store.d.ts +19 -1
  105. package/use-lunatic/commons/variables/lunatic-variables-store.js +13 -13
  106. package/use-lunatic/commons/variables/lunatic-variables-store.js.map +1 -1
  107. package/use-lunatic/commons/variables/lunatic-variables-store.spec.js +66 -1
  108. package/use-lunatic/commons/variables/lunatic-variables-store.spec.js.map +1 -1
  109. package/use-lunatic/hooks/use-loop-variables.d.ts +1 -1
  110. package/use-lunatic/hooks/use-loop-variables.js +1 -1
  111. package/use-lunatic/hooks/use-page-has-response.d.ts +1 -1
  112. package/use-lunatic/hooks/use-page-has-response.js +6 -6
  113. package/use-lunatic/hooks/useOverview.d.ts +1 -1
  114. package/use-lunatic/hooks/useOverview.js +4 -4
  115. package/use-lunatic/hooks/useWarnDepChange.d.ts +3 -2
  116. package/use-lunatic/hooks/useWarnDepChange.js +3 -2
  117. package/use-lunatic/hooks/useWarnDepChange.js.map +1 -1
  118. package/use-lunatic/lunatic-context.d.ts +5 -2
  119. package/use-lunatic/lunatic-context.js +5 -2
  120. package/use-lunatic/lunatic-context.js.map +1 -1
  121. package/use-lunatic/props/getComponentTypeProps.d.ts +4 -4
  122. package/use-lunatic/reducer/commons/index.d.ts +0 -1
  123. package/use-lunatic/reducer/commons/index.js +0 -6
  124. package/use-lunatic/reducer/commons/index.js.map +1 -1
  125. package/use-lunatic/type.d.ts +153 -2
  126. package/use-lunatic/use-lunatic.d.ts +13 -36
  127. package/use-lunatic/use-lunatic.js +13 -2
  128. package/use-lunatic/use-lunatic.js.map +1 -1
  129. package/utils/array.d.ts +4 -0
  130. package/utils/array.js +16 -2
  131. package/utils/array.js.map +1 -1
  132. package/utils/array.spec.js +11 -0
  133. package/utils/array.spec.js.map +1 -1
  134. package/esm/use-lunatic/reducer/commons/resize-array-variable.d.ts +0 -5
  135. package/esm/use-lunatic/reducer/commons/resize-array-variable.js +0 -21
  136. package/esm/use-lunatic/reducer/commons/resize-array-variable.js.map +0 -1
  137. package/src/use-lunatic/reducer/commons/resize-array-variable.ts +0 -28
  138. package/use-lunatic/reducer/commons/resize-array-variable.d.ts +0 -5
  139. package/use-lunatic/reducer/commons/resize-array-variable.js +0 -23
  140. package/use-lunatic/reducer/commons/resize-array-variable.js.map +0 -1
@@ -1855,329 +1855,6 @@ exports[`use-lunatic() > overview > with loop > should handle initialPage 1`] =
1855
1855
  ]
1856
1856
  `;
1857
1857
 
1858
- exports[`use-lunatic() > overview > with loop > should handle lastReachedPage 1`] = `
1859
- [
1860
- {
1861
- "children": [
1862
- {
1863
- "children": [],
1864
- "current": false,
1865
- "description": undefined,
1866
- "id": "lujqeci5",
1867
- "label": <MDLabel
1868
- expression="Votre santé"
1869
- />,
1870
- "page": "2",
1871
- "reached": true,
1872
- "type": "Subsequence",
1873
- },
1874
- {
1875
- "children": [],
1876
- "current": false,
1877
- "description": undefined,
1878
- "id": "lujqbyzl",
1879
- "label": <MDLabel
1880
- expression="Votre logement"
1881
- />,
1882
- "page": "3",
1883
- "reached": true,
1884
- "type": "Subsequence",
1885
- },
1886
- ],
1887
- "current": true,
1888
- "description": undefined,
1889
- "id": "lujqfpva",
1890
- "label": <MDLabel
1891
- expression="I - Séquence 1"
1892
- />,
1893
- "page": "1",
1894
- "reached": true,
1895
- "type": "Sequence",
1896
- },
1897
- {
1898
- "children": [
1899
- {
1900
- "children": [],
1901
- "current": false,
1902
- "description": undefined,
1903
- "id": "lulbmyhr",
1904
- "label": <MDLabel
1905
- expression="Commentaire sur composition du logement"
1906
- />,
1907
- "page": "8",
1908
- "reached": true,
1909
- "type": "Subsequence",
1910
- },
1911
- ],
1912
- "current": false,
1913
- "description": undefined,
1914
- "id": "lujqrqmp",
1915
- "label": <MDLabel
1916
- expression="II - Habitants du logement"
1917
- />,
1918
- "page": "5",
1919
- "reached": true,
1920
- "type": "Sequence",
1921
- },
1922
- {
1923
- "children": [
1924
- {
1925
- "children": [],
1926
- "current": false,
1927
- "description": undefined,
1928
- "id": "lujykwaz",
1929
- "label": <MDLabel
1930
- expression="Caractéristiques de Quentin"
1931
- />,
1932
- "page": "10.1#1",
1933
- "reached": true,
1934
- "type": "Subsequence",
1935
- },
1936
- {
1937
- "children": [],
1938
- "current": false,
1939
- "description": undefined,
1940
- "id": "lujykwaz",
1941
- "label": <MDLabel
1942
- expression="Caractéristiques de Luna"
1943
- />,
1944
- "page": "10.1#2",
1945
- "reached": true,
1946
- "type": "Subsequence",
1947
- },
1948
- {
1949
- "children": [],
1950
- "current": false,
1951
- "description": undefined,
1952
- "id": "lujykwaz",
1953
- "label": <MDLabel
1954
- expression="Caractéristiques de Paul"
1955
- />,
1956
- "page": "10.1#3",
1957
- "reached": true,
1958
- "type": "Subsequence",
1959
- },
1960
- {
1961
- "children": [],
1962
- "current": false,
1963
- "description": undefined,
1964
- "id": "lujyik5q",
1965
- "label": <MDLabel
1966
- expression="Autres caractéristiques de Luna : filtrée pour le premier individu"
1967
- />,
1968
- "page": "11.1#2",
1969
- "reached": true,
1970
- "type": "Subsequence",
1971
- },
1972
- {
1973
- "children": [],
1974
- "current": false,
1975
- "description": undefined,
1976
- "id": "luk0swcz",
1977
- "label": <MDLabel
1978
- expression="Encore d'autres caractéristiques de Luna : filtrée pour le premier individu"
1979
- />,
1980
- "page": "11.2#2",
1981
- "reached": true,
1982
- "type": "Subsequence",
1983
- },
1984
- {
1985
- "children": [],
1986
- "current": false,
1987
- "description": undefined,
1988
- "id": "lujyik5q",
1989
- "label": <MDLabel
1990
- expression="Autres caractéristiques de Paul : filtrée pour le premier individu"
1991
- />,
1992
- "page": "11.1#3",
1993
- "reached": false,
1994
- "type": "Subsequence",
1995
- },
1996
- {
1997
- "children": [],
1998
- "current": false,
1999
- "description": undefined,
2000
- "id": "luk0swcz",
2001
- "label": <MDLabel
2002
- expression="Encore d'autres caractéristiques de Paul : filtrée pour le premier individu"
2003
- />,
2004
- "page": "11.2#3",
2005
- "reached": false,
2006
- "type": "Subsequence",
2007
- },
2008
- ],
2009
- "current": false,
2010
- "description": undefined,
2011
- "id": "lujyi4pe",
2012
- "label": <MDLabel
2013
- expression="III - Détail des individus"
2014
- />,
2015
- "page": "9",
2016
- "reached": true,
2017
- "type": "Sequence",
2018
- },
2019
- {
2020
- "children": [
2021
- {
2022
- "children": [],
2023
- "current": false,
2024
- "description": undefined,
2025
- "id": "lumfc98o",
2026
- "label": <MDLabel
2027
- expression="Belle sous-séquence pour Quentin"
2028
- />,
2029
- "page": "12.2#1",
2030
- "reached": false,
2031
- "type": "Subsequence",
2032
- },
2033
- {
2034
- "children": [],
2035
- "current": false,
2036
- "description": undefined,
2037
- "id": "lumfe3bj",
2038
- "label": <MDLabel
2039
- expression="Autre belle sous-seq"
2040
- />,
2041
- "page": "12.3#1",
2042
- "reached": false,
2043
- "type": "Subsequence",
2044
- },
2045
- ],
2046
- "current": false,
2047
- "description": undefined,
2048
- "id": "luk1ojt5",
2049
- "label": <MDLabel
2050
- expression="IV - Belle séquence pour Quentin"
2051
- />,
2052
- "page": "12.1#1",
2053
- "reached": false,
2054
- "type": "Sequence",
2055
- },
2056
- {
2057
- "children": [],
2058
- "current": false,
2059
- "description": undefined,
2060
- "id": "lulbelgr",
2061
- "label": <MDLabel
2062
- expression="V - Autre séquence pour Quentin"
2063
- />,
2064
- "page": "12.4#1",
2065
- "reached": false,
2066
- "type": "Sequence",
2067
- },
2068
- {
2069
- "children": [
2070
- {
2071
- "children": [],
2072
- "current": false,
2073
- "description": undefined,
2074
- "id": "lumfc98o",
2075
- "label": <MDLabel
2076
- expression="Belle sous-séquence pour Luna"
2077
- />,
2078
- "page": "12.2#2",
2079
- "reached": false,
2080
- "type": "Subsequence",
2081
- },
2082
- {
2083
- "children": [],
2084
- "current": false,
2085
- "description": undefined,
2086
- "id": "lumfe3bj",
2087
- "label": <MDLabel
2088
- expression="Autre belle sous-seq"
2089
- />,
2090
- "page": "12.3#2",
2091
- "reached": false,
2092
- "type": "Subsequence",
2093
- },
2094
- ],
2095
- "current": false,
2096
- "description": undefined,
2097
- "id": "luk1ojt5",
2098
- "label": <MDLabel
2099
- expression="IV - Belle séquence pour Luna"
2100
- />,
2101
- "page": "12.1#2",
2102
- "reached": false,
2103
- "type": "Sequence",
2104
- },
2105
- {
2106
- "children": [],
2107
- "current": false,
2108
- "description": undefined,
2109
- "id": "lulbelgr",
2110
- "label": <MDLabel
2111
- expression="V - Autre séquence pour Luna"
2112
- />,
2113
- "page": "12.4#2",
2114
- "reached": false,
2115
- "type": "Sequence",
2116
- },
2117
- {
2118
- "children": [
2119
- {
2120
- "children": [],
2121
- "current": false,
2122
- "description": undefined,
2123
- "id": "lumfc98o",
2124
- "label": <MDLabel
2125
- expression="Belle sous-séquence pour Paul"
2126
- />,
2127
- "page": "12.2#3",
2128
- "reached": false,
2129
- "type": "Subsequence",
2130
- },
2131
- {
2132
- "children": [],
2133
- "current": false,
2134
- "description": undefined,
2135
- "id": "lumfe3bj",
2136
- "label": <MDLabel
2137
- expression="Autre belle sous-seq"
2138
- />,
2139
- "page": "12.3#3",
2140
- "reached": false,
2141
- "type": "Subsequence",
2142
- },
2143
- ],
2144
- "current": false,
2145
- "description": undefined,
2146
- "id": "luk1ojt5",
2147
- "label": <MDLabel
2148
- expression="IV - Belle séquence pour Paul"
2149
- />,
2150
- "page": "12.1#3",
2151
- "reached": false,
2152
- "type": "Sequence",
2153
- },
2154
- {
2155
- "children": [],
2156
- "current": false,
2157
- "description": undefined,
2158
- "id": "lulbelgr",
2159
- "label": <MDLabel
2160
- expression="V - Autre séquence pour Paul"
2161
- />,
2162
- "page": "12.4#3",
2163
- "reached": false,
2164
- "type": "Sequence",
2165
- },
2166
- {
2167
- "children": [],
2168
- "current": false,
2169
- "description": undefined,
2170
- "id": "COMMENT-SEQ",
2171
- "label": <MDLabel
2172
- expression="Commentaire"
2173
- />,
2174
- "page": "13",
2175
- "reached": false,
2176
- "type": "Sequence",
2177
- },
2178
- ]
2179
- `;
2180
-
2181
1858
  exports[`use-lunatic() > overview > with loop > should work with loop 1`] = `
2182
1859
  [
2183
1860
  {
@@ -35,7 +35,8 @@ const isLoopComponent = (
35
35
  };
36
36
 
37
37
  /**
38
- * Check if components of the current page have errors, and return a map of error (indexed by component ID)
38
+ * Check if components of the current page have errors, and return a map of
39
+ * errors (indexed by component ID).
39
40
  */
40
41
  function checkComponents(
41
42
  state: StateForControls,
@@ -93,7 +94,7 @@ function checkControls(
93
94
  }
94
95
 
95
96
  /**
96
- * Figure out the number of iterations of a component
97
+ * Figure out the number of iterations of a component.
97
98
  */
98
99
  function computeIterations(
99
100
  component: InterpretedComponent | ComponentDefinition,
@@ -210,7 +211,7 @@ function hasCriticalError(errors?: Record<string, LunaticError[]>): boolean {
210
211
  }
211
212
 
212
213
  /**
213
- * Check controls for currently visible components and output errors
214
+ * Check controls for currently visible components and output errors.
214
215
  */
215
216
  export function compileControls(state: StateForControls) {
216
217
  const components = replaceComponentSequence(getComponentsFromState(state));
@@ -1,9 +1,8 @@
1
1
  import type { LunaticVariablesStore } from '../lunatic-variables-store';
2
2
  import type { LunaticSource } from '../../../type';
3
3
  import { forceInt } from '../../../../utils/number';
4
- import { resizeArrayVariable } from '../../../reducer/commons';
5
4
  import { getExpressionAsString } from '../../../../utils/vtl';
6
- import { resizeArray } from '../../../../utils/array';
5
+ import { resizeArray, resizeDownArrayWithIndex } from '../../../../utils/array';
7
6
 
8
7
  /**
9
8
  * Resizing behaviour for the store
@@ -42,8 +41,20 @@ export function resizingBehaviour(
42
41
  const newSize = forceInt(store.run(resizingInfo.size));
43
42
  for (const variableName of resizingInfo.variables) {
44
43
  const value = store.get(variableName);
45
- if (!Array.isArray(value) || value.length !== newSize) {
46
- store.set(variableName, resizeArrayVariable(value, newSize, null), {
44
+ if (Array.isArray(value) && e.detail.removedIndex) {
45
+ store.set(
46
+ variableName,
47
+ resizeDownArrayWithIndex(value, e.detail.removedIndex),
48
+ {
49
+ cause: 'resizing',
50
+ }
51
+ );
52
+ }
53
+ if (
54
+ !e.detail.removedIndex &&
55
+ (!Array.isArray(value) || value.length !== newSize)
56
+ ) {
57
+ store.set(variableName, resizeArray(value, newSize, null), {
47
58
  cause: 'resizing',
48
59
  });
49
60
  }
@@ -61,6 +72,7 @@ function resizePairwise(
61
72
  },
62
73
  args: {
63
74
  iteration?: number[];
75
+ removedIndex?: number;
64
76
  }
65
77
  ) {
66
78
  // Handle expression being sent as an array or an object (ensure backward compatibility)
@@ -78,12 +90,25 @@ function resizePairwise(
78
90
  });
79
91
  resizingInfo.linksVariables.forEach((variable) => {
80
92
  const value = store.get(variable, args.iteration);
81
- const resizedValue = resizeArray(
82
- // The value is not an array, force an array
83
- Array.isArray(value) ? value.map((i) => resizeArray(i, ySize, null)) : [],
84
- xSize,
85
- new Array(ySize).fill(null)
86
- );
93
+ let resizedValue;
94
+ if (args.removedIndex) {
95
+ const removedIndex = args.removedIndex;
96
+ resizedValue = resizeDownArrayWithIndex(
97
+ Array.isArray(value)
98
+ ? value.map((i) => resizeDownArrayWithIndex(i, removedIndex))
99
+ : [],
100
+ removedIndex
101
+ );
102
+ } else {
103
+ resizedValue = resizeArray(
104
+ // The value is not an array, force an array
105
+ Array.isArray(value)
106
+ ? value.map((i) => resizeArray(i, ySize, null))
107
+ : [],
108
+ xSize,
109
+ new Array(ySize).fill(null)
110
+ );
111
+ }
87
112
  store.set(variable, resizedValue);
88
113
  });
89
114
  }
@@ -281,6 +281,28 @@ describe('lunatic-variables-store', () => {
281
281
  cause: 'resizing',
282
282
  });
283
283
  });
284
+
285
+ it('should resize variables with Index', () => {
286
+ variables.set('PRENOM', ['John', 'Jane', 'Marc']);
287
+ variables.set('AGE', [20, 30, 40]);
288
+ const spy = vi.fn();
289
+ variables.on('change', (e) => spy(e.detail));
290
+ resizingBehaviour(variables, {
291
+ PRENOM: {
292
+ size: 'count(PRENOM)',
293
+ variables: ['AGE'],
294
+ },
295
+ });
296
+ variables.set('PRENOM', ['John', 'Marc'], { removedIndex: 1 });
297
+ expect((variables.get('PRENOM') as string[]).length).toEqual(2);
298
+ expect((variables.get('AGE') as string[]).length).toEqual(2);
299
+ expect(spy).toHaveBeenLastCalledWith({
300
+ name: 'AGE',
301
+ value: [20, 40],
302
+ cause: 'resizing',
303
+ });
304
+ });
305
+
284
306
  it('should resize pairwise with the array syntax', () => {
285
307
  variables.set('PRENOM', []);
286
308
  variables.set('LINKS', [[]]);
@@ -316,7 +338,29 @@ describe('lunatic-variables-store', () => {
316
338
  [null, null, null],
317
339
  ]);
318
340
  });
319
- it('should handle both pairwise and normal resize', () => {
341
+ it('should resize pairwise with the object syntax with index', () => {
342
+ variables.set('PRENOM', ['John', 'Jane', 'Marc']);
343
+ variables.set('LINKS', [
344
+ [null, 2, 4],
345
+ [1, null, 2],
346
+ [3, 2, null],
347
+ ]);
348
+ resizingBehaviour(variables, {
349
+ PRENOM: {
350
+ sizeForLinksVariables: {
351
+ xAxisSize: 'count(PRENOM)',
352
+ yAxisSize: 'count(PRENOM)',
353
+ },
354
+ linksVariables: ['LINKS'],
355
+ },
356
+ });
357
+ variables.set('PRENOM', ['John', 'Marc'], { removedIndex: 1 });
358
+ expect(variables.get('LINKS') as string[][]).toEqual([
359
+ [null, 4],
360
+ [3, null],
361
+ ]);
362
+ });
363
+ it('should handle both: pairwise and normal resize', () => {
320
364
  variables.set('PRENOM', []);
321
365
  variables.set('NOM', []);
322
366
  variables.set('LINKS', [[]]);
@@ -336,6 +380,29 @@ describe('lunatic-variables-store', () => {
336
380
  ]);
337
381
  expect(variables.get('NOM') as string[]).toEqual([null, null, null]);
338
382
  });
383
+ it('should handle both: pairwise and normal resize with index', () => {
384
+ variables.set('PRENOM', ['John', 'Jane', 'Marc']);
385
+ variables.set('AGE', [40, 30, 20]);
386
+ variables.set('LINKS', [
387
+ [null, 2, 4],
388
+ [1, null, 2],
389
+ [3, 2, null],
390
+ ]);
391
+ resizingBehaviour(variables, {
392
+ PRENOM: {
393
+ sizeForLinksVariables: ['count(PRENOM)', 'count(PRENOM)'],
394
+ linksVariables: ['LINKS'],
395
+ size: 'count(PRENOM)',
396
+ variables: ['AGE'],
397
+ },
398
+ });
399
+ variables.set('PRENOM', ['John', 'Marc'], { removedIndex: 1 });
400
+ expect(variables.get('LINKS') as string[][]).toEqual([
401
+ [null, 4],
402
+ [3, null],
403
+ ]);
404
+ expect(variables.get('AGE') as string[]).toEqual([40, 20]);
405
+ });
339
406
  });
340
407
 
341
408
  describe('cleaning', () => {
@@ -19,23 +19,25 @@ import {
19
19
  VTLMissingDependency,
20
20
  } from './errors';
21
21
 
22
- // Interpret counter, used for testing purpose
22
+ /** Interpret counter. Used for testing purpose. */
23
23
  let interpretCount = 0;
24
- // Special variable that will take the current iteration value
24
+ /** Special variable that will take the current iteration value. */
25
25
  const iterationVariableName = 'GLOBAL_ITERATION_INDEX';
26
26
 
27
27
  type IterationLevel = number[];
28
28
  export type EventArgs = {
29
29
  change: {
30
- // Name of the changed variable
30
+ /** Name of the changed variable. */
31
31
  name: string;
32
- // New value for the variable
32
+ /** New value for the variable. */
33
33
  value: unknown;
34
- // Iteration changed (for array)
34
+ /** Iteration changed (for array). */
35
35
  iteration?: IterationLevel | undefined;
36
- // What triggered this change
36
+ /** removedIndex: when resize an array directly with only one handleChange (remove one line in tableLoop) */
37
+ removedIndex?: number;
38
+ /** What triggered this change. */
37
39
  cause?: 'resizing' | 'cleaning';
38
- // Extra sent when setting the variable
40
+ /** Extra sent when setting the variable. */
39
41
  [extra: string]: unknown;
40
42
  };
41
43
  };
@@ -123,7 +125,7 @@ export class LunaticVariablesStore {
123
125
  public set(
124
126
  name: string,
125
127
  value: unknown,
126
- args: Pick<EventArgs['change'], 'iteration' | 'cause'> = {}
128
+ args: Pick<EventArgs['change'], 'iteration' | 'cause' | 'removedIndex'> = {}
127
129
  ): LunaticVariable {
128
130
  if (!this.dictionary.has(name)) {
129
131
  this.dictionary.set(
@@ -220,7 +222,7 @@ export class LunaticVariablesStore {
220
222
  this.eventTarget.removeEventListener(eventName, cb as EventListener);
221
223
  }
222
224
 
223
- // Retrieve the number of interpret() run (used in testing only)
225
+ /** Retrieve the number of interpret() run (used in testing only). */
224
226
  get interpretCount() {
225
227
  return interpretCount;
226
228
  }
@@ -249,25 +251,25 @@ export class LunaticVariablesStore {
249
251
  }
250
252
 
251
253
  class LunaticVariable {
252
- // Last time the value was updated (changed)
254
+ /** Last time the value was updated (changed). */
253
255
  public updatedAt = new Map<undefined | string, number>();
254
- // Last time "calculation" was run (for calculated variable)
256
+ /** Last time "calculation" was run (for calculated variable). */
255
257
  private calculatedAt = new Map<undefined | string, number>();
256
- // Internal value for the variable
258
+ /** Internal value for the variable. */
257
259
  private value: unknown;
258
- // List of dependencies, ex: ['FIRSTNAME', 'LASTNAME']
260
+ /** List of dependencies, ex: ['FIRSTNAME', 'LASTNAME']. */
259
261
  private dependencies?: string[];
260
- // Expression for calculated variable
262
+ /** Expression for calculated variable. */
261
263
  public readonly expression?: string;
262
- // Dictionary holding all the available variables
264
+ /** Dictionary holding all the available variables. */
263
265
  private readonly dictionary?: Map<string, LunaticVariable>;
264
- // Specific iteration depth to get value from dependencies (used for yAxis for instance)
266
+ /** Specific iteration depth to get value from dependencies (used for yAxis for instance). */
265
267
  private readonly iterationDepth?: number;
266
- // For calculated variable, shape is copied from another variable
268
+ /** For calculated variable, shape is copied from another variable. */
267
269
  private readonly shapeFrom?: string[];
268
- // Keep a record of variable name (optional, used for debug)
270
+ /** Keep a record of variable name (optional, used for debug). */
269
271
  public readonly name?: string;
270
- // Count the number of calculation
272
+ /** Count the number of calculation. */
271
273
  public calculatedCount = 0;
272
274
 
273
275
  constructor(
@@ -2,7 +2,7 @@ import type { LunaticComponentDefinition, LunaticReducerState } from '../type';
2
2
  import { useMemo } from 'react';
3
3
 
4
4
  /**
5
- * Extract the list of variables used for the current loop
5
+ * Extract the list of variables used for the current loop.
6
6
  */
7
7
  export function useLoopVariables(
8
8
  pager: LunaticReducerState['pager'],
@@ -4,7 +4,7 @@ import type { LunaticComponentDefinition, LunaticReducerState } from '../type';
4
4
  import type { LunaticComponentProps } from '../../components/type';
5
5
 
6
6
  /**
7
- * Check if a page has one response (value is filled for at least one field)
7
+ * Check if a page has one response (value is filled for at least one field).
8
8
  */
9
9
  export function usePageHasResponse(
10
10
  components: LunaticComponentProps[],
@@ -67,10 +67,10 @@ export function usePageHasResponse(
67
67
  }
68
68
 
69
69
  /**
70
- * Check if a value is empty
71
- * - null ou undefined ou ''
72
- * - for arrays, every item must be empty
73
- * - for objects, every value must be empty
70
+ * Check if a value is empty.
71
+ * - `null`, `undefined` or `''`.
72
+ * - for arrays, every item must be empty.
73
+ * - for objects, every value must be empty.
74
74
  */
75
75
  function isEmpty(value: unknown): boolean {
76
76
  // Array is empty if all items are empty
@@ -86,7 +86,7 @@ function isEmpty(value: unknown): boolean {
86
86
  }
87
87
 
88
88
  /**
89
- * For complex component we need to inspect child components, interpret the response value
89
+ * For complex component we need to inspect child components, interpret the response value.
90
90
  */
91
91
  function isSubComponentsEmpty(
92
92
  components: (LunaticComponentProps | LunaticComponentDefinition)[],
@@ -18,7 +18,7 @@ export type InterpretedLunaticOverviewItem = {
18
18
  };
19
19
 
20
20
  /**
21
- * Hook to build a filled overview everytime the deps change
21
+ * Build a filled overview everytime the deps change.
22
22
  */
23
23
  export const useOverview = (
24
24
  {
@@ -36,7 +36,7 @@ export const useOverview = (
36
36
  };
37
37
 
38
38
  /**
39
- * Use lunatic data to interpret the static overview (calculated on init) with the real data
39
+ * Use Lunatic data to interpret the static overview (calculated on init) with the real data.
40
40
  */
41
41
  const interpretOverview = (
42
42
  overviewItems: LunaticOverviewItem[],
@@ -71,7 +71,7 @@ const interpretOverview = (
71
71
  };
72
72
 
73
73
  /**
74
- * Interpret expression inside an item (label & condition)
74
+ * Interpret expression inside an item (label & condition).
75
75
  */
76
76
  const interpretOverviewItem = (
77
77
  items: InterpretedLunaticOverviewItem[],
@@ -127,7 +127,7 @@ const interpretOverviewItem = (
127
127
  };
128
128
 
129
129
  /**
130
- * Set the current property in the correct overview item
130
+ * Set the current property in the correct overview item.
131
131
  */
132
132
  const applyCurrentPage = (
133
133
  items: InterpretedLunaticOverviewItem[],