@inseefr/lunatic 3.6.14 → 3.6.15-rc.1

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 (60) hide show
  1. package/components/Roundabout/Roundabout.js +8 -3
  2. package/components/Roundabout/Roundabout.js.map +1 -1
  3. package/esm/components/Roundabout/Roundabout.js +8 -3
  4. package/esm/components/Roundabout/Roundabout.js.map +1 -1
  5. package/esm/hooks/useMultimode.d.ts +49 -0
  6. package/esm/hooks/useMultimode.js +83 -0
  7. package/esm/hooks/useMultimode.js.map +1 -0
  8. package/esm/index.d.ts +1 -0
  9. package/esm/index.js +1 -0
  10. package/esm/index.js.map +1 -1
  11. package/esm/type.source.d.ts +33 -1
  12. package/esm/type.source.js +0 -1
  13. package/esm/type.source.js.map +1 -1
  14. package/esm/use-lunatic/reducer/reduce-go-next-page.js +2 -1
  15. package/esm/use-lunatic/reducer/reduce-go-next-page.js.map +1 -1
  16. package/esm/use-lunatic/reducer/reducerInitializer.d.ts +2 -2
  17. package/esm/use-lunatic/reducer/reducerInitializer.js +31 -24
  18. package/esm/use-lunatic/reducer/reducerInitializer.js.map +1 -1
  19. package/esm/use-lunatic/type.d.ts +2 -0
  20. package/esm/use-lunatic/use-lunatic.js +3 -0
  21. package/esm/use-lunatic/use-lunatic.js.map +1 -1
  22. package/esm/utils/getArticulationState.d.ts +64 -0
  23. package/esm/utils/getArticulationState.js +82 -0
  24. package/esm/utils/getArticulationState.js.map +1 -0
  25. package/hooks/useMultimode.d.ts +49 -0
  26. package/hooks/useMultimode.js +84 -0
  27. package/hooks/useMultimode.js.map +1 -0
  28. package/index.d.ts +1 -0
  29. package/index.js +3 -1
  30. package/index.js.map +1 -1
  31. package/package.json +18 -1
  32. package/src/components/Roundabout/Roundabout.tsx +8 -3
  33. package/src/hooks/useMultimode.ts +102 -0
  34. package/src/index.ts +1 -0
  35. package/src/stories/behaviour/articulation/articulation.stories.tsx +90 -0
  36. package/src/stories/behaviour/articulation/multimode.stories.tsx +19 -0
  37. package/src/stories/behaviour/articulation/roundabout.json +413 -0
  38. package/src/stories/utils/Orchestrator.tsx +3 -0
  39. package/src/stories/utils/OrchestratorSidebar.tsx +25 -1
  40. package/src/type.source.ts +33 -2
  41. package/src/use-lunatic/reducer/reduce-go-next-page.ts +2 -1
  42. package/src/use-lunatic/reducer/reducerInitializer.tsx +40 -29
  43. package/src/use-lunatic/type.ts +2 -0
  44. package/src/use-lunatic/use-lunatic.ts +4 -0
  45. package/src/utils/getArticulationState.ts +124 -0
  46. package/tsconfig.build.tsbuildinfo +1 -1
  47. package/type.source.d.ts +33 -1
  48. package/type.source.js +0 -1
  49. package/type.source.js.map +1 -1
  50. package/use-lunatic/reducer/reduce-go-next-page.js +2 -1
  51. package/use-lunatic/reducer/reduce-go-next-page.js.map +1 -1
  52. package/use-lunatic/reducer/reducerInitializer.d.ts +2 -2
  53. package/use-lunatic/reducer/reducerInitializer.js +31 -24
  54. package/use-lunatic/reducer/reducerInitializer.js.map +1 -1
  55. package/use-lunatic/type.d.ts +2 -0
  56. package/use-lunatic/use-lunatic.js +3 -0
  57. package/use-lunatic/use-lunatic.js.map +1 -1
  58. package/utils/getArticulationState.d.ts +64 -0
  59. package/utils/getArticulationState.js +84 -0
  60. package/utils/getArticulationState.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,124 @@
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
+ export enum ArticulationState {
13
+ COMPLETED = 1,
14
+ STARTED = 0,
15
+ NOT_STARTED = -1,
16
+ }
17
+
18
+ type ArticulationItem = {
19
+ label: string;
20
+ value: string;
21
+ };
22
+
23
+ type Articulation = {
24
+ source: string;
25
+ items: ArticulationItem[];
26
+ };
27
+
28
+ type Item = {
29
+ cells: {
30
+ label: string;
31
+ value: ReactNode;
32
+ }[];
33
+ progress: ArticulationState; // -1: not completed, 0: started, 1: finished
34
+ page: PageTag;
35
+ };
36
+
37
+ /**
38
+ * Retrieve the articulation state
39
+ *
40
+ * The goal of this function is to provide insights about a roundabout using extra information inserted in the JSON source
41
+ * provided to Lunatic.
42
+ *
43
+ * For instance
44
+ *
45
+ * ```
46
+ * "articulation": {
47
+ * "source": "roundabout",
48
+ * "items": [
49
+ * {
50
+ * "label": "Prénom",
51
+ * "value": "PRENOMS"
52
+ * },
53
+ * {
54
+ * "label": "Sexe",
55
+ * "value": "if SEXE = \"H\" then \"Homme\" else \"Femme\""
56
+ * },
57
+ * {
58
+ * "label": "Age",
59
+ * "value": "cast(AGE, string) || \" ans\""
60
+ * }
61
+ * ]
62
+ * },
63
+ * ```
64
+ *
65
+ * - source is the ID of the roundabout component
66
+ * - items define the field to extract from the roundabout data
67
+ */
68
+ export function getArticulationState(
69
+ source: LunaticSource & { articulation: Articulation },
70
+ data: LunaticData
71
+ ): { items: Item[] } {
72
+ const roundabout = findComponentById(
73
+ source.components,
74
+ source.articulation.source
75
+ );
76
+ const { variables } = reducerInitializer({ source, data });
77
+ const iterations = forceInt(
78
+ variables.run(roundabout?.iterations.value ?? '0')
79
+ );
80
+
81
+ const rows = times(iterations, (k) =>
82
+ source.articulation.items.map((item) => ({
83
+ label: item.label,
84
+ value: variables.run(item.value, { iteration: [k] }) as ReactNode,
85
+ }))
86
+ );
87
+
88
+ if (!roundabout) {
89
+ return {
90
+ items: [],
91
+ };
92
+ }
93
+
94
+ return {
95
+ items: rows.map((row, k) => ({
96
+ cells: row,
97
+ progress: forceInt(
98
+ variables.get(roundabout.progressVariable, [k]) ??
99
+ ArticulationState.NOT_STARTED
100
+ ),
101
+ page: (roundabout.page
102
+ ? `${roundabout.page}.1#${k + 1}`
103
+ : '1') as PageTag,
104
+ })),
105
+ };
106
+ }
107
+
108
+ export function findComponentById(
109
+ components: ComponentDefinition[],
110
+ id: string
111
+ ): (ComponentRoundaboutDefinition & { page?: string }) | null {
112
+ for (const c of components) {
113
+ if ('id' in c && c.id === id && c.componentType === 'Roundabout') {
114
+ return c;
115
+ }
116
+ if ('components' in c) {
117
+ const child = findComponentById(c.components, id);
118
+ if (child) {
119
+ return child;
120
+ }
121
+ }
122
+ }
123
+ return null;
124
+ }