@inseefr/lunatic 3.6.14 → 3.6.15-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 (46) hide show
  1. package/esm/hooks/useMultiMode.d.ts +49 -0
  2. package/esm/hooks/useMultiMode.js +83 -0
  3. package/esm/hooks/useMultiMode.js.map +1 -0
  4. package/esm/index.d.ts +1 -0
  5. package/esm/index.js +1 -0
  6. package/esm/index.js.map +1 -1
  7. package/esm/type.source.d.ts +55 -1
  8. package/esm/use-lunatic/reducer/reducerInitializer.d.ts +2 -2
  9. package/esm/use-lunatic/reducer/reducerInitializer.js +31 -24
  10. package/esm/use-lunatic/reducer/reducerInitializer.js.map +1 -1
  11. package/esm/use-lunatic/type.d.ts +2 -0
  12. package/esm/use-lunatic/use-lunatic.js +3 -0
  13. package/esm/use-lunatic/use-lunatic.js.map +1 -1
  14. package/esm/utils/getArticulation.d.ts +61 -0
  15. package/esm/utils/getArticulation.js +78 -0
  16. package/esm/utils/getArticulation.js.map +1 -0
  17. package/hooks/useMultiMode.d.ts +49 -0
  18. package/hooks/useMultiMode.js +84 -0
  19. package/hooks/useMultiMode.js.map +1 -0
  20. package/index.d.ts +1 -0
  21. package/index.js +3 -1
  22. package/index.js.map +1 -1
  23. package/package.json +18 -1
  24. package/src/hooks/useMultiMode.ts +102 -0
  25. package/src/index.ts +1 -0
  26. package/src/stories/behaviour/articulation/articulation.stories.tsx +90 -0
  27. package/src/stories/behaviour/articulation/multimode.stories.tsx +19 -0
  28. package/src/stories/behaviour/articulation/roundabout.json +413 -0
  29. package/src/stories/utils/Orchestrator.tsx +3 -0
  30. package/src/stories/utils/OrchestratorSidebar.tsx +25 -1
  31. package/src/type.source.ts +55 -1
  32. package/src/use-lunatic/reducer/reducerInitializer.tsx +40 -29
  33. package/src/use-lunatic/type.ts +2 -0
  34. package/src/use-lunatic/use-lunatic.ts +4 -0
  35. package/src/utils/getArticulation.ts +117 -0
  36. package/tsconfig.build.tsbuildinfo +1 -1
  37. package/type.source.d.ts +55 -1
  38. package/use-lunatic/reducer/reducerInitializer.d.ts +2 -2
  39. package/use-lunatic/reducer/reducerInitializer.js +31 -24
  40. package/use-lunatic/reducer/reducerInitializer.js.map +1 -1
  41. package/use-lunatic/type.d.ts +2 -0
  42. package/use-lunatic/use-lunatic.js +3 -0
  43. package/use-lunatic/use-lunatic.js.map +1 -1
  44. package/utils/getArticulation.d.ts +61 -0
  45. package/utils/getArticulation.js +78 -0
  46. package/utils/getArticulation.js.map +1 -0
@@ -33,6 +33,7 @@ import { useRefSync } from '../hooks/useRefSync';
33
33
  import { ConsoleLogger } from './logger/ConsoleLogger';
34
34
  import { useWarnDepChange } from './hooks/useWarnDepChange';
35
35
  import { useCallbackOnNextRender } from './hooks/useCallbackOnNextRender';
36
+ import { useMultiMode } from '../hooks/useMultiMode';
36
37
 
37
38
  const empty = {}; // Keep the same empty object (to avoid problem with useEffect dependencies)
38
39
  const DEFAULT_DATA = empty as LunaticData;
@@ -198,6 +199,8 @@ export function useLunatic(
198
199
  (variableNames?: string[]) => getData(false, variableNames)
199
200
  );
200
201
 
202
+ const { getMultiMode } = useMultiMode(source, state.variables);
203
+
201
204
  const pageTag = getPageTag(state.pager);
202
205
  const { isFirstPage, isLastPage } = isFirstLastPage(state.pager);
203
206
 
@@ -241,5 +244,6 @@ export function useLunatic(
241
244
  // Components
242
245
  Provider,
243
246
  handleChanges,
247
+ getMultiMode,
244
248
  } satisfies LunaticState;
245
249
  }
@@ -0,0 +1,117 @@
1
+ import type {
2
+ ComponentDefinition,
3
+ ComponentRoundaboutDefinition,
4
+ LunaticSource,
5
+ } from '../type.source';
6
+ import type { LunaticData, PageTag } from '../use-lunatic/type';
7
+ import { reducerInitializer } from '../use-lunatic/reducer/reducerInitializer';
8
+ import { type ReactNode } from 'react';
9
+ import { times } from './array';
10
+ import { forceInt } from './number';
11
+
12
+ type ArticulationItem = {
13
+ label: string;
14
+ value: string;
15
+ };
16
+
17
+ type Articulation = {
18
+ source: string;
19
+ items: ArticulationItem[];
20
+ };
21
+
22
+ type Item = {
23
+ cells: {
24
+ label: string;
25
+ value: ReactNode;
26
+ }[];
27
+ progress: number; // -1: not completed, 0: started, 1: finished
28
+ page: PageTag;
29
+ };
30
+
31
+ /**
32
+ * Retrieve the articulation state
33
+ *
34
+ * ## Why this hook
35
+ *
36
+ * The goal of this hook is to provide insights about a roundabout using extra information inserted in the JSON source
37
+ * provided to Lunatic.
38
+ *
39
+ * For instance
40
+ *
41
+ * ```
42
+ * "articulation": {
43
+ * "source": "roundabout",
44
+ * "items": [
45
+ * {
46
+ * "label": "Prénom",
47
+ * "value": "PRENOMS"
48
+ * },
49
+ * {
50
+ * "label": "Sexe",
51
+ * "value": "if SEXE = \"H\" then \"Homme\" else \"Femme\""
52
+ * },
53
+ * {
54
+ * "label": "Age",
55
+ * "value": "cast(AGE, string) || \" ans\""
56
+ * }
57
+ * ]
58
+ * },
59
+ * ```
60
+ *
61
+ * - source is the ID of the roundabout component
62
+ * - items define the field to extract from the roundabout data
63
+ */
64
+ export function getArticulation(
65
+ source: LunaticSource & { articulation: Articulation },
66
+ data: LunaticData
67
+ ): { items: Item[] } {
68
+ const roundabout = findComponentById(
69
+ source.components,
70
+ source.articulation.source
71
+ );
72
+ const { variables } = reducerInitializer({ source, data });
73
+ const iterations = forceInt(
74
+ variables.run(roundabout?.iterations.value ?? '0')
75
+ );
76
+
77
+ const rows = times(iterations, (k) =>
78
+ source.articulation.items.map((item) => ({
79
+ label: item.label,
80
+ value: variables.run(item.value, { iteration: [k] }) as ReactNode,
81
+ }))
82
+ );
83
+
84
+ if (!roundabout) {
85
+ return {
86
+ items: [],
87
+ };
88
+ }
89
+
90
+ return {
91
+ items: rows.map((row, k) => ({
92
+ cells: row,
93
+ progress: forceInt(variables.get(roundabout.progressVariable, [k]) ?? -1),
94
+ page: (roundabout.page
95
+ ? `${roundabout.page}.1#${k + 1}`
96
+ : '1') as PageTag,
97
+ })),
98
+ };
99
+ }
100
+
101
+ export function findComponentById(
102
+ components: ComponentDefinition[],
103
+ id: string
104
+ ): (ComponentRoundaboutDefinition & { page?: string }) | null {
105
+ for (const c of components) {
106
+ if ('id' in c && c.id === id && c.componentType === 'Roundabout') {
107
+ return c;
108
+ }
109
+ if ('components' in c) {
110
+ const child = findComponentById(c.components, id);
111
+ if (child) {
112
+ return child;
113
+ }
114
+ }
115
+ }
116
+ return null;
117
+ }