@inseefr/lunatic 0.3.5-experimental → 0.3.8-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 (98) hide show
  1. package/lib/index.js +6 -6
  2. package/lib/index.js.map +1 -1
  3. package/package.json +4 -3
  4. package/src/components/breadcrumb/component.js +29 -29
  5. package/src/components/button/component.js +53 -53
  6. package/src/components/button/index.js +1 -1
  7. package/src/components/checkbox/index.js +3 -3
  8. package/src/components/datepicker/index.js +1 -1
  9. package/src/components/declarations/index.js +1 -1
  10. package/src/components/declarations/wrappers/list-declarations-wrapper.js +232 -232
  11. package/src/components/filter-description/component.js +42 -42
  12. package/src/components/icon/component.js +33 -33
  13. package/src/components/index.js +5 -3
  14. package/src/components/input/index.js +2 -2
  15. package/src/components/loop/index.js +1 -1
  16. package/src/components/loop-constructor/wrapper/body-component.js +13 -1
  17. package/src/components/radio/index.js +1 -1
  18. package/src/components/sequence/index.js +1 -1
  19. package/src/components/subsequence/index.js +1 -1
  20. package/src/components/suggester/check-store.js +70 -70
  21. package/src/components/suggester/components/create-on-keydown-callback.js +28 -28
  22. package/src/components/tooltip/response.js +52 -52
  23. package/src/stories/checkbox-boolean/data-forced.json +48 -48
  24. package/src/stories/checkbox-group/data-vtl.json +102 -102
  25. package/src/stories/icons/icons.stories.js +16 -16
  26. package/src/stories/questionnaire/kish.json +275 -0
  27. package/src/stories/questionnaire/loop-and-controls.json +481 -0
  28. package/src/stories/questionnaire/questionnaire.stories.js +31 -0
  29. package/src/stories/suggester/bailleurs-sociaux-2021/fetch-bailleurs.js +12 -0
  30. package/src/stories/suggester/bailleurs-sociaux-2021/index.js +1 -0
  31. package/src/stories/suggester/data.json +31 -1
  32. package/src/stories/suggester/suggester-workers.stories.js +44 -0
  33. package/src/stories/suggester/suggester.stories.js +5 -0
  34. package/src/stories/utils/custom-lunatic.scss +23 -23
  35. package/src/tests/components/breadcrumb.spec.js +13 -13
  36. package/src/tests/components/button.spec.js +11 -11
  37. package/src/tests/components/checkbox-boolean.spec.js +45 -45
  38. package/src/tests/components/checkbox-group.spec.js +53 -53
  39. package/src/tests/components/checkbox-one.spec.js +32 -32
  40. package/src/tests/components/datepicker.spec.js +22 -22
  41. package/src/tests/components/declarations-wrappers/input-declarations-wrapper.spec.js +67 -67
  42. package/src/tests/components/declarations-wrappers/list-declarations-wrapper.spec.js +52 -52
  43. package/src/tests/components/declarations-wrappers/simple-declarations-wrapper.spec.js +21 -21
  44. package/src/tests/components/declarations.spec.js +46 -46
  45. package/src/tests/components/input.spec.js +18 -18
  46. package/src/tests/components/loops/loop-static.json +66 -66
  47. package/src/tests/components/loops/loop.json +258 -258
  48. package/src/tests/components/loops/loop.spec.js +30 -30
  49. package/src/tests/components/loops/roster-for-loop.spec.js +18 -18
  50. package/src/tests/components/progress-bar.spec.js +15 -15
  51. package/src/tests/components/radio.spec.js +27 -27
  52. package/src/tests/components/sequence.spec.js +9 -9
  53. package/src/tests/components/subsequence.spec.js +9 -9
  54. package/src/tests/components/table.spec.js +11 -11
  55. package/src/tests/components/textarea.spec.js +18 -18
  56. package/src/tests/components/tooltip.spec.js +25 -25
  57. package/src/tests/setup/setupTests.js +4 -4
  58. package/src/tests/utils/lib/alphabet.spec.js +36 -36
  59. package/src/tests/utils/lib/array.spec.js +22 -22
  60. package/src/tests/utils/lib/checkbox/group.spec.js +72 -72
  61. package/src/tests/utils/lib/decorator/title-decorator.spec.js +12 -12
  62. package/src/tests/utils/lib/input-number.spec.js +18 -18
  63. package/src/tests/utils/lib/items-positioning.spec.js +17 -17
  64. package/src/tests/utils/lib/label-position.spec.js +22 -22
  65. package/src/tests/utils/lib/loops/bindings.spec.js +75 -75
  66. package/src/tests/utils/lib/loops/shared.spec.js +82 -82
  67. package/src/tests/utils/lib/missing/missing.spec.js +74 -74
  68. package/src/tests/utils/lib/missing/mock.js +137 -137
  69. package/src/tests/utils/lib/pagination/shared.spec.js +42 -42
  70. package/src/tests/utils/lib/responses.spec.js +64 -64
  71. package/src/tests/utils/lib/style.spec.js +26 -26
  72. package/src/tests/utils/lib/tooltip/build-response.spec.js +95 -95
  73. package/src/tests/utils/lib/tooltip/content.spec.js +109 -109
  74. package/src/tests/utils/to-expose/handler/handler.spec.js +94 -94
  75. package/src/tests/utils/to-expose/handler/questionnaire.json +158 -158
  76. package/src/tests/utils/to-expose/handler/results/index.js +6 -6
  77. package/src/tests/utils/to-expose/handler/results/res-double.json +158 -158
  78. package/src/tests/utils/to-expose/handler/results/res-input-collected.json +158 -158
  79. package/src/tests/utils/to-expose/handler/results/res-loop.json +158 -158
  80. package/src/tests/utils/to-expose/handler/results/res-matrix.json +158 -158
  81. package/src/tests/utils/to-expose/handler/results/res-responses.json +158 -158
  82. package/src/tests/utils/to-expose/hooks/use-lunatic.spec.js +46 -46
  83. package/src/tests/utils/to-expose/init-questionnaire/data.json +12 -12
  84. package/src/tests/utils/to-expose/init-questionnaire/init-questionnaire.spec.js +19 -19
  85. package/src/tests/utils/to-expose/interpret/interpret.spec.js +48 -48
  86. package/src/tests/utils/to-expose/state/questionnaire.json +61 -61
  87. package/src/tests/utils/to-expose/state/results.js +78 -78
  88. package/src/utils/lib/controls/utils.js +8 -2
  89. package/src/utils/lib/tooltip/build-response.js +41 -41
  90. package/src/utils/store-tools/create/index.js +1 -1
  91. package/src/utils/store-tools/create/update-store-info.js +26 -26
  92. package/src/utils/store-tools/index.js +5 -5
  93. package/src/utils/suggester-workers/commons-tokenizer/create-fields-tokenizer.js +5 -1
  94. package/src/utils/suggester-workers/commons-tokenizer/index.js +1 -0
  95. package/src/utils/suggester-workers/searching/query-parser/query-parser-tokenized.js +7 -1
  96. package/src/utils/to-expose/handler.js +12 -14
  97. package/src/utils/to-expose/hooks/lunatic-split.js +5 -2
  98. package/src/utils/to-expose/hooks/lunatic.js +5 -2
package/package.json CHANGED
@@ -1,7 +1,7 @@
1
1
  {
2
2
  "name": "@inseefr/lunatic",
3
- "version": "0.3.5-experimental",
4
- "workersVersion": "0.2.1-experimental",
3
+ "version": "0.3.8-experimental",
4
+ "workersVersion": "0.2.4-experimental",
5
5
  "description": "Library of questionnaire components",
6
6
  "repository": {
7
7
  "type": "git",
@@ -50,7 +50,8 @@
50
50
  "library"
51
51
  ],
52
52
  "dependencies": {
53
- "@inseefr/trevas": "^0.1.12",
53
+ "@inseefr/trevas": "^0.1.14",
54
+ "array-flat-polyfill": "^1.0.1",
54
55
  "date-fns": "^2.25.0",
55
56
  "lodash.camelcase": "^4.3.0",
56
57
  "lodash.debounce": "^4.0.8",
@@ -1,29 +1,29 @@
1
- import React from 'react';
2
- import PropTypes from 'prop-types';
3
- import { buildStyleObject } from '../../utils/lib';
4
- import './breadcrumb.scss';
5
-
6
- const Breadcrumb = ({ elements, style }) => (
7
- <div
8
- aria-label={`breadcrumb`}
9
- className="breadcrumb-lunatic"
10
- style={buildStyleObject(style)}
11
- >
12
- {elements.map((e, i) => (
13
- <React.Fragment key={`breadcrumb-${e.toLowerCase()}`}>
14
- {e && (
15
- <span className={i !== 0 ? 'breadcrumb-element-lunatic' : undefined}>
16
- {e}
17
- </span>
18
- )}
19
- </React.Fragment>
20
- ))}
21
- </div>
22
- );
23
-
24
- Breadcrumb.propTypes = {
25
- elements: PropTypes.arrayOf(PropTypes.string).isRequired,
26
- style: PropTypes.object,
27
- };
28
-
29
- export default Breadcrumb;
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import { buildStyleObject } from '../../utils/lib';
4
+ import './breadcrumb.scss';
5
+
6
+ const Breadcrumb = ({ elements, style }) => (
7
+ <div
8
+ aria-label={`breadcrumb`}
9
+ className="breadcrumb-lunatic"
10
+ style={buildStyleObject(style)}
11
+ >
12
+ {elements.map((e, i) => (
13
+ <React.Fragment key={`breadcrumb-${e.toLowerCase()}`}>
14
+ {e && (
15
+ <span className={i !== 0 ? 'breadcrumb-element-lunatic' : undefined}>
16
+ {e}
17
+ </span>
18
+ )}
19
+ </React.Fragment>
20
+ ))}
21
+ </div>
22
+ );
23
+
24
+ Breadcrumb.propTypes = {
25
+ elements: PropTypes.arrayOf(PropTypes.string).isRequired,
26
+ style: PropTypes.object,
27
+ };
28
+
29
+ export default Breadcrumb;
@@ -1,53 +1,53 @@
1
- import React from 'react';
2
- import PropTypes from 'prop-types';
3
- import {
4
- buildStyleObject,
5
- createObjectEvent,
6
- isFunction,
7
- } from '../../utils/lib';
8
- import './button.scss';
9
- import { BUTTON_CATEGORY, EVENT_CLICK } from '../../constants';
10
-
11
- const Button = ({
12
- label,
13
- value,
14
- onClick,
15
- disabled,
16
- style,
17
- logFunction,
18
- id,
19
- }) => {
20
- const handleClick = (e) => {
21
- onClick(e);
22
- if (isFunction(logFunction))
23
- logFunction(
24
- createObjectEvent(
25
- `button-lunatic-${id}`,
26
- BUTTON_CATEGORY,
27
- EVENT_CLICK,
28
- null,
29
- label
30
- )
31
- );
32
- };
33
- return (
34
- <button
35
- type="button"
36
- aria-label={label || 'button'}
37
- className="button-lunatic"
38
- style={buildStyleObject(style)}
39
- disabled={disabled}
40
- onClick={handleClick}
41
- >
42
- {value}
43
- </button>
44
- );
45
- };
46
-
47
- Button.propTypes = {
48
- value: PropTypes.oneOfType([PropTypes.string, PropTypes.element]).isRequired,
49
- disabled: PropTypes.bool,
50
- onClick: PropTypes.func.isRequired,
51
- };
52
-
53
- export default Button;
1
+ import React from 'react';
2
+ import PropTypes from 'prop-types';
3
+ import {
4
+ buildStyleObject,
5
+ createObjectEvent,
6
+ isFunction,
7
+ } from '../../utils/lib';
8
+ import './button.scss';
9
+ import { BUTTON_CATEGORY, EVENT_CLICK } from '../../constants';
10
+
11
+ const Button = ({
12
+ label,
13
+ value,
14
+ onClick,
15
+ disabled,
16
+ style,
17
+ logFunction,
18
+ id,
19
+ }) => {
20
+ const handleClick = (e) => {
21
+ onClick(e);
22
+ if (isFunction(logFunction))
23
+ logFunction(
24
+ createObjectEvent(
25
+ `button-lunatic-${id}`,
26
+ BUTTON_CATEGORY,
27
+ EVENT_CLICK,
28
+ null,
29
+ label
30
+ )
31
+ );
32
+ };
33
+ return (
34
+ <button
35
+ type="button"
36
+ aria-label={label || 'button'}
37
+ className="button-lunatic"
38
+ style={buildStyleObject(style)}
39
+ disabled={disabled}
40
+ onClick={handleClick}
41
+ >
42
+ {value}
43
+ </button>
44
+ );
45
+ };
46
+
47
+ Button.propTypes = {
48
+ value: PropTypes.oneOfType([PropTypes.string, PropTypes.element]).isRequired,
49
+ disabled: PropTypes.bool,
50
+ onClick: PropTypes.func.isRequired,
51
+ };
52
+
53
+ export default Button;
@@ -1 +1 @@
1
- export { default } from './component';
1
+ export { default } from './component';
@@ -1,3 +1,3 @@
1
- export { default as CheckboxGroup } from './group';
2
- export { default as CheckboxBoolean } from './boolean';
3
- export { default as CheckboxOne } from './one';
1
+ export { default as CheckboxGroup } from './group';
2
+ export { default as CheckboxBoolean } from './boolean';
3
+ export { default as CheckboxOne } from './one';
@@ -1 +1 @@
1
- export { default } from './component';
1
+ export { default } from './component';
@@ -1 +1 @@
1
- export { default } from './component';
1
+ export { default } from './component';
@@ -1,232 +1,232 @@
1
- import React, { useState, useEffect, useRef } from 'react';
2
- import KeyboardEventHandler from 'react-keyboard-event-handler';
3
- import PropTypes from 'prop-types';
4
- import debounce from 'lodash.debounce';
5
- import Declarations from '../';
6
- import Icon from '../../icon';
7
- import { TooltipResponse } from '../../tooltip';
8
- import * as U from '../../../utils/lib';
9
- import * as C from '../../../constants';
10
- import { interpret } from '../../../utils/to-expose';
11
-
12
- const ListDeclarationsWrapper = ({
13
- id,
14
- label,
15
- preferences,
16
- response,
17
- options,
18
- handleChange: propsHandleChange,
19
- disabled,
20
- focused,
21
- shortcut,
22
- declarations,
23
- features,
24
- bindings,
25
- management,
26
- style,
27
- positioning,
28
- type,
29
- hasSpecificHandler,
30
- logFunction,
31
- }) => {
32
- const inputRef = useRef();
33
-
34
- const [value, setValue] = useState(() =>
35
- U.getResponseByPreference(preferences)(response)
36
- );
37
-
38
- const filledOptions =
39
- management && type === 'checkbox'
40
- ? [...options, { label: 'NR', value: '_N_R_' }]
41
- : options;
42
-
43
- const specificHandleChange = (e) => {
44
- const { values } = response;
45
- const [key, value] = Object.entries(e)[0];
46
- const newValue =
47
- values[preferences[preferences.length - 1]] === value ? null : value;
48
- handleChange({ [key]: newValue });
49
- if (management) {
50
- setValue(
51
- U.getResponseByPreference(preferences)(
52
- U.buildLocalResponse(response, newValue)
53
- )
54
- );
55
- } else setValue(newValue);
56
- };
57
-
58
- const handleChange = debounce((obj) => propsHandleChange(obj), 50);
59
-
60
- const onChange = (v) => {
61
- const update = {
62
- [U.getResponseName(response)]: v,
63
- };
64
- if (hasSpecificHandler) specificHandleChange(update);
65
- else {
66
- setValue(v);
67
- handleChange(update);
68
- }
69
- if (U.isFunction(logFunction))
70
- logFunction(
71
- U.createObjectEvent(
72
- `${type}-${id}-${v}`,
73
- C.INPUT_CATEGORY,
74
- C.EVENT_SELECTION,
75
- U.getResponseName(response),
76
- v
77
- )
78
- );
79
- };
80
-
81
- // Assume we only want to handle enable external updates
82
- // Don't need to check all value changes
83
- useEffect(() => {
84
- if (U.getResponseByPreference(preferences)(response) !== value)
85
- setValue(U.getResponseByPreference(preferences)(response));
86
- // eslint-disable-next-line react-hooks/exhaustive-deps
87
- }, [response, preferences]);
88
-
89
- useEffect(() => {
90
- if (focused) inputRef.current.focus();
91
- }, [focused]);
92
-
93
- const { fieldsetStyle, modalityStyle } = style;
94
- return (
95
- <>
96
- <Declarations
97
- id={id}
98
- type={C.BEFORE_QUESTION_TEXT}
99
- declarations={declarations}
100
- features={features}
101
- bindings={bindings}
102
- />
103
- <div className="field-container">
104
- <div className={`${management ? 'field-with-tooltip' : 'field'}`}>
105
- <fieldset
106
- key={`${type}-${id}`}
107
- className={`${type}-group-list`}
108
- style={U.buildStyleObject(fieldsetStyle)}
109
- >
110
- <legend>{interpret(features, logFunction)(bindings)(label)}</legend>
111
- <Declarations
112
- id={id}
113
- type={C.AFTER_QUESTION_TEXT}
114
- declarations={declarations}
115
- features={features}
116
- bindings={bindings}
117
- />
118
- {filledOptions.map(
119
- ({ label: optionLabel, value: optionValue }, i) => {
120
- const checked = value === optionValue;
121
- const interpretedLabel = interpret(
122
- features,
123
- logFunction
124
- )(bindings)(optionLabel);
125
- const keyboardSelectionKey =
126
- options.length < 10 ? `${i + 1}` : U.getAlphabet()[i];
127
- return (
128
- <div
129
- key={`${type}-${id}-${optionValue}`}
130
- className={`${type}-modality ${type}-modality-block ${U.getItemsPositioningClass(
131
- positioning
132
- )} ${checked ? 'content-checked' : ''} ${
133
- optionValue === '_N_R_' ? 'modality_NR' : ''
134
- }`}
135
- >
136
- <Icon type={type} checked={checked} disabled={disabled}>
137
- <input
138
- type={type}
139
- name={`${type}-${id}`}
140
- ref={i === 0 || checked ? inputRef : null}
141
- id={`${type}-${id}-${optionValue}`}
142
- aria-labelledby={`input-label-${id}-${optionValue}`}
143
- className={`${type}-lunatic`}
144
- style={U.buildStyleObject(style)}
145
- checked={checked}
146
- disabled={disabled}
147
- onChange={(optionLabel) => onChange(optionValue)}
148
- />
149
- <label
150
- htmlFor={`${type}-${id}-${optionValue}`}
151
- id={`input-label-${id}-${optionValue}`}
152
- style={checked ? U.buildStyleObject(modalityStyle) : {}}
153
- className="modality-label"
154
- >
155
- {shortcut && (
156
- <span className="code-modality">
157
- {keyboardSelectionKey.toUpperCase()}
158
- </span>
159
- )}
160
- {interpretedLabel}
161
- </label>
162
- </Icon>
163
- {shortcut && (
164
- <KeyboardEventHandler
165
- handleKeys={[keyboardSelectionKey.toLowerCase()]}
166
- onKeyEvent={(key, e) => {
167
- e.preventDefault();
168
- onChange(optionValue);
169
- }}
170
- handleFocusableElements
171
- />
172
- )}
173
- </div>
174
- );
175
- }
176
- )}
177
- </fieldset>
178
- </div>
179
- {management && (
180
- <div className="tooltip">
181
- <TooltipResponse
182
- id={id}
183
- response={U.buildMultiTooltipResponse(filledOptions)(response)}
184
- />
185
- </div>
186
- )}
187
- </div>
188
- <Declarations
189
- id={id}
190
- type={C.DETACHABLE}
191
- declarations={declarations}
192
- features={features}
193
- bindings={bindings}
194
- />
195
- </>
196
- );
197
- };
198
-
199
- ListDeclarationsWrapper.defaultProps = {
200
- label: '',
201
- preferences: ['COLLECTED'],
202
- response: {},
203
- options: [],
204
- disabled: false,
205
- focused: false,
206
- positioning: 'DEFAULT',
207
- declarations: [],
208
- features: [],
209
- bindings: {},
210
- management: false,
211
- style: { fieldsetStyle: {}, modalityStyle: {} },
212
- };
213
-
214
- ListDeclarationsWrapper.propTypes = {
215
- id: PropTypes.string.isRequired,
216
- label: PropTypes.string,
217
- preferences: PropTypes.arrayOf(U.valueTypePropTypes),
218
- response: U.responsePropTypes,
219
- options: U.optionsPropTypes,
220
- handleChange: PropTypes.func.isRequired,
221
- disabled: PropTypes.bool,
222
- focused: PropTypes.bool,
223
- positioning: PropTypes.oneOf(['DEFAULT', 'HORIZONTAL', 'VERTICAL']),
224
- declarations: U.declarationsPropTypes,
225
- features: PropTypes.arrayOf(PropTypes.string),
226
- bindings: PropTypes.object,
227
- management: PropTypes.bool,
228
- style: PropTypes.object,
229
- type: PropTypes.oneOf(['radio', 'checkbox']),
230
- };
231
-
232
- export default ListDeclarationsWrapper;
1
+ import React, { useState, useEffect, useRef } from 'react';
2
+ import KeyboardEventHandler from 'react-keyboard-event-handler';
3
+ import PropTypes from 'prop-types';
4
+ import debounce from 'lodash.debounce';
5
+ import Declarations from '../';
6
+ import Icon from '../../icon';
7
+ import { TooltipResponse } from '../../tooltip';
8
+ import * as U from '../../../utils/lib';
9
+ import * as C from '../../../constants';
10
+ import { interpret } from '../../../utils/to-expose';
11
+
12
+ const ListDeclarationsWrapper = ({
13
+ id,
14
+ label,
15
+ preferences,
16
+ response,
17
+ options,
18
+ handleChange: propsHandleChange,
19
+ disabled,
20
+ focused,
21
+ shortcut,
22
+ declarations,
23
+ features,
24
+ bindings,
25
+ management,
26
+ style,
27
+ positioning,
28
+ type,
29
+ hasSpecificHandler,
30
+ logFunction,
31
+ }) => {
32
+ const inputRef = useRef();
33
+
34
+ const [value, setValue] = useState(() =>
35
+ U.getResponseByPreference(preferences)(response)
36
+ );
37
+
38
+ const filledOptions =
39
+ management && type === 'checkbox'
40
+ ? [...options, { label: 'NR', value: '_N_R_' }]
41
+ : options;
42
+
43
+ const specificHandleChange = (e) => {
44
+ const { values } = response;
45
+ const [key, value] = Object.entries(e)[0];
46
+ const newValue =
47
+ values[preferences[preferences.length - 1]] === value ? null : value;
48
+ handleChange({ [key]: newValue });
49
+ if (management) {
50
+ setValue(
51
+ U.getResponseByPreference(preferences)(
52
+ U.buildLocalResponse(response, newValue)
53
+ )
54
+ );
55
+ } else setValue(newValue);
56
+ };
57
+
58
+ const handleChange = debounce((obj) => propsHandleChange(obj), 50);
59
+
60
+ const onChange = (v) => {
61
+ const update = {
62
+ [U.getResponseName(response)]: v,
63
+ };
64
+ if (hasSpecificHandler) specificHandleChange(update);
65
+ else {
66
+ setValue(v);
67
+ handleChange(update);
68
+ }
69
+ if (U.isFunction(logFunction))
70
+ logFunction(
71
+ U.createObjectEvent(
72
+ `${type}-${id}-${v}`,
73
+ C.INPUT_CATEGORY,
74
+ C.EVENT_SELECTION,
75
+ U.getResponseName(response),
76
+ v
77
+ )
78
+ );
79
+ };
80
+
81
+ // Assume we only want to handle enable external updates
82
+ // Don't need to check all value changes
83
+ useEffect(() => {
84
+ if (U.getResponseByPreference(preferences)(response) !== value)
85
+ setValue(U.getResponseByPreference(preferences)(response));
86
+ // eslint-disable-next-line react-hooks/exhaustive-deps
87
+ }, [response, preferences]);
88
+
89
+ useEffect(() => {
90
+ if (focused) inputRef.current.focus();
91
+ }, [focused]);
92
+
93
+ const { fieldsetStyle, modalityStyle } = style;
94
+ return (
95
+ <>
96
+ <Declarations
97
+ id={id}
98
+ type={C.BEFORE_QUESTION_TEXT}
99
+ declarations={declarations}
100
+ features={features}
101
+ bindings={bindings}
102
+ />
103
+ <div className="field-container">
104
+ <div className={`${management ? 'field-with-tooltip' : 'field'}`}>
105
+ <fieldset
106
+ key={`${type}-${id}`}
107
+ className={`${type}-group-list`}
108
+ style={U.buildStyleObject(fieldsetStyle)}
109
+ >
110
+ <legend>{interpret(features, logFunction)(bindings)(label)}</legend>
111
+ <Declarations
112
+ id={id}
113
+ type={C.AFTER_QUESTION_TEXT}
114
+ declarations={declarations}
115
+ features={features}
116
+ bindings={bindings}
117
+ />
118
+ {filledOptions.map(
119
+ ({ label: optionLabel, value: optionValue }, i) => {
120
+ const checked = value === optionValue;
121
+ const interpretedLabel = interpret(
122
+ features,
123
+ logFunction
124
+ )(bindings)(optionLabel);
125
+ const keyboardSelectionKey =
126
+ options.length < 10 ? `${i + 1}` : U.getAlphabet()[i];
127
+ return (
128
+ <div
129
+ key={`${type}-${id}-${optionValue}`}
130
+ className={`${type}-modality ${type}-modality-block ${U.getItemsPositioningClass(
131
+ positioning
132
+ )} ${checked ? 'content-checked' : ''} ${
133
+ optionValue === '_N_R_' ? 'modality_NR' : ''
134
+ }`}
135
+ >
136
+ <Icon type={type} checked={checked} disabled={disabled}>
137
+ <input
138
+ type={type}
139
+ name={`${type}-${id}`}
140
+ ref={i === 0 || checked ? inputRef : null}
141
+ id={`${type}-${id}-${optionValue}`}
142
+ aria-labelledby={`input-label-${id}-${optionValue}`}
143
+ className={`${type}-lunatic`}
144
+ style={U.buildStyleObject(style)}
145
+ checked={checked}
146
+ disabled={disabled}
147
+ onChange={(optionLabel) => onChange(optionValue)}
148
+ />
149
+ <label
150
+ htmlFor={`${type}-${id}-${optionValue}`}
151
+ id={`input-label-${id}-${optionValue}`}
152
+ style={checked ? U.buildStyleObject(modalityStyle) : {}}
153
+ className="modality-label"
154
+ >
155
+ {shortcut && (
156
+ <span className="code-modality">
157
+ {keyboardSelectionKey.toUpperCase()}
158
+ </span>
159
+ )}
160
+ {interpretedLabel}
161
+ </label>
162
+ </Icon>
163
+ {shortcut && (
164
+ <KeyboardEventHandler
165
+ handleKeys={[keyboardSelectionKey.toLowerCase()]}
166
+ onKeyEvent={(key, e) => {
167
+ e.preventDefault();
168
+ onChange(optionValue);
169
+ }}
170
+ handleFocusableElements
171
+ />
172
+ )}
173
+ </div>
174
+ );
175
+ }
176
+ )}
177
+ </fieldset>
178
+ </div>
179
+ {management && (
180
+ <div className="tooltip">
181
+ <TooltipResponse
182
+ id={id}
183
+ response={U.buildMultiTooltipResponse(filledOptions)(response)}
184
+ />
185
+ </div>
186
+ )}
187
+ </div>
188
+ <Declarations
189
+ id={id}
190
+ type={C.DETACHABLE}
191
+ declarations={declarations}
192
+ features={features}
193
+ bindings={bindings}
194
+ />
195
+ </>
196
+ );
197
+ };
198
+
199
+ ListDeclarationsWrapper.defaultProps = {
200
+ label: '',
201
+ preferences: ['COLLECTED'],
202
+ response: {},
203
+ options: [],
204
+ disabled: false,
205
+ focused: false,
206
+ positioning: 'DEFAULT',
207
+ declarations: [],
208
+ features: [],
209
+ bindings: {},
210
+ management: false,
211
+ style: { fieldsetStyle: {}, modalityStyle: {} },
212
+ };
213
+
214
+ ListDeclarationsWrapper.propTypes = {
215
+ id: PropTypes.string.isRequired,
216
+ label: PropTypes.string,
217
+ preferences: PropTypes.arrayOf(U.valueTypePropTypes),
218
+ response: U.responsePropTypes,
219
+ options: U.optionsPropTypes,
220
+ handleChange: PropTypes.func.isRequired,
221
+ disabled: PropTypes.bool,
222
+ focused: PropTypes.bool,
223
+ positioning: PropTypes.oneOf(['DEFAULT', 'HORIZONTAL', 'VERTICAL']),
224
+ declarations: U.declarationsPropTypes,
225
+ features: PropTypes.arrayOf(PropTypes.string),
226
+ bindings: PropTypes.object,
227
+ management: PropTypes.bool,
228
+ style: PropTypes.object,
229
+ type: PropTypes.oneOf(['radio', 'checkbox']),
230
+ };
231
+
232
+ export default ListDeclarationsWrapper;