cozy-ui-plus 4.4.1 → 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 +12 -0
- package/dist/ContactsList/ContactCell.js +3 -1
- package/dist/ContactsList/Contacts/ContactIdentity.js +11 -3
- package/dist/ContactsList/Contacts/ContactName.js +17 -18
- package/dist/src/ContactsList/ContactCell.d.ts +2 -1
- package/dist/src/ContactsList/Contacts/ContactName.d.ts +3 -1
- package/dist/src/ContactsList/Contacts/ContactName.spec.d.ts +1 -0
- package/package.json +2 -2
- package/src/ContactsList/ContactCell.jsx +2 -2
- package/src/ContactsList/Contacts/ContactIdentity.jsx +6 -4
- package/src/ContactsList/Contacts/ContactName.jsx +18 -21
- package/src/ContactsList/Contacts/ContactName.spec.jsx +99 -0
package/CHANGELOG.md
CHANGED
|
@@ -3,6 +3,18 @@
|
|
|
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
|
+
|
|
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)
|
|
13
|
+
|
|
14
|
+
### Features
|
|
15
|
+
|
|
16
|
+
- **cozy-ui-plus:** Add `disable` prop on ContactCell ([2249927](https://github.com/cozy/cozy-libs/commit/22499270ab1b110cb4e01cf83297fd69d33f5d3b))
|
|
17
|
+
|
|
6
18
|
## [4.4.1](https://github.com/cozy/cozy-libs/compare/cozy-ui-plus@4.4.0...cozy-ui-plus@4.4.1) (2026-01-29)
|
|
7
19
|
|
|
8
20
|
**Note:** Version bump only for package cozy-ui-plus
|
|
@@ -17,11 +17,13 @@ var Cell = function Cell(_ref) {
|
|
|
17
17
|
var row = _ref.row,
|
|
18
18
|
column = _ref.column,
|
|
19
19
|
cell = _ref.cell,
|
|
20
|
-
actions = _ref.actions
|
|
20
|
+
actions = _ref.actions,
|
|
21
|
+
disable = _ref.disable;
|
|
21
22
|
|
|
22
23
|
if (column.id === 'fullname') {
|
|
23
24
|
return /*#__PURE__*/_react.default.createElement(_ContactIdentity.default, {
|
|
24
25
|
contact: row,
|
|
26
|
+
disable: disable,
|
|
25
27
|
noWrapper: true
|
|
26
28
|
});
|
|
27
29
|
}
|
|
@@ -9,6 +9,8 @@ exports.default = void 0;
|
|
|
9
9
|
|
|
10
10
|
var _objectWithoutProperties2 = _interopRequireDefault(require("@babel/runtime/helpers/objectWithoutProperties"));
|
|
11
11
|
|
|
12
|
+
var _classnames = _interopRequireDefault(require("classnames"));
|
|
13
|
+
|
|
12
14
|
var _propTypes = _interopRequireDefault(require("prop-types"));
|
|
13
15
|
|
|
14
16
|
var _react = _interopRequireDefault(require("react"));
|
|
@@ -50,18 +52,24 @@ var MyselfMarker = function MyselfMarker() {
|
|
|
50
52
|
};
|
|
51
53
|
|
|
52
54
|
var ContactIdentity = function ContactIdentity(_ref) {
|
|
53
|
-
var contact = _ref.contact
|
|
55
|
+
var contact = _ref.contact,
|
|
56
|
+
disable = _ref.disable;
|
|
54
57
|
var isMyself = !!contact.me;
|
|
55
58
|
return /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, /*#__PURE__*/_react.default.createElement(_Avatar.default, {
|
|
59
|
+
className: (0, _classnames.default)({
|
|
60
|
+
'u-o-60': disable
|
|
61
|
+
}),
|
|
56
62
|
display: "inline",
|
|
57
63
|
size: "s"
|
|
58
64
|
}, (0, _contact.getInitials)(contact)), /*#__PURE__*/_react.default.createElement(_ContactName.default, {
|
|
59
|
-
contact: contact
|
|
65
|
+
contact: contact,
|
|
66
|
+
disable: disable
|
|
60
67
|
}), isMyself && /*#__PURE__*/_react.default.createElement(MyselfMarker, null));
|
|
61
68
|
};
|
|
62
69
|
|
|
63
70
|
ContactIdentity.propTypes = {
|
|
64
|
-
contact: _propTypes.default.object.isRequired
|
|
71
|
+
contact: _propTypes.default.object.isRequired,
|
|
72
|
+
disable: _propTypes.default.bool
|
|
65
73
|
};
|
|
66
74
|
|
|
67
75
|
var ContactIdentityWrapper = function ContactIdentityWrapper(_ref2) {
|
|
@@ -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,31 +16,32 @@ 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
|
|
19
|
+
var _getDisplayName;
|
|
20
|
+
|
|
21
|
+
var contact = _ref.contact,
|
|
22
|
+
disable = _ref.disable;
|
|
23
|
+
|
|
24
|
+
var _ref2 = contact.name || {},
|
|
25
|
+
familyName = _ref2.familyName;
|
|
22
26
|
|
|
23
|
-
var
|
|
24
|
-
var
|
|
25
|
-
var
|
|
26
|
-
var namesToDisplay = displayName === null || displayName === void 0 ? void 0 : displayName.split(' ');
|
|
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;
|
|
27
30
|
return /*#__PURE__*/_react.default.createElement(_Typography.default, {
|
|
28
31
|
"data-testid": "ContactName" // used by a test in cozy-contacts
|
|
29
32
|
,
|
|
30
33
|
className: "u-ml-1",
|
|
31
34
|
noWrap: true,
|
|
32
|
-
display: "inline"
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
className: (0, _classnames.default)({
|
|
38
|
-
'u-fw-bold': name === familyName
|
|
39
|
-
})
|
|
40
|
-
}, name, !isLastItem && /*#__PURE__*/_react.default.createElement(_react.default.Fragment, null, "\xA0"));
|
|
41
|
-
}));
|
|
35
|
+
display: "inline",
|
|
36
|
+
color: disable ? 'textSecondary' : 'textPrimary'
|
|
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);
|
|
42
40
|
};
|
|
43
41
|
|
|
44
42
|
ContactName.propTypes = {
|
|
45
|
-
contact: _propTypes.default.object.isRequired
|
|
43
|
+
contact: _propTypes.default.object.isRequired,
|
|
44
|
+
disable: _propTypes.default.bool
|
|
46
45
|
};
|
|
47
46
|
var _default = ContactName;
|
|
48
47
|
exports.default = _default;
|
|
@@ -1,8 +1,9 @@
|
|
|
1
|
-
declare const _default: React.MemoExoticComponent<({ row, column, cell, actions }: {
|
|
1
|
+
declare const _default: React.MemoExoticComponent<({ row, column, cell, actions, disable }: {
|
|
2
2
|
row: any;
|
|
3
3
|
column: any;
|
|
4
4
|
cell: any;
|
|
5
5
|
actions: any;
|
|
6
|
+
disable: any;
|
|
6
7
|
}) => any>;
|
|
7
8
|
export default _default;
|
|
8
9
|
import React from 'react';
|
|
@@ -1,10 +1,12 @@
|
|
|
1
1
|
export default ContactName;
|
|
2
|
-
declare function ContactName({ contact }: {
|
|
2
|
+
declare function ContactName({ contact, disable }: {
|
|
3
3
|
contact: any;
|
|
4
|
+
disable: any;
|
|
4
5
|
}): JSX.Element;
|
|
5
6
|
declare namespace ContactName {
|
|
6
7
|
namespace propTypes {
|
|
7
8
|
let contact: PropTypes.Validator<object>;
|
|
9
|
+
let disable: PropTypes.Requireable<boolean>;
|
|
8
10
|
}
|
|
9
11
|
}
|
|
10
12
|
import PropTypes from 'prop-types';
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
export {};
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cozy-ui-plus",
|
|
3
|
-
"version": "4.
|
|
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": "
|
|
77
|
+
"gitHead": "549503df8a2071ff837e672ad5f7019aa122cb1f"
|
|
78
78
|
}
|
|
@@ -4,9 +4,9 @@ import ActionsMenuButton from 'cozy-ui/transpiled/react/ActionsMenu/ActionsMenuB
|
|
|
4
4
|
|
|
5
5
|
import ContactIdentity from './Contacts/ContactIdentity'
|
|
6
6
|
|
|
7
|
-
const Cell = ({ row, column, cell, actions }) => {
|
|
7
|
+
const Cell = ({ row, column, cell, actions, disable }) => {
|
|
8
8
|
if (column.id === 'fullname') {
|
|
9
|
-
return <ContactIdentity contact={row} noWrapper />
|
|
9
|
+
return <ContactIdentity contact={row} disable={disable} noWrapper />
|
|
10
10
|
}
|
|
11
11
|
|
|
12
12
|
if (column.id === 'actions') {
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import cx from 'classnames'
|
|
1
2
|
import PropTypes from 'prop-types'
|
|
2
3
|
import React from 'react'
|
|
3
4
|
import { useI18n, useExtendI18n } from 'twake-i18n'
|
|
@@ -17,22 +18,23 @@ const MyselfMarker = () => {
|
|
|
17
18
|
return <span className={`${styles['contact-myself']}`}>({t('me')})</span>
|
|
18
19
|
}
|
|
19
20
|
|
|
20
|
-
const ContactIdentity = ({ contact }) => {
|
|
21
|
+
const ContactIdentity = ({ contact, disable }) => {
|
|
21
22
|
const isMyself = !!contact.me
|
|
22
23
|
|
|
23
24
|
return (
|
|
24
25
|
<>
|
|
25
|
-
<Avatar display="inline" size="s">
|
|
26
|
+
<Avatar className={cx({ 'u-o-60': disable })} display="inline" size="s">
|
|
26
27
|
{getInitials(contact)}
|
|
27
28
|
</Avatar>
|
|
28
|
-
<ContactName contact={contact} />
|
|
29
|
+
<ContactName contact={contact} disable={disable} />
|
|
29
30
|
{isMyself && <MyselfMarker />}
|
|
30
31
|
</>
|
|
31
32
|
)
|
|
32
33
|
}
|
|
33
34
|
|
|
34
35
|
ContactIdentity.propTypes = {
|
|
35
|
-
contact: PropTypes.object.isRequired
|
|
36
|
+
contact: PropTypes.object.isRequired,
|
|
37
|
+
disable: PropTypes.bool
|
|
36
38
|
}
|
|
37
39
|
|
|
38
40
|
const ContactIdentityWrapper = ({ noWrapper, ...props }) => {
|
|
@@ -1,14 +1,16 @@
|
|
|
1
|
-
import cx from 'classnames'
|
|
2
1
|
import PropTypes from 'prop-types'
|
|
3
2
|
import React from 'react'
|
|
4
3
|
|
|
5
4
|
import { getDisplayName } from 'cozy-client/dist/models/contact'
|
|
6
5
|
import Typography from 'cozy-ui/transpiled/react/Typography'
|
|
7
6
|
|
|
8
|
-
const ContactName = ({ contact }) => {
|
|
9
|
-
const familyName = contact.name
|
|
10
|
-
const displayName = getDisplayName(contact)
|
|
11
|
-
const
|
|
7
|
+
const ContactName = ({ contact, disable }) => {
|
|
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
|
|
@@ -16,28 +18,23 @@ const ContactName = ({ contact }) => {
|
|
|
16
18
|
className="u-ml-1"
|
|
17
19
|
noWrap
|
|
18
20
|
display="inline"
|
|
21
|
+
color={disable ? 'textSecondary' : 'textPrimary'}
|
|
19
22
|
>
|
|
20
|
-
{
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
})}
|
|
29
|
-
>
|
|
30
|
-
{name}
|
|
31
|
-
{!isLastItem && <> </>}
|
|
32
|
-
</span>
|
|
33
|
-
)
|
|
34
|
-
})}
|
|
23
|
+
{hasFamilyName ? (
|
|
24
|
+
<>
|
|
25
|
+
{namePrefix && <>{namePrefix} </>}
|
|
26
|
+
<span className="u-fw-bold">{familyName}</span>
|
|
27
|
+
</>
|
|
28
|
+
) : (
|
|
29
|
+
displayName
|
|
30
|
+
)}
|
|
35
31
|
</Typography>
|
|
36
32
|
)
|
|
37
33
|
}
|
|
38
34
|
|
|
39
35
|
ContactName.propTypes = {
|
|
40
|
-
contact: PropTypes.object.isRequired
|
|
36
|
+
contact: PropTypes.object.isRequired,
|
|
37
|
+
disable: PropTypes.bool
|
|
41
38
|
}
|
|
42
39
|
|
|
43
40
|
export default ContactName
|
|
@@ -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
|
+
})
|