cozy-ui-plus 4.5.0 → 4.5.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.
package/CHANGELOG.md CHANGED
@@ -3,6 +3,12 @@
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
+ ## [4.5.1](https://github.com/cozy/cozy-libs/compare/cozy-ui-plus@4.5.0...cozy-ui-plus@4.5.1) (2026-02-03)
7
+
8
+ ### Bug Fixes
9
+
10
+ - **cozy-ui-plus:** Fix ContactName not bolding multi-word family names ([e8015c0](https://github.com/cozy/cozy-libs/commit/e8015c05bda2272b85bf96cb1d560251097fef07))
11
+
6
12
  # [4.5.0](https://github.com/cozy/cozy-libs/compare/cozy-ui-plus@4.4.1...cozy-ui-plus@4.5.0) (2026-02-02)
7
13
 
8
14
  ### Features
@@ -7,8 +7,6 @@ Object.defineProperty(exports, "__esModule", {
7
7
  });
8
8
  exports.default = void 0;
9
9
 
10
- var _classnames = _interopRequireDefault(require("classnames"));
11
-
12
10
  var _propTypes = _interopRequireDefault(require("prop-types"));
13
11
 
14
12
  var _react = _interopRequireDefault(require("react"));
@@ -18,13 +16,17 @@ var _contact = require("cozy-client/dist/models/contact");
18
16
  var _Typography = _interopRequireDefault(require("cozy-ui/transpiled/react/Typography"));
19
17
 
20
18
  var ContactName = function ContactName(_ref) {
21
- var _contact$name;
19
+ var _getDisplayName;
22
20
 
23
21
  var contact = _ref.contact,
24
22
  disable = _ref.disable;
25
- var familyName = (_contact$name = contact.name) === null || _contact$name === void 0 ? void 0 : _contact$name.familyName;
26
- var displayName = (0, _contact.getDisplayName)(contact);
27
- var namesToDisplay = displayName === null || displayName === void 0 ? void 0 : displayName.split(' ');
23
+
24
+ var _ref2 = contact.name || {},
25
+ familyName = _ref2.familyName;
26
+
27
+ var displayName = (_getDisplayName = (0, _contact.getDisplayName)(contact)) === null || _getDisplayName === void 0 ? void 0 : _getDisplayName.trim();
28
+ var hasFamilyName = familyName && (displayName === null || displayName === void 0 ? void 0 : displayName.endsWith(familyName));
29
+ var namePrefix = hasFamilyName ? displayName.slice(0, -familyName.length).trimEnd() : null;
28
30
  return /*#__PURE__*/_react.default.createElement(_Typography.default, {
29
31
  "data-testid": "ContactName" // used by a test in cozy-contacts
30
32
  ,
@@ -32,15 +34,9 @@ var ContactName = function ContactName(_ref) {
32
34
  noWrap: true,
33
35
  display: "inline",
34
36
  color: disable ? 'textSecondary' : 'textPrimary'
35
- }, namesToDisplay === null || namesToDisplay === void 0 ? void 0 : namesToDisplay.map(function (name, index) {
36
- var isLastItem = index === namesToDisplay.length - 1;
37
- return /*#__PURE__*/_react.default.createElement("span", {
38
- key: "display-".concat(index),
39
- className: (0, _classnames.default)({
40
- 'u-fw-bold': name === familyName
41
- })
42
- }, name, !isLastItem && /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, "\xA0"));
43
- }));
37
+ }, hasFamilyName ? /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, namePrefix && /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, namePrefix, "\xA0"), /*#__PURE__*/_react.default.createElement("span", {
38
+ className: "u-fw-bold"
39
+ }, familyName)) : displayName);
44
40
  };
45
41
 
46
42
  ContactName.propTypes = {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "cozy-ui-plus",
3
- "version": "4.5.0",
3
+ "version": "4.5.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",
@@ -74,5 +74,5 @@
74
74
  "react-dom": "^16 || ^17 || ^18",
75
75
  "twake-i18n": ">=0.3.0"
76
76
  },
77
- "gitHead": "61e7d0678b71327a91c8b527edda7e06994ab43d"
77
+ "gitHead": "549503df8a2071ff837e672ad5f7019aa122cb1f"
78
78
  }
@@ -1,4 +1,3 @@
1
- import cx from 'classnames'
2
1
  import PropTypes from 'prop-types'
3
2
  import React from 'react'
4
3
 
@@ -6,9 +5,12 @@ import { getDisplayName } from 'cozy-client/dist/models/contact'
6
5
  import Typography from 'cozy-ui/transpiled/react/Typography'
7
6
 
8
7
  const ContactName = ({ contact, disable }) => {
9
- const familyName = contact.name?.familyName
10
- const displayName = getDisplayName(contact)
11
- const namesToDisplay = displayName?.split(' ')
8
+ const { familyName } = contact.name || {}
9
+ const displayName = getDisplayName(contact)?.trim()
10
+ const hasFamilyName = familyName && displayName?.endsWith(familyName)
11
+ const namePrefix = hasFamilyName
12
+ ? displayName.slice(0, -familyName.length).trimEnd()
13
+ : null
12
14
 
13
15
  return (
14
16
  <Typography
@@ -18,21 +20,14 @@ const ContactName = ({ contact, disable }) => {
18
20
  display="inline"
19
21
  color={disable ? 'textSecondary' : 'textPrimary'}
20
22
  >
21
- {namesToDisplay?.map((name, index) => {
22
- const isLastItem = index === namesToDisplay.length - 1
23
-
24
- return (
25
- <span
26
- key={`display-${index}`}
27
- className={cx({
28
- 'u-fw-bold': name === familyName
29
- })}
30
- >
31
- {name}
32
- {!isLastItem && <>&nbsp;</>}
33
- </span>
34
- )
35
- })}
23
+ {hasFamilyName ? (
24
+ <>
25
+ {namePrefix && <>{namePrefix}&nbsp;</>}
26
+ <span className="u-fw-bold">{familyName}</span>
27
+ </>
28
+ ) : (
29
+ displayName
30
+ )}
36
31
  </Typography>
37
32
  )
38
33
  }
@@ -0,0 +1,99 @@
1
+ import { render, screen } from '@testing-library/react'
2
+ import React from 'react'
3
+
4
+ import { getDisplayName } from 'cozy-client/dist/models/contact'
5
+
6
+ import ContactName from './ContactName'
7
+
8
+ jest.mock('cozy-client/dist/models/contact', () => ({
9
+ getDisplayName: jest.fn()
10
+ }))
11
+
12
+ const makeContact = attrs => ({
13
+ _id: 'contactid',
14
+ _type: 'io.cozy.contacts',
15
+ ...attrs
16
+ })
17
+
18
+ describe('ContactName', () => {
19
+ it('should bold single-word family name', () => {
20
+ getDisplayName.mockReturnValue('John Doe')
21
+ const contact = makeContact({
22
+ name: { familyName: 'Doe', givenName: 'John' }
23
+ })
24
+
25
+ render(<ContactName contact={contact} />)
26
+
27
+ const boldElement = document.querySelector('.u-fw-bold')
28
+ expect(boldElement).toHaveTextContent('Doe')
29
+ })
30
+
31
+ it('should bold multi-word family name', () => {
32
+ getDisplayName.mockReturnValue('khaled Van Beethoven')
33
+ const contact = makeContact({
34
+ name: { familyName: 'Van Beethoven', givenName: 'khaled' }
35
+ })
36
+
37
+ render(<ContactName contact={contact} />)
38
+
39
+ const boldElement = document.querySelector('.u-fw-bold')
40
+ expect(boldElement).toHaveTextContent('Van Beethoven')
41
+ })
42
+
43
+ it('should not bold anything when familyName is missing', () => {
44
+ getDisplayName.mockReturnValue('johndoe@localhost')
45
+ const contact = makeContact()
46
+
47
+ render(<ContactName contact={contact} />)
48
+
49
+ const boldElement = document.querySelector('.u-fw-bold')
50
+ expect(boldElement).toBeNull()
51
+ expect(screen.getByText('johndoe@localhost')).toBeInTheDocument()
52
+ })
53
+
54
+ it('should not bold when displayName does not end with familyName', () => {
55
+ getDisplayName.mockReturnValue('johndoe@localhost')
56
+ const contact = makeContact({
57
+ name: { familyName: 'Doe' }
58
+ })
59
+
60
+ render(<ContactName contact={contact} />)
61
+
62
+ const boldElement = document.querySelector('.u-fw-bold')
63
+ expect(boldElement).toBeNull()
64
+ })
65
+
66
+ it('should handle contact without name property', () => {
67
+ getDisplayName.mockReturnValue('johndoe@localhost')
68
+ const contact = makeContact()
69
+
70
+ render(<ContactName contact={contact} />)
71
+
72
+ expect(screen.getByText('johndoe@localhost')).toBeInTheDocument()
73
+ })
74
+
75
+ it('should display name prefix before bolded family name', () => {
76
+ getDisplayName.mockReturnValue('khaled Van Beethoven')
77
+ const contact = makeContact({
78
+ name: { familyName: 'Van Beethoven', givenName: 'khaled' }
79
+ })
80
+
81
+ render(<ContactName contact={contact} />)
82
+
83
+ const nameElement = screen.getByTestId('ContactName')
84
+ expect(nameElement).toHaveTextContent('khaled')
85
+ expect(nameElement).toHaveTextContent('Van Beethoven')
86
+ })
87
+
88
+ it('should bold family name even with trailing whitespace in displayName', () => {
89
+ getDisplayName.mockReturnValue('John Doe ')
90
+ const contact = makeContact({
91
+ name: { familyName: 'Doe', givenName: 'John' }
92
+ })
93
+
94
+ render(<ContactName contact={contact} />)
95
+
96
+ const boldElement = document.querySelector('.u-fw-bold')
97
+ expect(boldElement).toHaveTextContent('Doe')
98
+ })
99
+ })