cozy-ui-plus 5.1.1 → 5.2.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 (37) hide show
  1. package/CHANGELOG.md +17 -0
  2. package/dist/Contacts/AddModal/ContactForm/FieldInput.js +4 -0
  3. package/dist/Contacts/AddModal/ContactForm/FieldInputAccordion.js +2 -0
  4. package/dist/Contacts/AddModal/ContactForm/FieldInputArray.js +10 -4
  5. package/dist/Contacts/AddModal/ContactForm/FieldInputLayout.js +11 -9
  6. package/dist/Contacts/AddModal/ContactForm/FieldInputWrapper.js +5 -1
  7. package/dist/Contacts/AddModal/ContactForm/TextFieldCustomLabelSelect.js +7 -1
  8. package/dist/Contacts/AddModal/ContactForm/TextFieldPhone/index.js +17 -3
  9. package/dist/Contacts/AddModal/ContactForm/fieldsConfig.js +0 -5
  10. package/dist/Contacts/AddModal/ContactForm/formValuesToContact.js +1 -1
  11. package/dist/Contacts/AddModal/ContactForm/helpers.js +46 -2
  12. package/dist/Contacts/AddModal/ContactForm/index.js +2 -0
  13. package/dist/Contacts/AddModal/types.js +1 -0
  14. package/dist/src/Contacts/AddModal/ContactForm/FieldInput.d.ts +3 -1
  15. package/dist/src/Contacts/AddModal/ContactForm/FieldInputAccordion.d.ts +2 -1
  16. package/dist/src/Contacts/AddModal/ContactForm/FieldInputArray.d.ts +2 -1
  17. package/dist/src/Contacts/AddModal/ContactForm/FieldInputLayout.d.ts +4 -8
  18. package/dist/src/Contacts/AddModal/ContactForm/FieldInputWrapper.d.ts +5 -1
  19. package/dist/src/Contacts/AddModal/ContactForm/TextFieldCustomLabelSelect.d.ts +4 -1
  20. package/dist/src/Contacts/AddModal/ContactForm/TextFieldPhone/index.d.ts +5 -1
  21. package/dist/src/Contacts/AddModal/ContactForm/helpers.d.ts +12 -2
  22. package/dist/src/Contacts/AddModal/ContactForm/index.d.ts +2 -1
  23. package/dist/src/Contacts/AddModal/types.d.ts +1 -0
  24. package/package.json +2 -2
  25. package/src/Contacts/AddModal/ContactForm/FieldInput.jsx +4 -0
  26. package/src/Contacts/AddModal/ContactForm/FieldInputAccordion.jsx +2 -0
  27. package/src/Contacts/AddModal/ContactForm/FieldInputArray.jsx +7 -2
  28. package/src/Contacts/AddModal/ContactForm/FieldInputLayout.jsx +8 -3
  29. package/src/Contacts/AddModal/ContactForm/FieldInputWrapper.jsx +8 -1
  30. package/src/Contacts/AddModal/ContactForm/TextFieldCustomLabelSelect.jsx +5 -0
  31. package/src/Contacts/AddModal/ContactForm/TextFieldPhone/index.jsx +22 -2
  32. package/src/Contacts/AddModal/ContactForm/fieldsConfig.jsx +0 -5
  33. package/src/Contacts/AddModal/ContactForm/formValuesToContact.js +2 -1
  34. package/src/Contacts/AddModal/ContactForm/helpers.js +37 -0
  35. package/src/Contacts/AddModal/ContactForm/helpers.spec.js +40 -0
  36. package/src/Contacts/AddModal/ContactForm/index.jsx +2 -0
  37. package/src/Contacts/AddModal/types.js +1 -0
package/CHANGELOG.md CHANGED
@@ -3,6 +3,23 @@
3
3
  All notable changes to this project will be documented in this file.
4
4
  See [Conventional Commits](https://conventionalcommits.org) for commit guidelines.
5
5
 
6
+ ## [5.2.1](https://github.com/cozy/cozy-libs/compare/cozy-ui-plus@5.2.0...cozy-ui-plus@5.2.1) (2026-03-09)
7
+
8
+ ### Bug Fixes
9
+
10
+ - **cozy-ui-plus:** Only country code phone number is now ignored ([d7aedf8](https://github.com/cozy/cozy-libs/commit/d7aedf8a4f0c21e9b433c94fd2f4c93745d2ca22))
11
+
12
+ # [5.2.0](https://github.com/cozy/cozy-libs/compare/cozy-ui-plus@5.1.1...cozy-ui-plus@5.2.0) (2026-03-09)
13
+
14
+ ### Bug Fixes
15
+
16
+ - **cozy-ui-plus:** Remove useless name on label field in ContactForm ([6769cf4](https://github.com/cozy/cozy-libs/commit/6769cf451d4388ea4db07ef34dce5ee9e4168253))
17
+
18
+ ### Features
19
+
20
+ - **cozy-ui-plus:** Add disable on ContactForm field ([56a0000](https://github.com/cozy/cozy-libs/commit/56a0000f0b457aa12c5d3725e67197c61e774e7b))
21
+ - **cozy-ui-plus:** Spread Contact in ContactForm ([e0f5279](https://github.com/cozy/cozy-libs/commit/e0f52797e922daffbd1264af454d093b75f6baf0))
22
+
6
23
  ## [5.1.1](https://github.com/cozy/cozy-libs/compare/cozy-ui-plus@5.1.0...cozy-ui-plus@5.1.1) (2026-03-05)
7
24
 
8
25
  **Note:** Version bump only for package cozy-ui-plus
@@ -53,6 +53,7 @@ var FieldInput = function FieldInput(_ref) {
53
53
  subFields = _ref$attributes.subFields,
54
54
  restAttributes = (0, _objectWithoutProperties2.default)(_ref$attributes, _excluded),
55
55
  contacts = _ref.contacts,
56
+ contact = _ref.contact,
56
57
  error = _ref.error,
57
58
  helperText = _ref.helperText,
58
59
  label = _ref.label,
@@ -109,6 +110,7 @@ var FieldInput = function FieldInput(_ref) {
109
110
  id: id,
110
111
  attributes: restAttributes,
111
112
  name: name,
113
+ contact: contact,
112
114
  component: _FieldInputWrapper.default,
113
115
  onFocus: onFocus,
114
116
  onClick: handleClick
@@ -133,6 +135,7 @@ var FieldInput = function FieldInput(_ref) {
133
135
  attributes: labelProps,
134
136
  name: "".concat(name, "Label"),
135
137
  label: t('Contacts.AddModal.ContactForm.fields.label'),
138
+ contact: contact,
136
139
  component: _FieldInputWrapper.default,
137
140
  onFocus: onFocus
138
141
  }))));
@@ -149,6 +152,7 @@ FieldInput.propTypes = {
149
152
  contacts: _propTypes.default.shape({
150
153
  data: _propTypes.default.arrayOf(_propTypes.default.object)
151
154
  }),
155
+ contact: _propTypes.default.object,
152
156
  // Destructuring props
153
157
  id: _propTypes.default.string,
154
158
  label: _propTypes.default.string
@@ -41,6 +41,7 @@ var FieldInputAccordion = function FieldInputAccordion(_ref) {
41
41
  subFields = _ref$attributes.subFields,
42
42
  restAttributes = (0, _objectWithoutProperties2.default)(_ref$attributes, _excluded),
43
43
  contacts = _ref.contacts,
44
+ contact = _ref.contact,
44
45
  error = _ref.error,
45
46
  helperText = _ref.helperText;
46
47
  (0, _twakeI18n.useExtendI18n)(_locales.locales);
@@ -58,6 +59,7 @@ var FieldInputAccordion = function FieldInputAccordion(_ref) {
58
59
  }, /*#__PURE__*/_react.default.createElement(_FieldInput.default, {
59
60
  attributes: restAttributes,
60
61
  contacts: contacts,
62
+ contact: contact,
61
63
  error: error,
62
64
  helperText: helperText,
63
65
  name: name,
@@ -43,6 +43,7 @@ var FieldInputArray = function FieldInputArray(_ref) {
43
43
  label = _ref$attributes.label,
44
44
  restAttributes = (0, _objectWithoutProperties2.default)(_ref$attributes, _excluded),
45
45
  contacts = _ref.contacts,
46
+ contact = _ref.contact,
46
47
  formProps = _ref.formProps;
47
48
  (0, _twakeI18n.useExtendI18n)(_locales.locales);
48
49
 
@@ -50,16 +51,20 @@ var FieldInputArray = function FieldInputArray(_ref) {
50
51
  t = _useI18n.t;
51
52
 
52
53
  var errors = formProps.errors;
54
+ var disabled = restAttributes.disabled,
55
+ isDisabled = restAttributes.isDisabled;
53
56
  return /*#__PURE__*/_react.default.createElement(_reactFinalFormArrays.FieldArray, {
54
57
  name: name
55
58
  }, function (_ref2) {
56
59
  var fields = _ref2.fields;
57
60
  return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, fields.map(function (nameWithIndex, index) {
58
- var _fields$value$index, _fields$value$index2;
59
-
60
- var key = ((_fields$value$index = fields.value[index]) === null || _fields$value$index === void 0 ? void 0 : _fields$value$index.fieldId) || nameWithIndex;
61
- var showRemove = (_fields$value$index2 = fields.value[index]) === null || _fields$value$index2 === void 0 ? void 0 : _fields$value$index2[name];
61
+ var field = fields.value[index];
62
+ var key = (field === null || field === void 0 ? void 0 : field.fieldId) || nameWithIndex;
62
63
  var inputName = "".concat(nameWithIndex, ".").concat(name);
64
+
65
+ var _disabled = disabled || (isDisabled === null || isDisabled === void 0 ? void 0 : isDisabled(inputName, contact));
66
+
67
+ var showRemove = (field === null || field === void 0 ? void 0 : field[name]) && !_disabled;
63
68
  var isError = (0, _helpers.makeIsRequiredError)(restAttributes.required, formProps);
64
69
  return /*#__PURE__*/_react.default.createElement("div", {
65
70
  key: key,
@@ -69,6 +74,7 @@ var FieldInputArray = function FieldInputArray(_ref) {
69
74
  }, /*#__PURE__*/_react.default.createElement(_FieldInput.default, {
70
75
  attributes: restAttributes,
71
76
  contacts: contacts,
77
+ contact: contact,
72
78
  error: isError,
73
79
  helperText: isError ? errors[inputName] : null,
74
80
  name: inputName,
@@ -29,17 +29,12 @@ var _helpers = require("./helpers");
29
29
 
30
30
  var _locales = require("./locales");
31
31
 
32
- var _excluded = ["layout", "icon", "isSecondary", "validate"],
33
- _excluded2 = ["name", "label"];
32
+ var _excluded = ["name", "label", "layout", "icon", "isSecondary"];
34
33
 
35
34
  var FieldInputLayout = function FieldInputLayout(_ref) {
36
- var _ref$attributes = _ref.attributes,
37
- layout = _ref$attributes.layout,
38
- icon = _ref$attributes.icon,
39
- isSecondary = _ref$attributes.isSecondary,
40
- validate = _ref$attributes.validate,
41
- attributes = (0, _objectWithoutProperties2.default)(_ref$attributes, _excluded),
35
+ var attributes = _ref.attributes,
42
36
  contacts = _ref.contacts,
37
+ contact = _ref.contact,
43
38
  showSecondaryFields = _ref.showSecondaryFields,
44
39
  formProps = _ref.formProps;
45
40
  (0, _twakeI18n.useExtendI18n)(_locales.locales);
@@ -50,7 +45,10 @@ var FieldInputLayout = function FieldInputLayout(_ref) {
50
45
  var errors = formProps.errors;
51
46
  var name = attributes.name,
52
47
  label = attributes.label,
53
- restAttributes = (0, _objectWithoutProperties2.default)(attributes, _excluded2);
48
+ layout = attributes.layout,
49
+ icon = attributes.icon,
50
+ isSecondary = attributes.isSecondary,
51
+ restAttributes = (0, _objectWithoutProperties2.default)(attributes, _excluded);
54
52
  var isError = (0, _helpers.makeIsRequiredError)(restAttributes.required, formProps);
55
53
  return /*#__PURE__*/_react.default.createElement("div", {
56
54
  className: (0, _classnames.default)('u-mt-1', {
@@ -69,15 +67,18 @@ var FieldInputLayout = function FieldInputLayout(_ref) {
69
67
  }, layout === 'array' ? /*#__PURE__*/_react.default.createElement(_FieldInputArray.default, {
70
68
  attributes: attributes,
71
69
  contacts: contacts,
70
+ contact: contact,
72
71
  formProps: formProps
73
72
  }) : layout === 'accordion' ? /*#__PURE__*/_react.default.createElement(_FieldInputAccordion.default, {
74
73
  attributes: attributes,
75
74
  contacts: contacts,
75
+ contact: contact,
76
76
  error: isError,
77
77
  helperText: isError ? errors[name] : null
78
78
  }) : /*#__PURE__*/_react.default.createElement(_FieldInput.default, {
79
79
  attributes: restAttributes,
80
80
  contacts: contacts,
81
+ contact: contact,
81
82
  error: isError,
82
83
  helperText: isError ? errors[name] : null,
83
84
  name: name,
@@ -91,6 +92,7 @@ FieldInputLayout.propTypes = {
91
92
  contacts: _propTypes.default.shape({
92
93
  data: _propTypes.default.arrayOf(_propTypes.default.object)
93
94
  }),
95
+ contact: _propTypes.default.object,
94
96
  formProps: _propTypes.default.object
95
97
  };
96
98
  var _default = FieldInputLayout;
@@ -21,7 +21,7 @@ var _TextFieldSelect = _interopRequireDefault(require("./TextFieldSelect"));
21
21
 
22
22
  var _types = require("../types");
23
23
 
24
- var _excluded = ["component"],
24
+ var _excluded = ["component", "layout", "icon", "isSecondary", "validate"],
25
25
  _excluded2 = ["input", "attributes", "variant", "fullWidth"];
26
26
 
27
27
  // component used to flatten props to ensure compatibility
@@ -30,6 +30,10 @@ var FieldInputWrapper = function FieldInputWrapper(_ref) {
30
30
  var input = _ref.input,
31
31
  _ref$attributes = _ref.attributes,
32
32
  component = _ref$attributes.component,
33
+ layout = _ref$attributes.layout,
34
+ icon = _ref$attributes.icon,
35
+ isSecondary = _ref$attributes.isSecondary,
36
+ validate = _ref$attributes.validate,
33
37
  restAttributes = (0, _objectWithoutProperties2.default)(_ref$attributes, _excluded),
34
38
  variant = _ref.variant,
35
39
  fullWidth = _ref.fullWidth,
@@ -27,7 +27,7 @@ var _CustomLabelDialog = _interopRequireDefault(require("../CustomLabelDialog"))
27
27
 
28
28
  var _types = require("../types");
29
29
 
30
- var _excluded = ["name", "value", "options", "customLabelOptions", "onChange"];
30
+ var _excluded = ["name", "value", "options", "disabled", "isDisabled", "contact", "customLabelOptions", "onChange"];
31
31
 
32
32
  function _getRequireWildcardCache(nodeInterop) { if (typeof WeakMap !== "function") return null; var cacheBabelInterop = new WeakMap(); var cacheNodeInterop = new WeakMap(); return (_getRequireWildcardCache = function _getRequireWildcardCache(nodeInterop) { return nodeInterop ? cacheNodeInterop : cacheBabelInterop; })(nodeInterop); }
33
33
 
@@ -37,6 +37,9 @@ var TextFieldCustomLabelSelect = function TextFieldCustomLabelSelect(_ref) {
37
37
  var name = _ref.name,
38
38
  value = _ref.value,
39
39
  options = _ref.options,
40
+ disabled = _ref.disabled,
41
+ isDisabled = _ref.isDisabled,
42
+ contact = _ref.contact,
40
43
  customLabelOptions = _ref.customLabelOptions,
41
44
  _onChange = _ref.onChange,
42
45
  props = (0, _objectWithoutProperties2.default)(_ref, _excluded);
@@ -77,10 +80,13 @@ var TextFieldCustomLabelSelect = function TextFieldCustomLabelSelect(_ref) {
77
80
 
78
81
  var _options = options.concat(customOption);
79
82
 
83
+ var _disabled = disabled || (isDisabled === null || isDisabled === void 0 ? void 0 : isDisabled(name, contact));
84
+
80
85
  return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_TextFieldSelect.default, (0, _extends2.default)({}, props, {
81
86
  name: name,
82
87
  value: value,
83
88
  options: _options,
89
+ disabled: _disabled,
84
90
  onChange: function onChange(ev) {
85
91
  if (ev.target.value === 'skip') {
86
92
  return;
@@ -23,12 +23,18 @@ var _Breakpoints = require("cozy-ui/transpiled/react/providers/Breakpoints");
23
23
 
24
24
  var _FlagBottomSheet = _interopRequireDefault(require("./FlagBottomSheet"));
25
25
 
26
+ var _FlagImage = _interopRequireDefault(require("./FlagImage"));
27
+
26
28
  var _FlagMenu = _interopRequireDefault(require("./FlagMenu"));
27
29
 
28
- var _excluded = ["value", "onChange"];
30
+ var _excluded = ["name", "value", "disabled", "isDisabled", "contact", "onChange"];
29
31
 
30
32
  var TextFieldPhone = function TextFieldPhone(_ref) {
31
- var value = _ref.value,
33
+ var name = _ref.name,
34
+ value = _ref.value,
35
+ disabled = _ref.disabled,
36
+ isDisabled = _ref.isDisabled,
37
+ contact = _ref.contact,
32
38
  _onChange = _ref.onChange,
33
39
  props = (0, _objectWithoutProperties2.default)(_ref, _excluded);
34
40
 
@@ -50,13 +56,21 @@ var TextFieldPhone = function TextFieldPhone(_ref) {
50
56
  setCountry = _usePhoneInput.setCountry;
51
57
 
52
58
  var ResponsiveFlagMenu = isMobile ? _FlagBottomSheet.default : _FlagMenu.default;
59
+
60
+ var _disabled = disabled || (isDisabled === null || isDisabled === void 0 ? void 0 : isDisabled(name, contact));
61
+
53
62
  return /*#__PURE__*/_react.default.createElement(_TextField.default, (0, _extends2.default)({
63
+ name: name,
54
64
  value: inputValue,
55
65
  inputRef: inputRef,
66
+ disabled: _disabled,
56
67
  InputProps: {
57
68
  startAdornment: /*#__PURE__*/_react.default.createElement(_InputAdornment.default, {
58
69
  position: "start"
59
- }, /*#__PURE__*/_react.default.createElement(ResponsiveFlagMenu, {
70
+ }, _disabled ? /*#__PURE__*/_react.default.createElement(_FlagImage.default, {
71
+ className: "u-ml-half",
72
+ iso2: country.iso2
73
+ }) : /*#__PURE__*/_react.default.createElement(ResponsiveFlagMenu, {
60
74
  value: country.iso2,
61
75
  setCountry: setCountry
62
76
  }))
@@ -86,7 +86,6 @@ var fields = [{
86
86
  layout: 'array',
87
87
  component: _index.default,
88
88
  label: {
89
- name: 'phoneLabel',
90
89
  select: true,
91
90
  customLabelOptions: {
92
91
  defaultType: '',
@@ -121,7 +120,6 @@ var fields = [{
121
120
  type: 'email',
122
121
  layout: 'array',
123
122
  label: {
124
- name: 'emailLabel',
125
123
  select: true,
126
124
  customLabelOptions: {
127
125
  defaultType: '',
@@ -200,7 +198,6 @@ var fields = [{
200
198
  type: 'text'
201
199
  }],
202
200
  label: {
203
- name: 'addressLabel',
204
201
  select: true,
205
202
  customLabelOptions: {
206
203
  defaultType: '',
@@ -228,7 +225,6 @@ var fields = [{
228
225
  type: 'url',
229
226
  isSecondary: true,
230
227
  label: {
231
- name: 'cozyLabel',
232
228
  select: true,
233
229
  customLabelOptions: {
234
230
  defaultType: '',
@@ -273,7 +269,6 @@ var fields = [{
273
269
  }))
274
270
  },
275
271
  label: {
276
- name: 'relatedContactLabel',
277
272
  select: true,
278
273
  options: [{
279
274
  value: '',
@@ -76,7 +76,7 @@ var formValuesToContact = function formValuesToContact(_ref) {
76
76
  t: t
77
77
  }),
78
78
  phone: phone ? phone.filter(function (val) {
79
- return val && val.phone;
79
+ return val !== null && val !== void 0 && val.phone ? (0, _helpers.excludedCountryCode)(val) : undefined;
80
80
  }).map(function (_ref3, index) {
81
81
  var phone = _ref3.phone,
82
82
  phoneLabel = _ref3.phoneLabel;
@@ -5,7 +5,7 @@ var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefau
5
5
  Object.defineProperty(exports, "__esModule", {
6
6
  value: true
7
7
  });
8
- exports.validateFields = exports.removeRelatedContactRelationships = exports.removeField = exports.removeAsscociatedData = exports.moveToHead = exports.movePrimaryToHead = exports.makeTypeAndLabel = exports.makeRelatedContact = exports.makeItemLabel = exports.makeIsRequiredError = exports.makeInitialCustomValue = exports.makeImppValues = exports.makeFields = exports.makeCustomLabel = exports.initializationFieldValues = exports.hasNoValues = exports.hasExtendedAddress = exports.getRelatedContactRelationships = exports.getFirstValueIfArray = exports.createAddress = exports.addField = void 0;
8
+ exports.validateFields = exports.removeRelatedContactRelationships = exports.removeField = exports.removeAsscociatedData = exports.moveToHead = exports.movePrimaryToHead = exports.makeTypeAndLabel = exports.makeRelatedContact = exports.makeItemLabel = exports.makeIsRequiredError = exports.makeInitialCustomValue = exports.makeImppValues = exports.makeFields = exports.makeCustomLabel = exports.initializationFieldValues = exports.hasNoValues = exports.hasExtendedAddress = exports.getRelatedContactRelationships = exports.getFirstValueIfArray = exports.excludedCountryCode = exports.createAddress = exports.addField = void 0;
9
9
 
10
10
  var _slicedToArray2 = _interopRequireDefault(require("@babel/runtime/helpers/slicedToArray"));
11
11
 
@@ -23,6 +23,8 @@ var _merge = _interopRequireDefault(require("lodash/merge"));
23
23
 
24
24
  var _uniqueId = _interopRequireDefault(require("lodash/uniqueId"));
25
25
 
26
+ var _reactInternationalPhone = require("react-international-phone");
27
+
26
28
  var _cozyClient = require("cozy-client");
27
29
 
28
30
  var _contact = require("cozy-client/dist/models/contact");
@@ -165,6 +167,14 @@ var hasExtendedAddress = function hasExtendedAddress(addressField) {
165
167
  return extendedAddressKeys.includes(ext);
166
168
  });
167
169
  };
170
+ /**
171
+ * Items matching the given predicate function `shouldBeHead`
172
+ * are moved to the start of the array, preserving the order of the others.
173
+ *
174
+ * @param {Function} shouldBeHead - A predicate function that takes an item and returns true if it should be moved to the head of the array.
175
+ * @returns {Function} A function that takes an array of items and returns a new array with the matching item(s) moved to the front.
176
+ */
177
+
168
178
 
169
179
  exports.hasExtendedAddress = hasExtendedAddress;
170
180
 
@@ -175,6 +185,14 @@ var moveToHead = function moveToHead(shouldBeHead) {
175
185
  }, []);
176
186
  };
177
187
  };
188
+ /**
189
+ * Moves items with the `primary` property set to true to the head of the array.
190
+ *
191
+ * @function
192
+ * @param {Array<Object>} items - The input array of items, each item optionally having a `primary` property.
193
+ * @returns {Array<Object>} The reordered array with 'primary' items at the front.
194
+ */
195
+
178
196
 
179
197
  exports.moveToHead = moveToHead;
180
198
  var movePrimaryToHead = moveToHead(function (v) {
@@ -543,5 +561,31 @@ var makeFields = function makeFields(customFields, defaultFields) {
543
561
  });
544
562
  return fields;
545
563
  };
564
+ /**
565
+ * Excludes phone numbers that consist only of a country code.
566
+ * If the provided phone value matches only a country code (e.g., "+33"),
567
+ * returns undefined. Otherwise, returns the phone value.
568
+ *
569
+ * @param {Object} val - An object containing the phone number.
570
+ * @param {string} val.phone - The phone number string, possibly starting with "+" and a country code.
571
+ * @returns {string|undefined} The phone number if it is not just a country code, otherwise undefined.
572
+ */
573
+
574
+
575
+ exports.makeFields = makeFields;
576
+
577
+ var excludedCountryCode = function excludedCountryCode(val) {
578
+ var phoneWithoutPrefix = val.phone.split('+')[1];
579
+
580
+ var isOnlyCountryCode = _reactInternationalPhone.defaultCountries.some(function (country) {
581
+ var _parseCountry = (0, _reactInternationalPhone.parseCountry)(country),
582
+ dialCode = _parseCountry.dialCode;
583
+
584
+ return phoneWithoutPrefix === dialCode;
585
+ });
586
+
587
+ if (isOnlyCountryCode) return undefined;
588
+ return val.phone;
589
+ };
546
590
 
547
- exports.makeFields = makeFields;
591
+ exports.excludedCountryCode = excludedCountryCode;
@@ -63,6 +63,7 @@ function getSubmitContactForm() {
63
63
  *
64
64
  * @param {object} params
65
65
  * @param {{ data: Array<object> }} params.contacts
66
+ * @param {object} params.contact
66
67
  * @param {import('cozy-client/types/types').IOCozyContact} params.contact
67
68
  * @param {Object} params.customFieldsProps
68
69
  * @param {func} params.onSubmit
@@ -135,6 +136,7 @@ var ContactForm = function ContactForm(_ref) {
135
136
  key: index,
136
137
  attributes: attributes,
137
138
  contacts: contacts,
139
+ contact: contact,
138
140
  showSecondaryFields: showSecondaryFields,
139
141
  formProps: {
140
142
  valid: valid,
@@ -100,6 +100,7 @@ var FieldInputWrapperPropTypes = {
100
100
  label: _propTypes.default.string,
101
101
  required: _propTypes.default.bool,
102
102
  variant: _propTypes.default.string,
103
+ contact: _propTypes.default.object,
103
104
  customLabelOptions: _propTypes.default.shape({
104
105
  hide: _propTypes.default.bool,
105
106
  defaultType: _propTypes.default.string.isRequired,
@@ -1,5 +1,5 @@
1
1
  export default FieldInput;
2
- declare function FieldInput({ name, labelProps, className, attributes: { subFields, ...restAttributes }, contacts, error, helperText, label, isInvisible }: {
2
+ declare function FieldInput({ name, labelProps, className, attributes: { subFields, ...restAttributes }, contacts, contact, error, helperText, label, isInvisible }: {
3
3
  name: any;
4
4
  labelProps: any;
5
5
  className: any;
@@ -8,6 +8,7 @@ declare function FieldInput({ name, labelProps, className, attributes: { subFiel
8
8
  subFields: any;
9
9
  };
10
10
  contacts: any;
11
+ contact: any;
11
12
  error: any;
12
13
  helperText: any;
13
14
  label: any;
@@ -23,6 +24,7 @@ declare namespace FieldInput {
23
24
  export let contacts: PropTypes.Requireable<PropTypes.InferProps<{
24
25
  data: PropTypes.Requireable<object[]>;
25
26
  }>>;
27
+ export let contact: PropTypes.Requireable<object>;
26
28
  export let id: PropTypes.Requireable<string>;
27
29
  export let label: PropTypes.Requireable<string>;
28
30
  }
@@ -1,5 +1,5 @@
1
1
  export default FieldInputAccordion;
2
- declare function FieldInputAccordion({ attributes: { name, label, subFields, ...restAttributes }, contacts, error, helperText }: {
2
+ declare function FieldInputAccordion({ attributes: { name, label, subFields, ...restAttributes }, contacts, contact, error, helperText }: {
3
3
  attributes: {
4
4
  [x: string]: any;
5
5
  name: any;
@@ -7,6 +7,7 @@ declare function FieldInputAccordion({ attributes: { name, label, subFields, ...
7
7
  subFields: any;
8
8
  };
9
9
  contacts: any;
10
+ contact: any;
10
11
  error: any;
11
12
  helperText: any;
12
13
  }): JSX.Element;
@@ -1,10 +1,11 @@
1
1
  export default FieldInputArray;
2
- declare function FieldInputArray({ attributes: { name, label, ...restAttributes }, contacts, formProps }: {
2
+ declare function FieldInputArray({ attributes: { name, label, ...restAttributes }, contacts, contact, formProps }: {
3
3
  attributes: {
4
4
  [x: string]: any;
5
5
  name: any;
6
6
  label: any;
7
7
  };
8
8
  contacts: any;
9
+ contact: any;
9
10
  formProps: any;
10
11
  }): JSX.Element;
@@ -1,13 +1,8 @@
1
1
  export default FieldInputLayout;
2
- declare function FieldInputLayout({ attributes: { layout, icon, isSecondary, validate, ...attributes }, contacts, showSecondaryFields, formProps }: {
3
- attributes: {
4
- [x: string]: any;
5
- layout: any;
6
- icon: any;
7
- isSecondary: any;
8
- validate: any;
9
- };
2
+ declare function FieldInputLayout({ attributes, contacts, contact, showSecondaryFields, formProps }: {
3
+ attributes: any;
10
4
  contacts: any;
5
+ contact: any;
11
6
  showSecondaryFields: any;
12
7
  formProps: any;
13
8
  }): JSX.Element;
@@ -17,6 +12,7 @@ declare namespace FieldInputLayout {
17
12
  let contacts: PropTypes.Requireable<PropTypes.InferProps<{
18
13
  data: PropTypes.Requireable<object[]>;
19
14
  }>>;
15
+ let contact: PropTypes.Requireable<object>;
20
16
  let formProps: PropTypes.Requireable<object>;
21
17
  }
22
18
  }
@@ -1,10 +1,14 @@
1
1
  export default FieldInputWrapper;
2
- declare function FieldInputWrapper({ input, attributes: { component, ...restAttributes }, variant, fullWidth, ...props }: {
2
+ declare function FieldInputWrapper({ input, attributes: { component, layout, icon, isSecondary, validate, ...restAttributes }, variant, fullWidth, ...props }: {
3
3
  [x: string]: any;
4
4
  input: any;
5
5
  attributes: {
6
6
  [x: string]: any;
7
7
  component: any;
8
+ layout: any;
9
+ icon: any;
10
+ isSecondary: any;
11
+ validate: any;
8
12
  };
9
13
  variant: any;
10
14
  fullWidth: any;
@@ -1,9 +1,12 @@
1
1
  export default TextFieldCustomLabelSelect;
2
- declare function TextFieldCustomLabelSelect({ name, value, options, customLabelOptions, onChange, ...props }: {
2
+ declare function TextFieldCustomLabelSelect({ name, value, options, disabled, isDisabled, contact, customLabelOptions, onChange, ...props }: {
3
3
  [x: string]: any;
4
4
  name: any;
5
5
  value: any;
6
6
  options: any;
7
+ disabled: any;
8
+ isDisabled: any;
9
+ contact: any;
7
10
  customLabelOptions: any;
8
11
  onChange: any;
9
12
  }): JSX.Element;
@@ -1,6 +1,10 @@
1
1
  export default TextFieldPhone;
2
- declare function TextFieldPhone({ value, onChange, ...props }: {
2
+ declare function TextFieldPhone({ name, value, disabled, isDisabled, contact, onChange, ...props }: {
3
3
  [x: string]: any;
4
+ name: any;
4
5
  value: any;
6
+ disabled: any;
7
+ isDisabled: any;
8
+ contact: any;
5
9
  onChange: any;
6
10
  }): JSX.Element;
@@ -8,8 +8,15 @@ export function makeTypeAndLabel(itemLabel?: string): {
8
8
  label?: string;
9
9
  };
10
10
  export function hasExtendedAddress(addressField: object): boolean;
11
- export function moveToHead(shouldBeHead: any): (items: any) => any;
12
- export function movePrimaryToHead(items: any): any;
11
+ export function moveToHead(shouldBeHead: Function): Function;
12
+ /**
13
+ * Moves items with the `primary` property set to true to the head of the array.
14
+ *
15
+ * @function
16
+ * @param {Array<Object>} items - The input array of items, each item optionally having a `primary` property.
17
+ * @returns {Array<Object>} The reordered array with 'primary' items at the front.
18
+ */
19
+ export const movePrimaryToHead: Function;
13
20
  export function createAddress({ address, oldContact, t }: {
14
21
  address: any;
15
22
  oldContact: any;
@@ -36,3 +43,6 @@ export function makeImppValues(oldContact: import("cozy-client/types/types").IOC
36
43
  export function initializationFieldValues(fields: any): any;
37
44
  export function makeInitialCustomValue(name: string, value: string): string;
38
45
  export function makeFields(customFields: (import("../types").Field)[] | undefined, defaultFields: (import("../types").Field)[]): (import("../types").Field)[];
46
+ export function excludedCountryCode(val: {
47
+ phone: string;
48
+ }): string | undefined;
@@ -5,7 +5,8 @@ declare const _default: React.MemoExoticComponent<{
5
5
  contacts: {
6
6
  data: Array<object>;
7
7
  };
8
- contact: import("cozy-client/types/types").IOCozyContact;
8
+ contact: object;
9
+ contact: any;
9
10
  customFieldsProps: any;
10
11
  onSubmit: func;
11
12
  }): JSX.Element;
@@ -83,6 +83,7 @@ export namespace FieldInputWrapperPropTypes {
83
83
  export let label: PropTypes.Requireable<string>;
84
84
  export let required: PropTypes.Requireable<boolean>;
85
85
  export let variant: PropTypes.Requireable<string>;
86
+ export let contact: PropTypes.Requireable<object>;
86
87
  export let customLabelOptions: PropTypes.Requireable<PropTypes.InferProps<{
87
88
  hide: PropTypes.Requireable<boolean>;
88
89
  defaultType: PropTypes.Validator<string>;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cozy-ui-plus",
3
- "version": "5.1.1",
3
+ "version": "5.2.1",
4
4
  "description": "Cozy-ui-plus is an extension of cozy-ui and provides components based on cozy-client",
5
5
  "main": "dist/index.js",
6
6
  "license": "MIT",
@@ -73,5 +73,5 @@
73
73
  "react-dom": "^16 || ^17 || ^18",
74
74
  "twake-i18n": ">=0.3.0"
75
75
  },
76
- "gitHead": "46d6951cb22a17ac26c3b00c28caf47d405d6683"
76
+ "gitHead": "3b9c5cf0b6442700d6a3b9d21010089f3f9f8b32"
77
77
  }
@@ -19,6 +19,7 @@ const FieldInput = ({
19
19
  className,
20
20
  attributes: { subFields, ...restAttributes },
21
21
  contacts,
22
+ contact,
22
23
  error,
23
24
  helperText,
24
25
  label,
@@ -62,6 +63,7 @@ const FieldInput = ({
62
63
  id={id}
63
64
  attributes={restAttributes}
64
65
  name={name}
66
+ contact={contact}
65
67
  component={FieldInputWrapper}
66
68
  onFocus={onFocus}
67
69
  onClick={handleClick}
@@ -87,6 +89,7 @@ const FieldInput = ({
87
89
  attributes={labelProps}
88
90
  name={`${name}Label`}
89
91
  label={t('Contacts.AddModal.ContactForm.fields.label')}
92
+ contact={contact}
90
93
  component={FieldInputWrapper}
91
94
  onFocus={onFocus}
92
95
  />
@@ -107,6 +110,7 @@ FieldInput.propTypes = {
107
110
  contacts: PropTypes.shape({
108
111
  data: PropTypes.arrayOf(PropTypes.object)
109
112
  }),
113
+ contact: PropTypes.object,
110
114
  // Destructuring props
111
115
  id: PropTypes.string,
112
116
  label: PropTypes.string
@@ -12,6 +12,7 @@ import { locales } from './locales'
12
12
  const FieldInputAccordion = ({
13
13
  attributes: { name, label, subFields, ...restAttributes },
14
14
  contacts,
15
+ contact,
15
16
  error,
16
17
  helperText
17
18
  }) => {
@@ -25,6 +26,7 @@ const FieldInputAccordion = ({
25
26
  <FieldInput
26
27
  attributes={restAttributes}
27
28
  contacts={contacts}
29
+ contact={contact}
28
30
  error={error}
29
31
  helperText={helperText}
30
32
  name={name}
@@ -17,11 +17,13 @@ import { locales } from './locales'
17
17
  const FieldInputArray = ({
18
18
  attributes: { name, label, ...restAttributes },
19
19
  contacts,
20
+ contact,
20
21
  formProps
21
22
  }) => {
22
23
  useExtendI18n(locales)
23
24
  const { t } = useI18n()
24
25
  const { errors } = formProps
26
+ const { disabled, isDisabled } = restAttributes
25
27
 
26
28
  return (
27
29
  <FieldArray name={name}>
@@ -29,9 +31,11 @@ const FieldInputArray = ({
29
31
  return (
30
32
  <>
31
33
  {fields.map((nameWithIndex, index) => {
32
- const key = fields.value[index]?.fieldId || nameWithIndex
33
- const showRemove = fields.value[index]?.[name]
34
+ const field = fields.value[index]
35
+ const key = field?.fieldId || nameWithIndex
34
36
  const inputName = `${nameWithIndex}.${name}`
37
+ const _disabled = disabled || isDisabled?.(inputName, contact)
38
+ const showRemove = field?.[name] && !_disabled
35
39
  const isError = makeIsRequiredError(
36
40
  restAttributes.required,
37
41
  formProps
@@ -47,6 +51,7 @@ const FieldInputArray = ({
47
51
  <FieldInput
48
52
  attributes={restAttributes}
49
53
  contacts={contacts}
54
+ contact={contact}
50
55
  error={isError}
51
56
  helperText={isError ? errors[inputName] : null}
52
57
  name={inputName}
@@ -12,16 +12,17 @@ import { makeIsRequiredError } from './helpers'
12
12
  import { locales } from './locales'
13
13
 
14
14
  const FieldInputLayout = ({
15
- // eslint-disable-next-line no-unused-vars
16
- attributes: { layout, icon, isSecondary, validate, ...attributes }, // ⚠️ `layout` `icon` `isSecondary` `validate` here are removed from attributes to avoid DOM propagration
15
+ attributes,
17
16
  contacts,
17
+ contact,
18
18
  showSecondaryFields,
19
19
  formProps
20
20
  }) => {
21
21
  useExtendI18n(locales)
22
22
  const { t } = useI18n()
23
23
  const { errors } = formProps
24
- const { name, label, ...restAttributes } = attributes
24
+ const { name, label, layout, icon, isSecondary, ...restAttributes } =
25
+ attributes
25
26
 
26
27
  const isError = makeIsRequiredError(restAttributes.required, formProps)
27
28
 
@@ -42,12 +43,14 @@ const FieldInputLayout = ({
42
43
  <FieldInputArray
43
44
  attributes={attributes}
44
45
  contacts={contacts}
46
+ contact={contact}
45
47
  formProps={formProps}
46
48
  />
47
49
  ) : layout === 'accordion' ? (
48
50
  <FieldInputAccordion
49
51
  attributes={attributes}
50
52
  contacts={contacts}
53
+ contact={contact}
51
54
  error={isError}
52
55
  helperText={isError ? errors[name] : null}
53
56
  />
@@ -55,6 +58,7 @@ const FieldInputLayout = ({
55
58
  <FieldInput
56
59
  attributes={restAttributes}
57
60
  contacts={contacts}
61
+ contact={contact}
58
62
  error={isError}
59
63
  helperText={isError ? errors[name] : null}
60
64
  name={name}
@@ -72,6 +76,7 @@ FieldInputLayout.propTypes = {
72
76
  contacts: PropTypes.shape({
73
77
  data: PropTypes.arrayOf(PropTypes.object)
74
78
  }),
79
+ contact: PropTypes.object,
75
80
  formProps: PropTypes.object
76
81
  }
77
82
 
@@ -10,7 +10,14 @@ import { FieldInputWrapperPropTypes } from '../types'
10
10
  // between Field from react-final-form and TextField from Mui
11
11
  const FieldInputWrapper = ({
12
12
  input,
13
- attributes: { component, ...restAttributes },
13
+ attributes: {
14
+ component,
15
+ layout, // eslint-disable-line no-unused-vars
16
+ icon, // eslint-disable-line no-unused-vars
17
+ isSecondary, // eslint-disable-line no-unused-vars
18
+ validate, // eslint-disable-line no-unused-vars
19
+ ...restAttributes
20
+ }, // ⚠️ `layout` `icon` `isSecondary` `validate` are removed from attributes to avoid DOM propagration, only used for business rules
14
21
  variant,
15
22
  fullWidth,
16
23
  ...props
@@ -11,6 +11,9 @@ const TextFieldCustomLabelSelect = ({
11
11
  name,
12
12
  value,
13
13
  options,
14
+ disabled,
15
+ isDisabled,
16
+ contact,
14
17
  customLabelOptions,
15
18
  onChange,
16
19
  ...props
@@ -44,6 +47,7 @@ const TextFieldCustomLabelSelect = ({
44
47
  }
45
48
  ]
46
49
  const _options = options.concat(customOption)
50
+ const _disabled = disabled || isDisabled?.(name, contact)
47
51
 
48
52
  return (
49
53
  <>
@@ -52,6 +56,7 @@ const TextFieldCustomLabelSelect = ({
52
56
  name={name}
53
57
  value={value}
54
58
  options={_options}
59
+ disabled={_disabled}
55
60
  onChange={ev => {
56
61
  if (ev.target.value === 'skip') {
57
62
  return
@@ -6,10 +6,20 @@ import TextField from 'cozy-ui/transpiled/react/TextField'
6
6
  import { useBreakpoints } from 'cozy-ui/transpiled/react/providers/Breakpoints'
7
7
 
8
8
  import FlagBottomSheet from './FlagBottomSheet'
9
+ import FlagImage from './FlagImage'
9
10
  import FlagMenu from './FlagMenu'
10
11
 
11
- const TextFieldPhone = ({ value, onChange, ...props }) => {
12
+ const TextFieldPhone = ({
13
+ name,
14
+ value,
15
+ disabled,
16
+ isDisabled,
17
+ contact,
18
+ onChange,
19
+ ...props
20
+ }) => {
12
21
  const { isMobile } = useBreakpoints()
22
+
13
23
  const { inputValue, handlePhoneValueChange, inputRef, country, setCountry } =
14
24
  usePhoneInput({
15
25
  defaultCountry: 'fr',
@@ -21,15 +31,25 @@ const TextFieldPhone = ({ value, onChange, ...props }) => {
21
31
  })
22
32
 
23
33
  const ResponsiveFlagMenu = isMobile ? FlagBottomSheet : FlagMenu
34
+ const _disabled = disabled || isDisabled?.(name, contact)
24
35
 
25
36
  return (
26
37
  <TextField
38
+ name={name}
27
39
  value={inputValue}
28
40
  inputRef={inputRef}
41
+ disabled={_disabled}
29
42
  InputProps={{
30
43
  startAdornment: (
31
44
  <InputAdornment position="start">
32
- <ResponsiveFlagMenu value={country.iso2} setCountry={setCountry} />
45
+ {_disabled ? (
46
+ <FlagImage className="u-ml-half" iso2={country.iso2} />
47
+ ) : (
48
+ <ResponsiveFlagMenu
49
+ value={country.iso2}
50
+ setCountry={setCountry}
51
+ />
52
+ )}
33
53
  </InputAdornment>
34
54
  )
35
55
  }}
@@ -78,7 +78,6 @@ export const fields = [
78
78
  layout: 'array',
79
79
  component: TextFieldPhone,
80
80
  label: {
81
- name: 'phoneLabel',
82
81
  select: true,
83
82
  customLabelOptions: {
84
83
  defaultType: '',
@@ -122,7 +121,6 @@ export const fields = [
122
121
  type: 'email',
123
122
  layout: 'array',
124
123
  label: {
125
- name: 'emailLabel',
126
124
  select: true,
127
125
  customLabelOptions: {
128
126
  defaultType: '',
@@ -220,7 +218,6 @@ export const fields = [
220
218
  }
221
219
  ],
222
220
  label: {
223
- name: 'addressLabel',
224
221
  select: true,
225
222
  customLabelOptions: {
226
223
  defaultType: '',
@@ -254,7 +251,6 @@ export const fields = [
254
251
  type: 'url',
255
252
  isSecondary: true,
256
253
  label: {
257
- name: 'cozyLabel',
258
254
  select: true,
259
255
  customLabelOptions: {
260
256
  defaultType: '',
@@ -303,7 +299,6 @@ export const fields = [
303
299
  )
304
300
  },
305
301
  label: {
306
- name: 'relatedContactLabel',
307
302
  select: true,
308
303
  options: [
309
304
  {
@@ -6,6 +6,7 @@ import {
6
6
  createAddress,
7
7
  getRelatedContactRelationships,
8
8
  makeImppValues,
9
+ excludedCountryCode,
9
10
  makeTypeAndLabel
10
11
  } from './helpers'
11
12
 
@@ -76,7 +77,7 @@ const formValuesToContact = ({
76
77
  address: createAddress({ address, oldContact: oldContactCleaned, t }),
77
78
  phone: phone
78
79
  ? phone
79
- .filter(val => val && val.phone)
80
+ .filter(val => (val?.phone ? excludedCountryCode(val) : undefined))
80
81
  .map(({ phone, phoneLabel }, index) => ({
81
82
  number: phone,
82
83
  ...makeTypeAndLabel(phoneLabel),
@@ -2,6 +2,7 @@ import get from 'lodash/get'
2
2
  import isEqual from 'lodash/isEqual'
3
3
  import merge from 'lodash/merge'
4
4
  import uniqueId from 'lodash/uniqueId'
5
+ import { defaultCountries, parseCountry } from 'react-international-phone'
5
6
 
6
7
  import { Association } from 'cozy-client'
7
8
  import { makeDisplayName } from 'cozy-client/dist/models/contact'
@@ -134,9 +135,23 @@ export const hasExtendedAddress = addressField => {
134
135
  )
135
136
  }
136
137
 
138
+ /**
139
+ * Items matching the given predicate function `shouldBeHead`
140
+ * are moved to the start of the array, preserving the order of the others.
141
+ *
142
+ * @param {Function} shouldBeHead - A predicate function that takes an item and returns true if it should be moved to the head of the array.
143
+ * @returns {Function} A function that takes an array of items and returns a new array with the matching item(s) moved to the front.
144
+ */
137
145
  export const moveToHead = shouldBeHead => items =>
138
146
  items.reduce((arr, v) => (shouldBeHead(v) ? [v, ...arr] : [...arr, v]), [])
139
147
 
148
+ /**
149
+ * Moves items with the `primary` property set to true to the head of the array.
150
+ *
151
+ * @function
152
+ * @param {Array<Object>} items - The input array of items, each item optionally having a `primary` property.
153
+ * @returns {Array<Object>} The reordered array with 'primary' items at the front.
154
+ */
140
155
  export const movePrimaryToHead = moveToHead(v => v?.primary)
141
156
 
142
157
  export const createAddress = ({ address, oldContact, t }) => {
@@ -466,3 +481,25 @@ export const makeFields = (customFields, defaultFields) => {
466
481
 
467
482
  return fields
468
483
  }
484
+
485
+ /**
486
+ * Excludes phone numbers that consist only of a country code.
487
+ * If the provided phone value matches only a country code (e.g., "+33"),
488
+ * returns undefined. Otherwise, returns the phone value.
489
+ *
490
+ * @param {Object} val - An object containing the phone number.
491
+ * @param {string} val.phone - The phone number string, possibly starting with "+" and a country code.
492
+ * @returns {string|undefined} The phone number if it is not just a country code, otherwise undefined.
493
+ */
494
+ export const excludedCountryCode = val => {
495
+ const phoneWithoutPrefix = val.phone.split('+')[1]
496
+
497
+ const isOnlyCountryCode = defaultCountries.some(country => {
498
+ const { dialCode } = parseCountry(country)
499
+ return phoneWithoutPrefix === dialCode
500
+ })
501
+
502
+ if (isOnlyCountryCode) return undefined
503
+
504
+ return val.phone
505
+ }
@@ -12,10 +12,20 @@ import {
12
12
  getFirstValueIfArray,
13
13
  validateFields
14
14
  } from './helpers'
15
+ import { excludedCountryCode } from './helpers'
15
16
  import { locales } from './locales'
16
17
 
17
18
  const t = x => get(locales.en, x, x)
18
19
 
20
+ jest.mock('react-international-phone', () => ({
21
+ ...jest.requireActual('react-international-phone'),
22
+ defaultCountries: [
23
+ ['France', 'fr', '33'],
24
+ ['United States', 'us', '1'],
25
+ ['Germany', 'de', '49']
26
+ ]
27
+ }))
28
+
19
29
  describe('makeCustomLabel', () => {
20
30
  it('should return custom type and supported label', () => {
21
31
  const resForWork = makeCustomLabel('{"type":"someType","label":"work"}', t)
@@ -741,3 +751,33 @@ describe('validateFields', () => {
741
751
  expect(res).toEqual({ mail: 'Some fields are not filled correctly' })
742
752
  })
743
753
  })
754
+
755
+ describe('excludedCountryCode', () => {
756
+ it('returns undefined for country code only (+33)', () => {
757
+ expect(excludedCountryCode({ phone: '+33' })).toBeUndefined()
758
+ })
759
+
760
+ it('preserves full number for Germany (+4930123456)', () => {
761
+ expect(excludedCountryCode({ phone: '+4930123456' })).toBe('+4930123456')
762
+ })
763
+
764
+ it('returns undefined for country code only (+1)', () => {
765
+ expect(excludedCountryCode({ phone: '+1' })).toBeUndefined()
766
+ })
767
+
768
+ it('preserves full French mobile (+33612345678)', () => {
769
+ expect(excludedCountryCode({ phone: '+33612345678' })).toBe('+33612345678')
770
+ })
771
+
772
+ it('preserves value not matching country code (+490)', () => {
773
+ expect(excludedCountryCode({ phone: '+490' })).toBe('+490')
774
+ })
775
+
776
+ it('preserves numbers with no country code (12345)', () => {
777
+ expect(excludedCountryCode({ phone: '12345' })).toBe('12345')
778
+ })
779
+
780
+ it('returns undefined for country code only (+49)', () => {
781
+ expect(excludedCountryCode({ phone: '+49' })).toBeUndefined()
782
+ })
783
+ })
@@ -37,6 +37,7 @@ export function getSubmitContactForm() {
37
37
  *
38
38
  * @param {object} params
39
39
  * @param {{ data: Array<object> }} params.contacts
40
+ * @param {object} params.contact
40
41
  * @param {import('cozy-client/types/types').IOCozyContact} params.contact
41
42
  * @param {Object} params.customFieldsProps
42
43
  * @param {func} params.onSubmit
@@ -94,6 +95,7 @@ const ContactForm = ({ contacts, contact, customFieldsProps, onSubmit }) => {
94
95
  key={index}
95
96
  attributes={attributes}
96
97
  contacts={contacts}
98
+ contact={contact}
97
99
  showSecondaryFields={showSecondaryFields}
98
100
  formProps={{
99
101
  valid,
@@ -93,6 +93,7 @@ export const FieldInputWrapperPropTypes = {
93
93
  label: PropTypes.string,
94
94
  required: PropTypes.bool,
95
95
  variant: PropTypes.string,
96
+ contact: PropTypes.object,
96
97
  customLabelOptions: PropTypes.shape({
97
98
  hide: PropTypes.bool,
98
99
  defaultType: PropTypes.string.isRequired,