@inseefr/lunatic 0.3.2-experimental → 0.3.3-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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@inseefr/lunatic",
3
- "version": "0.3.2-experimental",
3
+ "version": "0.3.3-experimental",
4
4
  "workersVersion": "0.2.1-experimental",
5
5
  "description": "Library of questionnaire components",
6
6
  "repository": {
@@ -50,7 +50,7 @@
50
50
  "library"
51
51
  ],
52
52
  "dependencies": {
53
- "@inseefr/trevas": "^0.1.11",
53
+ "@inseefr/trevas": "^0.1.12",
54
54
  "date-fns": "^2.25.0",
55
55
  "lodash.camelcase": "^4.3.0",
56
56
  "lodash.debounce": "^4.0.8",
@@ -172,6 +172,7 @@ const InputDeclarationsWrapper = ({
172
172
  aria-required={mandatory}
173
173
  onChange={(e) => {
174
174
  const v = e.target.value;
175
+ const valueToFire = v === '' ? null : v;
175
176
  if (
176
177
  (([null, ''].includes(v) && value.length > 0) ||
177
178
  ([null, ''].includes(value) && v.length > 0)) &&
@@ -179,7 +180,7 @@ const InputDeclarationsWrapper = ({
179
180
  ) {
180
181
  setValue(v);
181
182
  handleChange({
182
- [U.getResponseName(response)]: v,
183
+ [U.getResponseName(response)]: valueToFire,
183
184
  });
184
185
  } else if (
185
186
  // Chrome
@@ -187,11 +188,11 @@ const InputDeclarationsWrapper = ({
187
188
  'Event' &&
188
189
  roleType !== 'datepicker') ||
189
190
  // FF hack: impossible to handle arrow events
190
- (Math.abs(v - value) === 1 && isInputNumber)
191
+ (Math.abs(v - value) !== 0 && isInputNumber)
191
192
  ) {
192
- setValue(v);
193
+ setValue(valueToFire);
193
194
  handleChange({
194
- [U.getResponseName(response)]: v,
195
+ [U.getResponseName(response)]: valueToFire,
195
196
  });
196
197
  } else {
197
198
  if (isInputNumber) {
@@ -205,8 +206,8 @@ const InputDeclarationsWrapper = ({
205
206
  return null;
206
207
  } else validate(v);
207
208
  }
208
- if (management) setValue(v);
209
- else setValue(v === '' ? null : v);
209
+ if (management) setValue(valueToFire);
210
+ else setValue(valueToFire);
210
211
  }
211
212
  }}
212
213
  onBlur={handleChangeOnBlur}
@@ -3,6 +3,7 @@ import PropTypes from 'prop-types';
3
3
  import classnames from 'classnames';
4
4
  import Label from './label';
5
5
  import * as U from '../../../../utils/lib';
6
+ import * as C from '../../../../constants';
6
7
  import * as CLEAN from '../cleaner-callbacks';
7
8
  import * as actions from '../actions';
8
9
  import DropdownField from './dropdown-field';
@@ -65,9 +66,19 @@ function Dropdown({
65
66
  state,
66
67
  dispatch,
67
68
  refs,
69
+ logFunction,
68
70
  }) {
69
71
  const { visible, focused, id, disabled } = state;
70
72
 
73
+ const createEventFocus = (focusIn = true) =>
74
+ U.createObjectEvent(
75
+ id,
76
+ C.INPUT_CATEGORY,
77
+ focusIn ? C.EVENT_FOCUS_IN : C.EVENT_FOCUS_OUT,
78
+ U.getResponseName(response),
79
+ valueFromProps
80
+ );
81
+
71
82
  CLEAN.add(id, function () {
72
83
  dispatch(actions.hidePanel());
73
84
  dispatch(actions.setFocused(false));
@@ -130,6 +141,16 @@ function Dropdown({
130
141
  [state, dispatch, onSelect]
131
142
  );
132
143
 
144
+ // log info when focus change
145
+ useEffect(() => {
146
+ if (id && focused && U.isFunction(logFunction))
147
+ logFunction(createEventFocus());
148
+ if (id && !focused && U.isFunction(logFunction))
149
+ logFunction(createEventFocus(false));
150
+
151
+ // eslint-disable-next-line react-hooks/exhaustive-deps
152
+ }, [focused, id]);
153
+
133
154
  return (
134
155
  <DropdownContainer
135
156
  className={classnames(className, U.getLabelPositionClass(labelPosition), {
@@ -37,6 +37,7 @@ const createOnSelect = (_, dispatch, onSelect) => (option) => {
37
37
  * @param {props}
38
38
  */
39
39
  function Dropdown({
40
+ id: initId,
40
41
  widthAuto,
41
42
  options = [],
42
43
  onSelect,
@@ -52,10 +53,11 @@ function Dropdown({
52
53
  disabled,
53
54
  focused: initFocused,
54
55
  DeclarationAfterLabel,
56
+ logFunction,
55
57
  }) {
56
58
  const [state, dispatch] = useReducer(reducer, {
57
59
  ...initial,
58
- id: `dropdown-${new Date().getMilliseconds()}`,
60
+ id: `dropdown-${initId || new Date().getMilliseconds()}`,
59
61
  disabled,
60
62
  focused: initFocused,
61
63
  });
@@ -98,6 +100,7 @@ function Dropdown({
98
100
  value={valueFromProps}
99
101
  zIndex={zIndex}
100
102
  management={management}
103
+ logFunction={logFunction}
101
104
  >
102
105
  <DeclarationAfterLabel />
103
106
  <span
@@ -26,11 +26,12 @@ const Dropdown = ({
26
26
  className,
27
27
  zIndex,
28
28
  DeclarationAfterLabel,
29
+ logFunction,
29
30
  }) => {
30
31
  const containerEl = useRef();
31
32
  const [state, dispatch] = useReducer(reducer, {
32
33
  ...initial,
33
- id: `dropdown-${initId}-${new Date().getMilliseconds()}`,
34
+ id: `dropdown-${initId || new Date().getMilliseconds()}`,
34
35
  disabled,
35
36
  focused: initFocused,
36
37
  });
@@ -59,6 +60,7 @@ const Dropdown = ({
59
60
  onSelect={onSelect_}
60
61
  value={value}
61
62
  zIndex={zIndex}
63
+ logFunction={logFunction}
62
64
  >
63
65
  <DeclarationAfterLabel />
64
66
  <span className={classnames('lunatic-dropdown-input', { focused })}>
@@ -1,42 +1,42 @@
1
- import React, { useRef, useCallback } from 'react';
2
- import classnames from 'classnames';
3
- import useDocumentAddEventListener from '../../../utils/to-expose/hooks/use-document-add-event-listener';
4
-
5
- function SuggesterContent({
6
- children,
7
- id,
8
- focused,
9
- onFocus,
10
- onBlur,
11
- onKeyDown,
12
- }) {
13
- const ref = useRef();
14
- const onClick = useCallback(
15
- function (e) {
16
- const { current } = ref;
17
- if (!current.contains(e.target)) {
18
- onBlur();
19
- }
20
- },
21
- [ref, onBlur]
22
- );
23
-
24
- useDocumentAddEventListener('mousedown', onClick);
25
-
26
- return (
27
- <div
28
- className={classnames('lunatic-suggester', {
29
- focused,
30
- })}
31
- onFocus={onFocus}
32
- onKeyDown={onKeyDown}
33
- ref={ref}
34
- >
35
- <div className={classnames('lunatic-suggester-content', { focused })}>
36
- {children}
37
- </div>
38
- </div>
39
- );
40
- }
41
-
42
- export default SuggesterContent;
1
+ import React, { useRef, useCallback } from 'react';
2
+ import classnames from 'classnames';
3
+ import useDocumentAddEventListener from '../../../utils/to-expose/hooks/use-document-add-event-listener';
4
+
5
+ function SuggesterContent({
6
+ children,
7
+ id,
8
+ focused,
9
+ onFocus,
10
+ onBlur,
11
+ onKeyDown,
12
+ }) {
13
+ const ref = useRef();
14
+ const onClick = useCallback(
15
+ function (e) {
16
+ const { current } = ref;
17
+ if (!current.contains(e.target) && focused) {
18
+ onBlur();
19
+ }
20
+ },
21
+ [ref, focused, onBlur]
22
+ );
23
+
24
+ useDocumentAddEventListener('mousedown', onClick);
25
+
26
+ return (
27
+ <div
28
+ className={classnames('lunatic-suggester', {
29
+ focused,
30
+ })}
31
+ onFocus={onFocus}
32
+ onKeyDown={onKeyDown}
33
+ ref={ref}
34
+ >
35
+ <div className={classnames('lunatic-suggester-content', { focused })}>
36
+ {children}
37
+ </div>
38
+ </div>
39
+ );
40
+ }
41
+
42
+ export default SuggesterContent;
@@ -1,4 +1,11 @@
1
- import React, { useCallback, useContext, useRef, useMemo } from 'react';
1
+ import React, {
2
+ useCallback,
3
+ useContext,
4
+ useRef,
5
+ useMemo,
6
+ useEffect,
7
+ useState,
8
+ } from 'react';
2
9
  import classnames from 'classnames';
3
10
  import { actions, SuggesterContext } from '../state-management';
4
11
  import SuggesterContent from './suggester-content';
@@ -6,6 +13,8 @@ import Selection from './selection';
6
13
  import Panel from './panel';
7
14
  import createOnKeyDownCallback from './create-on-keydown-callback';
8
15
  import Delete from './selection/delete';
16
+ import * as C from '../../../constants';
17
+ import * as U from '../../../utils/lib';
9
18
  import './suggester.scss';
10
19
 
11
20
  function Suggester({
@@ -16,23 +25,54 @@ function Suggester({
16
25
  labelRenderer,
17
26
  onSelect,
18
27
  value,
28
+ focused: initFocused,
29
+ response,
30
+ logFunction,
19
31
  }) {
20
32
  const inputEl = useRef();
21
33
  const [state, dispatch] = useContext(SuggesterContext);
22
34
  const { focused, id, messageError, search, disabled } = state;
23
35
 
36
+ const [init, setInit] = useState(false);
37
+
38
+ const createEventFocus = (focusIn = true) =>
39
+ U.createObjectEvent(
40
+ `suggester-${id}`,
41
+ C.INPUT_CATEGORY,
42
+ focusIn ? C.EVENT_FOCUS_IN : C.EVENT_FOCUS_OUT,
43
+ U.getResponseName(response),
44
+ value
45
+ );
46
+
24
47
  const onFocus = useCallback(
25
48
  function () {
26
- if (!disabled) {
49
+ if (!focused && !disabled) {
27
50
  if (inputEl.current !== document.activeElement) {
28
51
  }
29
52
  inputEl.current.focus();
30
53
  dispatch(actions.onFocus());
31
54
  }
32
55
  },
33
- [dispatch, disabled]
56
+ [disabled, dispatch, focused]
34
57
  );
35
58
 
59
+ // Handle focused props of Component
60
+ useEffect(() => {
61
+ if (!init && id) {
62
+ if (initFocused && !focused) onFocus();
63
+ setInit(true);
64
+ }
65
+ }, [focused, init, initFocused, onFocus, id]);
66
+
67
+ // log info when focus change
68
+ useEffect(() => {
69
+ if (init && id && focused && U.isFunction(logFunction))
70
+ logFunction(createEventFocus());
71
+ if (init && id && !focused && U.isFunction(logFunction))
72
+ logFunction(createEventFocus(false));
73
+ // eslint-disable-next-line react-hooks/exhaustive-deps
74
+ }, [focused, id, init]);
75
+
36
76
  const onDelete = useCallback(
37
77
  function () {
38
78
  dispatch(actions.onDeleteSearch());
@@ -1,4 +1,4 @@
1
- import React, { useEffect, useMemo, useState } from 'react';
1
+ import React, { useMemo, useState } from 'react';
2
2
  import PropTypes from 'prop-types';
3
3
  import SuggesterWrapper from './suggester-wrapper';
4
4
  import createSearching from './searching';
@@ -15,6 +15,9 @@ function IDBSuggester({
15
15
  onSelect,
16
16
  disabled,
17
17
  value,
18
+ focused,
19
+ response,
20
+ logFunction,
18
21
  }) {
19
22
  const [store, setStore] = useState(undefined);
20
23
  const searching = useMemo(
@@ -44,6 +47,9 @@ function IDBSuggester({
44
47
  storeName={storeName}
45
48
  disabled={disabled}
46
49
  value={value}
50
+ focused={focused}
51
+ response={response}
52
+ logFunction={logFunction}
47
53
  />
48
54
  </CheckStore>
49
55
  );
@@ -89,6 +89,7 @@ function Suggester({
89
89
  response={response}
90
90
  id={id}
91
91
  value={value}
92
+ logFunction={logFunction}
92
93
  />
93
94
  </FieldWrapper>
94
95
  </LabelWrapper>
@@ -30,6 +30,9 @@ function SuggesterWrapper({
30
30
  labelRenderer,
31
31
  disabled,
32
32
  value,
33
+ focused,
34
+ response,
35
+ logFunction,
33
36
  }) {
34
37
  const [state, dispatch] = useReducer(reducer, INITIAL_STATE);
35
38
  const { search, selectedIndex, options, expended } = state;
@@ -82,6 +85,9 @@ function SuggesterWrapper({
82
85
  labelRenderer={labelRenderer}
83
86
  onSelect={onSelect}
84
87
  value={value}
88
+ focused={focused}
89
+ response={response}
90
+ logFunction={logFunction}
85
91
  />
86
92
  </SuggesterContext.Provider>
87
93
  );