cozy-ui 146.2.2 → 146.3.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 (65) hide show
  1. package/CHANGELOG.md +21 -0
  2. package/package.json +1 -1
  3. package/react/DropdownText/index.jsx +3 -5
  4. package/react/MemberAutocomplete/MemberAutocomplete.spec.jsx +107 -0
  5. package/react/MemberAutocomplete/MemberAutocompleteActions.jsx +77 -0
  6. package/react/MemberAutocomplete/MemberChip.jsx +29 -0
  7. package/react/MemberAutocomplete/MemberSuggestion.jsx +32 -0
  8. package/react/MemberAutocomplete/Readme.md +65 -0
  9. package/react/MemberAutocomplete/helpers.js +70 -0
  10. package/react/MemberAutocomplete/helpers.spec.js +51 -0
  11. package/react/MemberAutocomplete/index.jsx +248 -0
  12. package/react/MemberAutocomplete/locales/de.json +5 -0
  13. package/react/MemberAutocomplete/locales/en.json +5 -0
  14. package/react/MemberAutocomplete/locales/es.json +5 -0
  15. package/react/MemberAutocomplete/locales/fr.json +5 -0
  16. package/react/MemberAutocomplete/locales/index.js +17 -0
  17. package/react/MemberAutocomplete/locales/it.json +5 -0
  18. package/react/MemberAutocomplete/locales/ru.json +5 -0
  19. package/react/MemberAutocomplete/locales/vi.json +5 -0
  20. package/react/MemberAutocomplete/useMemberInput.js +84 -0
  21. package/react/MemberAutocomplete/useMemberSuggestions.js +65 -0
  22. package/react/MemberAutocomplete/useMemberSuggestions.spec.js +97 -0
  23. package/react/MemberAutocomplete/useRoleMenuFocus.js +35 -0
  24. package/react/MemberRow/MemberOrGroupAvatar.jsx +21 -0
  25. package/react/MemberRow/MemberRoleMenu.jsx +29 -4
  26. package/react/MemberRow/MemberRoleMenuHeader.jsx +3 -8
  27. package/react/MemberRow/Readme.md +5 -4
  28. package/react/MemberRow/index.jsx +3 -19
  29. package/react/MemberRow/propTypes.js +1 -0
  30. package/react/MuiCozyTheme/makeTheme.jsx +12 -1
  31. package/transpiled/react/DropdownText/index.js +3 -3
  32. package/transpiled/react/MemberAutocomplete/MemberAutocomplete.spec.d.ts +1 -0
  33. package/transpiled/react/MemberAutocomplete/MemberAutocompleteActions.d.ts +25 -0
  34. package/transpiled/react/MemberAutocomplete/MemberAutocompleteActions.js +69 -0
  35. package/transpiled/react/MemberAutocomplete/MemberChip.d.ts +39 -0
  36. package/transpiled/react/MemberAutocomplete/MemberChip.js +33 -0
  37. package/transpiled/react/MemberAutocomplete/MemberSuggestion.d.ts +36 -0
  38. package/transpiled/react/MemberAutocomplete/MemberSuggestion.js +31 -0
  39. package/transpiled/react/MemberAutocomplete/helpers.d.ts +7 -0
  40. package/transpiled/react/MemberAutocomplete/helpers.js +73 -0
  41. package/transpiled/react/MemberAutocomplete/helpers.spec.d.ts +1 -0
  42. package/transpiled/react/MemberAutocomplete/index.d.ts +71 -0
  43. package/transpiled/react/MemberAutocomplete/index.js +296 -0
  44. package/transpiled/react/MemberAutocomplete/locales/index.d.ts +16 -0
  45. package/transpiled/react/MemberAutocomplete/locales/index.js +44 -0
  46. package/transpiled/react/MemberAutocomplete/useMemberInput.d.ts +15 -0
  47. package/transpiled/react/MemberAutocomplete/useMemberInput.js +79 -0
  48. package/transpiled/react/MemberAutocomplete/useMemberSuggestions.d.ts +11 -0
  49. package/transpiled/react/MemberAutocomplete/useMemberSuggestions.js +120 -0
  50. package/transpiled/react/MemberAutocomplete/useMemberSuggestions.spec.d.ts +1 -0
  51. package/transpiled/react/MemberAutocomplete/useRoleMenuFocus.d.ts +6 -0
  52. package/transpiled/react/MemberAutocomplete/useRoleMenuFocus.js +37 -0
  53. package/transpiled/react/MemberList/index.d.ts +1 -0
  54. package/transpiled/react/MemberRow/MemberOrGroupAvatar.d.ts +39 -0
  55. package/transpiled/react/MemberRow/MemberOrGroupAvatar.js +29 -0
  56. package/transpiled/react/MemberRow/MemberRoleMenu.d.ts +9 -1
  57. package/transpiled/react/MemberRow/MemberRoleMenu.js +26 -9
  58. package/transpiled/react/MemberRow/MemberRoleMenuHeader.d.ts +1 -0
  59. package/transpiled/react/MemberRow/MemberRoleMenuHeader.js +4 -13
  60. package/transpiled/react/MemberRow/MemberRowActions.d.ts +1 -0
  61. package/transpiled/react/MemberRow/index.d.ts +1 -10
  62. package/transpiled/react/MemberRow/index.js +4 -13
  63. package/transpiled/react/MemberRow/propTypes.d.ts +1 -0
  64. package/transpiled/react/MemberRow/propTypes.js +1 -0
  65. package/transpiled/react/MuiCozyTheme/makeTheme.js +15 -2
@@ -0,0 +1,296 @@
1
+ import _extends from "@babel/runtime/helpers/extends";
2
+ import _defineProperty from "@babel/runtime/helpers/defineProperty";
3
+ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
4
+
5
+ function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); enumerableOnly && (symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; })), keys.push.apply(keys, symbols); } return keys; }
6
+
7
+ function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = null != arguments[i] ? arguments[i] : {}; i % 2 ? ownKeys(Object(source), !0).forEach(function (key) { _defineProperty(target, key, source[key]); }) : Object.getOwnPropertyDescriptors ? Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)) : ownKeys(Object(source)).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } return target; }
8
+
9
+ import cx from 'classnames';
10
+ import PropTypes from 'prop-types';
11
+ import React, { useState } from 'react';
12
+ import { useI18n, useExtendI18n } from 'twake-i18n';
13
+ import MemberAutocompleteActions from "cozy-ui/transpiled/react/MemberAutocomplete/MemberAutocompleteActions";
14
+ import MemberChip from "cozy-ui/transpiled/react/MemberAutocomplete/MemberChip";
15
+ import MemberSuggestion from "cozy-ui/transpiled/react/MemberAutocomplete/MemberSuggestion";
16
+ import { getUnpickedMembers } from "cozy-ui/transpiled/react/MemberAutocomplete/helpers";
17
+ import { locales } from "cozy-ui/transpiled/react/MemberAutocomplete/locales";
18
+ import { useMemberInput } from "cozy-ui/transpiled/react/MemberAutocomplete/useMemberInput";
19
+ import { useMemberSuggestions } from "cozy-ui/transpiled/react/MemberAutocomplete/useMemberSuggestions";
20
+ import { useRoleMenuFocus } from "cozy-ui/transpiled/react/MemberAutocomplete/useRoleMenuFocus";
21
+ import Autocomplete from "cozy-ui/transpiled/react/Autocomplete";
22
+ import Buttons from "cozy-ui/transpiled/react/Buttons";
23
+ import { memberPropType, rolesPropType } from "cozy-ui/transpiled/react/MemberRow/propTypes";
24
+ import TextField from "cozy-ui/transpiled/react/TextField";
25
+ import Typography from "cozy-ui/transpiled/react/Typography";
26
+ import { getRandomUUID } from "cozy-ui/transpiled/react/helpers/getRandomUUID";
27
+ import { makeStyles } from "cozy-ui/transpiled/react/styles";
28
+ var LIMIT_TAGS = 3;
29
+ var useStyles = makeStyles({
30
+ inputRoot: {
31
+ '&&': {
32
+ padding: '.375rem .5625rem',
33
+ paddingRight: function paddingRight(_ref) {
34
+ var actionsWidth = _ref.actionsWidth;
35
+ return actionsWidth > 0 ? "calc(".concat(actionsWidth, "px + 1.5rem)") : null;
36
+ }
37
+ }
38
+ },
39
+ input: {
40
+ '&&': {
41
+ padding: '.59375rem .25rem'
42
+ },
43
+ '&&:first-child': {
44
+ paddingLeft: '.4375rem'
45
+ }
46
+ },
47
+ submit: {
48
+ marginTop: '.3125rem'
49
+ },
50
+ listbox: {
51
+ maxHeight: '9rem'
52
+ },
53
+ option: {
54
+ '&[aria-selected="true"]': {
55
+ backgroundColor: 'transparent'
56
+ },
57
+ '&[data-focus="true"], &:active': {
58
+ backgroundColor: 'var(--actionColorSelected)'
59
+ }
60
+ }
61
+ });
62
+ /**
63
+ * Field to pick the members to invite among suggestions, shown as chips
64
+ */
65
+
66
+ var MemberAutocomplete = function MemberAutocomplete(_ref2) {
67
+ var value = _ref2.value,
68
+ _ref2$getSuggestions = _ref2.getSuggestions,
69
+ getSuggestions = _ref2$getSuggestions === void 0 ? function () {
70
+ return [];
71
+ } : _ref2$getSuggestions,
72
+ fetchSuggestions = _ref2.fetchSuggestions,
73
+ _ref2$getMembersFromT = _ref2.getMembersFromText,
74
+ getMembersFromText = _ref2$getMembersFromT === void 0 ? function () {
75
+ return [];
76
+ } : _ref2$getMembersFromT,
77
+ _ref2$minQueryLength = _ref2.minQueryLength,
78
+ minQueryLength = _ref2$minQueryLength === void 0 ? 3 : _ref2$minQueryLength,
79
+ _ref2$debounceMs = _ref2.debounceMs,
80
+ debounceMs = _ref2$debounceMs === void 0 ? 300 : _ref2$debounceMs,
81
+ roles = _ref2.roles,
82
+ role = _ref2.role,
83
+ title = _ref2.title,
84
+ placeholder = _ref2.placeholder,
85
+ _ref2$loading = _ref2.loading,
86
+ loading = _ref2$loading === void 0 ? false : _ref2$loading,
87
+ _ref2$disabled = _ref2.disabled,
88
+ disabled = _ref2$disabled === void 0 ? false : _ref2$disabled,
89
+ _ref2$autoFocus = _ref2.autoFocus,
90
+ autoFocus = _ref2$autoFocus === void 0 ? false : _ref2$autoFocus,
91
+ onChange = _ref2.onChange,
92
+ onRoleChange = _ref2.onRoleChange,
93
+ onSubmit = _ref2.onSubmit;
94
+ useExtendI18n(locales);
95
+
96
+ var _useI18n = useI18n(),
97
+ t = _useI18n.t;
98
+
99
+ var _useState = useState(getRandomUUID),
100
+ _useState2 = _slicedToArray(_useState, 1),
101
+ inputId = _useState2[0];
102
+
103
+ var _useState3 = useState(''),
104
+ _useState4 = _slicedToArray(_useState3, 2),
105
+ inputValue = _useState4[0],
106
+ setInputValue = _useState4[1];
107
+
108
+ var _useState5 = useState(0),
109
+ _useState6 = _slicedToArray(_useState5, 2),
110
+ actionsWidth = _useState6[0],
111
+ setActionsWidth = _useState6[1];
112
+
113
+ var classes = useStyles({
114
+ actionsWidth: actionsWidth
115
+ });
116
+
117
+ var _useMemberSuggestions = useMemberSuggestions({
118
+ inputValue: inputValue,
119
+ getSuggestions: getSuggestions,
120
+ fetchSuggestions: fetchSuggestions,
121
+ getMembersFromText: getMembersFromText,
122
+ minQueryLength: minQueryLength,
123
+ debounceMs: debounceMs
124
+ }),
125
+ suggestions = _useMemberSuggestions.suggestions,
126
+ isFetching = _useMemberSuggestions.isFetching;
127
+
128
+ var _useMemberInput = useMemberInput({
129
+ inputValue: inputValue,
130
+ value: value,
131
+ suggestions: suggestions,
132
+ getMembersFromText: getMembersFromText,
133
+ onInputValueChange: setInputValue,
134
+ onChange: onChange
135
+ }),
136
+ isTextAddedOnBlur = _useMemberInput.isTextAddedOnBlur,
137
+ handleChange = _useMemberInput.handleChange,
138
+ handleInputChange = _useMemberInput.handleInputChange,
139
+ handleKeyDown = _useMemberInput.handleKeyDown,
140
+ handlePaste = _useMemberInput.handlePaste,
141
+ handleBlur = _useMemberInput.handleBlur;
142
+
143
+ var _useRoleMenuFocus = useRoleMenuFocus(inputId),
144
+ isFocusKept = _useRoleMenuFocus.isFocusKept,
145
+ handleRoleMenuOpen = _useRoleMenuFocus.handleRoleMenuOpen,
146
+ handleRoleMenuClose = _useRoleMenuFocus.handleRoleMenuClose,
147
+ handleInputFocus = _useRoleMenuFocus.handleInputFocus;
148
+
149
+ var titleId = "".concat(inputId, "-title");
150
+ var isTitleShown = title !== undefined;
151
+ var isSubmitShown = onSubmit !== undefined;
152
+ var hasMembersToSend = value.length > 0 || isTextAddedOnBlur;
153
+ var isLoading = loading || isFetching;
154
+ var unpickedSuggestions = getUnpickedMembers(suggestions, value);
155
+ var fieldPlaceholder = value.length === 0 ? placeholder : undefined;
156
+ return /*#__PURE__*/React.createElement("div", null, isTitleShown && /*#__PURE__*/React.createElement(Typography, {
157
+ id: titleId,
158
+ variant: "h5",
159
+ className: "u-mb-half"
160
+ }, title), /*#__PURE__*/React.createElement("div", {
161
+ className: "u-flex u-flex-items-start"
162
+ }, /*#__PURE__*/React.createElement(Autocomplete, {
163
+ className: "u-flex-grow-1",
164
+ classes: {
165
+ inputRoot: classes.inputRoot,
166
+ input: classes.input,
167
+ paper: 'u-mv-half u-bdrs-4',
168
+ listbox: cx('u-pv-half', classes.listbox),
169
+ option: cx('u-p-0 u-mih-auto', classes.option)
170
+ },
171
+ id: inputId,
172
+ multiple: true,
173
+ freeSolo: true,
174
+ autoHighlight: true,
175
+ disableClearable: true,
176
+ limitTags: isFocusKept ? -1 : LIMIT_TAGS,
177
+ disabled: disabled,
178
+ options: unpickedSuggestions,
179
+ value: value,
180
+ inputValue: inputValue,
181
+ filterOptions: function filterOptions(allOptions) {
182
+ return allOptions;
183
+ },
184
+ getOptionLabel: function getOptionLabel(option) {
185
+ var _option$name;
186
+
187
+ return (_option$name = option.name) !== null && _option$name !== void 0 ? _option$name : option;
188
+ },
189
+ getOptionSelected: function getOptionSelected(option, picked) {
190
+ return option.id === picked.id;
191
+ },
192
+ renderOption: function renderOption(suggestion) {
193
+ return /*#__PURE__*/React.createElement(MemberSuggestion, {
194
+ suggestion: suggestion
195
+ });
196
+ },
197
+ renderTags: function renderTags(members, getTagProps) {
198
+ return members.map(function (member, index) {
199
+ return /*#__PURE__*/React.createElement(MemberChip, {
200
+ key: member.id,
201
+ member: member,
202
+ tagProps: getTagProps({
203
+ index: index
204
+ })
205
+ });
206
+ });
207
+ },
208
+ renderInput: function renderInput(params) {
209
+ return /*#__PURE__*/React.createElement(TextField, _extends({}, params, {
210
+ variant: "outlined",
211
+ type: "email",
212
+ placeholder: fieldPlaceholder,
213
+ autoFocus: autoFocus,
214
+ InputProps: _objectSpread(_objectSpread({}, params.InputProps), {}, {
215
+ endAdornment: /*#__PURE__*/React.createElement(MemberAutocompleteActions, {
216
+ roles: roles,
217
+ role: role,
218
+ isLoading: isLoading,
219
+ disabled: disabled,
220
+ onRoleChange: onRoleChange,
221
+ onRoleMenuOpen: handleRoleMenuOpen,
222
+ onRoleMenuClose: handleRoleMenuClose,
223
+ onWidthChange: setActionsWidth
224
+ })
225
+ }),
226
+ inputProps: _objectSpread(_objectSpread({}, params.inputProps), {}, {
227
+ 'aria-labelledby': isTitleShown ? titleId : undefined,
228
+ onKeyDown: handleKeyDown,
229
+ onPaste: handlePaste
230
+ }),
231
+ focused: isFocusKept || undefined,
232
+ onFocus: handleInputFocus,
233
+ onBlur: handleBlur
234
+ }));
235
+ },
236
+ onChange: handleChange,
237
+ onInputChange: handleInputChange
238
+ }), isSubmitShown && /*#__PURE__*/React.createElement(Buttons, {
239
+ className: cx('u-ml-1', classes.submit),
240
+ label: t('MemberAutocomplete.send'),
241
+ disabled: disabled || !hasMembersToSend,
242
+ onClick: onSubmit
243
+ })));
244
+ };
245
+
246
+ MemberAutocomplete.propTypes = {
247
+ /** Picked members, see `MemberRow` */
248
+ value: PropTypes.arrayOf(memberPropType).isRequired,
249
+
250
+ /** Returns the local members matching a text */
251
+ getSuggestions: PropTypes.func,
252
+
253
+ /** Resolves with the remote members matching a text, shown before the local ones */
254
+ fetchSuggestions: PropTypes.func,
255
+
256
+ /** Turns a typed or pasted text (e.g. emails) into members, suggested when nothing matches.
257
+ * Give them the `email` of the person, so that a suggested or picked one replaces them */
258
+ getMembersFromText: PropTypes.func,
259
+
260
+ /** Text length from which `fetchSuggestions` is called */
261
+ minQueryLength: PropTypes.number,
262
+
263
+ /** Delay before calling `fetchSuggestions` */
264
+ debounceMs: PropTypes.number,
265
+
266
+ /** Roles the members can get, as `{ value, label }` */
267
+ roles: rolesPropType,
268
+
269
+ /** Role given to the picked members */
270
+ role: PropTypes.string,
271
+
272
+ /** Title shown above the field */
273
+ title: PropTypes.string,
274
+
275
+ /** Placeholder of the field, shown while no member is picked */
276
+ placeholder: PropTypes.string,
277
+
278
+ /** Whether the suggestions are loading */
279
+ loading: PropTypes.bool,
280
+
281
+ /** Whether the field is disabled */
282
+ disabled: PropTypes.bool,
283
+
284
+ /** Whether the field takes the focus */
285
+ autoFocus: PropTypes.bool,
286
+
287
+ /** Called with the picked members */
288
+ onChange: PropTypes.func.isRequired,
289
+
290
+ /** Called with the new role */
291
+ onRoleChange: PropTypes.func,
292
+
293
+ /** Shows a send button calling it */
294
+ onSubmit: PropTypes.func
295
+ };
296
+ export default MemberAutocomplete;
@@ -0,0 +1,16 @@
1
+ export namespace locales {
2
+ export { de };
3
+ export { en };
4
+ export { es };
5
+ export { fr };
6
+ export { it };
7
+ export { ru };
8
+ export { vi };
9
+ }
10
+ import de from "./de.json";
11
+ import en from "./en.json";
12
+ import es from "./es.json";
13
+ import fr from "./fr.json";
14
+ import it from "./it.json";
15
+ import ru from "./ru.json";
16
+ import vi from "./vi.json";
@@ -0,0 +1,44 @@
1
+ var de = {
2
+ MemberAutocomplete: {
3
+ send: "Senden"
4
+ }
5
+ };
6
+ var en = {
7
+ MemberAutocomplete: {
8
+ send: "Send"
9
+ }
10
+ };
11
+ var es = {
12
+ MemberAutocomplete: {
13
+ send: "Enviar"
14
+ }
15
+ };
16
+ var fr = {
17
+ MemberAutocomplete: {
18
+ send: "Envoyer"
19
+ }
20
+ };
21
+ var it = {
22
+ MemberAutocomplete: {
23
+ send: "Invia"
24
+ }
25
+ };
26
+ var ru = {
27
+ MemberAutocomplete: {
28
+ send: "\u041E\u0442\u043F\u0440\u0430\u0432\u0438\u0442\u044C"
29
+ }
30
+ };
31
+ var vi = {
32
+ MemberAutocomplete: {
33
+ send: "G\u1EEDi"
34
+ }
35
+ };
36
+ export var locales = {
37
+ de: de,
38
+ en: en,
39
+ es: es,
40
+ fr: fr,
41
+ it: it,
42
+ ru: ru,
43
+ vi: vi
44
+ };
@@ -0,0 +1,15 @@
1
+ export function useMemberInput({ inputValue, value, suggestions, getMembersFromText, onInputValueChange, onChange }: {
2
+ inputValue: string;
3
+ value: object[];
4
+ suggestions: object[];
5
+ getMembersFromText: Function;
6
+ onInputValueChange: Function;
7
+ onChange: Function;
8
+ }): {
9
+ isTextAddedOnBlur: boolean;
10
+ handleChange: (event: any, newValue: any, reason: any) => void;
11
+ handleInputChange: (event: any, newInputValue: any, reason: any) => void;
12
+ handleKeyDown: (event: any) => void;
13
+ handlePaste: (event: any) => void;
14
+ handleBlur: () => void;
15
+ };
@@ -0,0 +1,79 @@
1
+ import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
2
+ import { getUnpickedMembers, isEmailLike, makeMembersFromValue, resolveKnownMembers } from "cozy-ui/transpiled/react/MemberAutocomplete/helpers";
3
+ /**
4
+ * Turns the typed text into members on Enter, Space, paste and blur. A text giving no member
5
+ * stays typed, and a member for a suggested or picked person is replaced by it.
6
+ *
7
+ * @param {object} params
8
+ * @param {string} params.inputValue - Typed text
9
+ * @param {object[]} params.value - Picked members
10
+ * @param {object[]} params.suggestions - Suggested members
11
+ * @param {Function} params.getMembersFromText - Turns a text into members
12
+ * @param {Function} params.onInputValueChange - Called with the typed text
13
+ * @param {Function} params.onChange - Called with the picked members
14
+ */
15
+
16
+ export var useMemberInput = function useMemberInput(_ref) {
17
+ var inputValue = _ref.inputValue,
18
+ value = _ref.value,
19
+ suggestions = _ref.suggestions,
20
+ getMembersFromText = _ref.getMembersFromText,
21
+ onInputValueChange = _ref.onInputValueChange,
22
+ onChange = _ref.onChange;
23
+
24
+ var getKnownMembersFromText = function getKnownMembersFromText(text) {
25
+ return resolveKnownMembers(getMembersFromText(text), [].concat(_toConsumableArray(value), _toConsumableArray(suggestions)));
26
+ };
27
+
28
+ var addMembersFromText = function addMembersFromText(text) {
29
+ var members = getKnownMembersFromText(text);
30
+ if (members.length === 0) return false;
31
+ onChange([].concat(_toConsumableArray(value), _toConsumableArray(getUnpickedMembers(members, value))));
32
+ return true;
33
+ };
34
+
35
+ var handleChange = function handleChange(event, newValue, reason) {
36
+ var typedText = newValue.find(function (item) {
37
+ return typeof item === 'string';
38
+ });
39
+ var isUnknownText = typedText !== undefined && getKnownMembersFromText(typedText).length === 0;
40
+ if (isUnknownText) return;
41
+ onChange(makeMembersFromValue(newValue, getKnownMembersFromText));
42
+ if (reason !== 'remove-option') onInputValueChange('');
43
+ }; // The Autocomplete resets the text whenever `value` is a new array, even with the same members
44
+
45
+
46
+ var handleInputChange = function handleInputChange(event, newInputValue, reason) {
47
+ if (reason !== 'reset') onInputValueChange(newInputValue);
48
+ };
49
+
50
+ var handleKeyDown = function handleKeyDown(event) {
51
+ if (event.key === ' ' && addMembersFromText(inputValue)) {
52
+ event.preventDefault();
53
+ onInputValueChange('');
54
+ }
55
+ };
56
+
57
+ var handlePaste = function handlePaste(event) {
58
+ if (addMembersFromText(event.clipboardData.getData('text'))) {
59
+ event.preventDefault();
60
+ }
61
+ };
62
+
63
+ var isTextAddedOnBlur = isEmailLike(inputValue) && getKnownMembersFromText(inputValue).length > 0;
64
+
65
+ var handleBlur = function handleBlur() {
66
+ if (isTextAddedOnBlur && addMembersFromText(inputValue)) {
67
+ onInputValueChange('');
68
+ }
69
+ };
70
+
71
+ return {
72
+ isTextAddedOnBlur: isTextAddedOnBlur,
73
+ handleChange: handleChange,
74
+ handleInputChange: handleInputChange,
75
+ handleKeyDown: handleKeyDown,
76
+ handlePaste: handlePaste,
77
+ handleBlur: handleBlur
78
+ };
79
+ };
@@ -0,0 +1,11 @@
1
+ export function useMemberSuggestions({ inputValue, getSuggestions, fetchSuggestions, getMembersFromText, minQueryLength, debounceMs }: {
2
+ inputValue: string;
3
+ getSuggestions: Function;
4
+ fetchSuggestions?: Function | undefined;
5
+ getMembersFromText: Function;
6
+ minQueryLength: number;
7
+ debounceMs: number;
8
+ }): {
9
+ suggestions: object[];
10
+ isFetching: boolean;
11
+ };
@@ -0,0 +1,120 @@
1
+ import _toConsumableArray from "@babel/runtime/helpers/toConsumableArray";
2
+ import _asyncToGenerator from "@babel/runtime/helpers/asyncToGenerator";
3
+ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
4
+ import _regeneratorRuntime from "@babel/runtime/regenerator";
5
+ import { useEffect, useRef, useState } from 'react';
6
+ import { makeSuggestions } from "cozy-ui/transpiled/react/MemberAutocomplete/helpers";
7
+ /**
8
+ * Computes the members to suggest for the typed text. The local ones and the ones made
9
+ * from the text are always up to date. The fetched ones come first once `fetchSuggestions`
10
+ * answers for the current text.
11
+ *
12
+ * @param {object} params
13
+ * @param {string} params.inputValue - Typed text
14
+ * @param {Function} params.getSuggestions - Returns the local members matching a text
15
+ * @param {Function} [params.fetchSuggestions] - Resolves with the remote members matching a text
16
+ * @param {Function} params.getMembersFromText - Turns a text into members, suggested when nothing matches
17
+ * @param {number} params.minQueryLength - Text length from which `fetchSuggestions` is called
18
+ * @param {number} params.debounceMs - Delay before calling `fetchSuggestions`
19
+ * @returns {{ suggestions: object[], isFetching: boolean }}
20
+ */
21
+
22
+ export var useMemberSuggestions = function useMemberSuggestions(_ref) {
23
+ var inputValue = _ref.inputValue,
24
+ getSuggestions = _ref.getSuggestions,
25
+ fetchSuggestions = _ref.fetchSuggestions,
26
+ getMembersFromText = _ref.getMembersFromText,
27
+ minQueryLength = _ref.minQueryLength,
28
+ debounceMs = _ref.debounceMs;
29
+
30
+ var _useState = useState({
31
+ query: '',
32
+ members: []
33
+ }),
34
+ _useState2 = _slicedToArray(_useState, 2),
35
+ fetched = _useState2[0],
36
+ setFetched = _useState2[1];
37
+
38
+ var fetchSuggestionsRef = useRef();
39
+ fetchSuggestionsRef.current = fetchSuggestions;
40
+ var query = inputValue.trim();
41
+ var isRemoteQuery = fetchSuggestions !== undefined && query.length >= minQueryLength;
42
+ var isFetching = isRemoteQuery && fetched.query !== query;
43
+ useEffect(function () {
44
+ if (!isRemoteQuery) return;
45
+ var isOutdated = false;
46
+ var timeout = setTimeout( /*#__PURE__*/_asyncToGenerator( /*#__PURE__*/_regeneratorRuntime.mark(function _callee() {
47
+ var members, _yield$fetchSuggestio;
48
+
49
+ return _regeneratorRuntime.wrap(function _callee$(_context) {
50
+ while (1) {
51
+ switch (_context.prev = _context.next) {
52
+ case 0:
53
+ members = [];
54
+ _context.prev = 1;
55
+ _context.next = 4;
56
+ return fetchSuggestionsRef.current(query);
57
+
58
+ case 4:
59
+ _context.t1 = _yield$fetchSuggestio = _context.sent;
60
+ _context.t0 = _context.t1 !== null;
61
+
62
+ if (!_context.t0) {
63
+ _context.next = 8;
64
+ break;
65
+ }
66
+
67
+ _context.t0 = _yield$fetchSuggestio !== void 0;
68
+
69
+ case 8:
70
+ if (!_context.t0) {
71
+ _context.next = 12;
72
+ break;
73
+ }
74
+
75
+ _context.t2 = _yield$fetchSuggestio;
76
+ _context.next = 13;
77
+ break;
78
+
79
+ case 12:
80
+ _context.t2 = [];
81
+
82
+ case 13:
83
+ members = _context.t2;
84
+ _context.next = 19;
85
+ break;
86
+
87
+ case 16:
88
+ _context.prev = 16;
89
+ _context.t3 = _context["catch"](1);
90
+ members = [];
91
+
92
+ case 19:
93
+ if (!isOutdated) setFetched({
94
+ query: query,
95
+ members: members
96
+ });
97
+
98
+ case 20:
99
+ case "end":
100
+ return _context.stop();
101
+ }
102
+ }
103
+ }, _callee, null, [[1, 16]]);
104
+ })), debounceMs);
105
+ return function () {
106
+ isOutdated = true;
107
+ clearTimeout(timeout);
108
+ };
109
+ }, [query, isRemoteQuery, debounceMs]);
110
+ if (query.length === 0) return {
111
+ suggestions: [],
112
+ isFetching: false
113
+ };
114
+ var fetchedSuggestions = fetched.query === query ? fetched.members : [];
115
+ var suggestions = makeSuggestions([].concat(_toConsumableArray(fetchedSuggestions), _toConsumableArray(getSuggestions(query))), getMembersFromText(query));
116
+ return {
117
+ suggestions: suggestions,
118
+ isFetching: isFetching
119
+ };
120
+ };
@@ -0,0 +1,6 @@
1
+ export function useRoleMenuFocus(inputId: string): {
2
+ isFocusKept: boolean;
3
+ handleRoleMenuOpen: () => void;
4
+ handleRoleMenuClose: () => void;
5
+ handleInputFocus: () => void;
6
+ };
@@ -0,0 +1,37 @@
1
+ import _slicedToArray from "@babel/runtime/helpers/slicedToArray";
2
+ import { useState } from 'react';
3
+ /**
4
+ * Keeps the field shown as focused while the role menu, opened from the focused input,
5
+ * is open. On close, the input gets the focus back if the menu took it.
6
+ *
7
+ * @param {string} inputId - Id of the input
8
+ */
9
+
10
+ export var useRoleMenuFocus = function useRoleMenuFocus(inputId) {
11
+ var _useState = useState(false),
12
+ _useState2 = _slicedToArray(_useState, 2),
13
+ isFocusKept = _useState2[0],
14
+ setFocusKept = _useState2[1];
15
+
16
+ var handleRoleMenuOpen = function handleRoleMenuOpen() {
17
+ setFocusKept(document.activeElement.id === inputId);
18
+ }; // A menu shown as a bottom sheet on mobile leaves the focus on the input
19
+
20
+
21
+ var handleRoleMenuClose = function handleRoleMenuClose() {
22
+ if (!isFocusKept) return;
23
+ var input = document.getElementById(inputId);
24
+ if (document.activeElement === input) setFocusKept(false);else input.focus();
25
+ };
26
+
27
+ var handleInputFocus = function handleInputFocus() {
28
+ setFocusKept(false);
29
+ };
30
+
31
+ return {
32
+ isFocusKept: isFocusKept,
33
+ handleRoleMenuOpen: handleRoleMenuOpen,
34
+ handleRoleMenuClose: handleRoleMenuClose,
35
+ handleInputFocus: handleInputFocus
36
+ };
37
+ };
@@ -25,6 +25,7 @@ declare namespace MemberList {
25
25
  id: PropTypes.Validator<string>;
26
26
  name: PropTypes.Requireable<string>;
27
27
  subtitle: PropTypes.Requireable<PropTypes.ReactNodeLike>;
28
+ email: PropTypes.Requireable<string>;
28
29
  avatarUrl: PropTypes.Requireable<string>;
29
30
  initials: PropTypes.Requireable<string>;
30
31
  color: PropTypes.Requireable<string>;
@@ -0,0 +1,39 @@
1
+ export default MemberOrGroupAvatar;
2
+ declare function MemberOrGroupAvatar({ member, size }: {
3
+ member: any;
4
+ size: any;
5
+ }): JSX.Element;
6
+ declare namespace MemberOrGroupAvatar {
7
+ namespace propTypes {
8
+ const member: PropTypes.Validator<PropTypes.InferProps<{
9
+ id: PropTypes.Validator<string>;
10
+ name: PropTypes.Requireable<string>;
11
+ subtitle: PropTypes.Requireable<PropTypes.ReactNodeLike>;
12
+ email: PropTypes.Requireable<string>;
13
+ avatarUrl: PropTypes.Requireable<string>;
14
+ initials: PropTypes.Requireable<string>;
15
+ color: PropTypes.Requireable<string>;
16
+ isGroup: PropTypes.Requireable<boolean>;
17
+ isOwner: PropTypes.Requireable<boolean>;
18
+ isCurrentUser: PropTypes.Requireable<boolean>;
19
+ role: PropTypes.Requireable<string>;
20
+ roles: PropTypes.Requireable<(PropTypes.InferProps<{
21
+ value: PropTypes.Validator<string>;
22
+ label: PropTypes.Validator<string>;
23
+ }> | null)[]>;
24
+ canChangeRole: PropTypes.Requireable<boolean>;
25
+ canRemove: PropTypes.Requireable<boolean>;
26
+ removeIcon: PropTypes.Requireable<object>;
27
+ removeLabel: PropTypes.Requireable<string>;
28
+ action: PropTypes.Requireable<PropTypes.InferProps<{
29
+ label: PropTypes.Validator<string>;
30
+ onClick: PropTypes.Validator<(...args: any[]) => any>;
31
+ }>>;
32
+ isPending: PropTypes.Requireable<boolean>;
33
+ onClick: PropTypes.Requireable<(...args: any[]) => any>;
34
+ data: PropTypes.Requireable<any>;
35
+ }>>;
36
+ const size: PropTypes.Validator<string>;
37
+ }
38
+ }
39
+ import PropTypes from "prop-types";