cozy-ui-plus 5.3.1 → 6.1.0
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 +23 -0
- package/dist/CollectionField/index.js +2 -2
- package/dist/Contacts/AddModal/ContactForm/FieldInput.js +49 -20
- package/dist/Contacts/AddModal/ContactForm/FieldInputArray.js +5 -16
- package/dist/Contacts/AddModal/ContactForm/FieldInputLayout.js +2 -2
- package/dist/Contacts/AddModal/ContactForm/FieldInputWrapper.js +3 -1
- package/dist/Contacts/AddModal/ContactForm/RemoveButton.js +34 -0
- package/dist/Contacts/AddModal/ContactForm/fieldsConfig.js +3 -1
- package/dist/Contacts/AddModal/ContactForm/helpers.js +12 -2
- package/dist/Contacts/AddModal/ContactForm/index.js +14 -3
- package/dist/ContactsListModal/ContactsListModal.js +2 -6
- package/dist/ContactsListModal/MobileHeader.js +2 -6
- package/dist/Field/index.js +9 -10
- package/dist/ListItem/ListItemFile/ItemIcon.js +11 -4
- package/dist/Qualification/QualificationItem/index.js +10 -14
- package/dist/ShortcutTile/index.js +2 -2
- package/dist/SquareAppIcon/index.js +22 -21
- package/dist/providers/CozyTheme/index.js +0 -3
- package/dist/src/Contacts/AddModal/ContactForm/FieldInput.d.ts +3 -1
- package/dist/src/Contacts/AddModal/ContactForm/FieldInputWrapper.d.ts +2 -1
- package/dist/src/Contacts/AddModal/ContactForm/RemoveButton.d.ts +4 -0
- package/dist/src/providers/CozyTheme/index.d.ts +0 -3
- package/dist/stylesheet.css +0 -25
- package/package.json +4 -4
- package/src/CollectionField/index.jsx +2 -2
- package/src/Contacts/AddModal/ContactForm/FieldInput.jsx +29 -9
- package/src/Contacts/AddModal/ContactForm/FieldInputArray.jsx +3 -14
- package/src/Contacts/AddModal/ContactForm/FieldInputLayout.jsx +5 -3
- package/src/Contacts/AddModal/ContactForm/FieldInputWrapper.jsx +3 -1
- package/src/Contacts/AddModal/ContactForm/RemoveButton.jsx +18 -0
- package/src/Contacts/AddModal/ContactForm/fieldsConfig.jsx +3 -1
- package/src/Contacts/AddModal/ContactForm/helpers.js +11 -2
- package/src/Contacts/AddModal/ContactForm/helpers.spec.js +62 -0
- package/src/Contacts/AddModal/ContactForm/index.jsx +27 -14
- package/src/ContactsListModal/ContactsListModal.jsx +1 -4
- package/src/ContactsListModal/MobileHeader.jsx +20 -24
- package/src/Field/index.jsx +7 -6
- package/src/ListItem/ListItemFile/ItemIcon.jsx +15 -7
- package/src/Qualification/QualificationItem/index.jsx +11 -16
- package/src/ShortcutTile/index.tsx +1 -1
- package/src/SquareAppIcon/__snapshots__/SquareAppIcon.spec.js.snap +240 -271
- package/src/SquareAppIcon/index.jsx +96 -107
- package/src/providers/CozyTheme/index.jsx +0 -2
- package/src/Contacts/AddModal/ContactForm/styles.styl +0 -2
|
@@ -21,6 +21,8 @@ var _propTypes = _interopRequireDefault(require("prop-types"));
|
|
|
21
21
|
|
|
22
22
|
var _react = _interopRequireWildcard(require("react"));
|
|
23
23
|
|
|
24
|
+
var _helpers = require("cozy-ui/transpiled/react/Avatar/helpers");
|
|
25
|
+
|
|
24
26
|
var _Badge = _interopRequireDefault(require("cozy-ui/transpiled/react/Badge"));
|
|
25
27
|
|
|
26
28
|
var _Icon = _interopRequireDefault(require("cozy-ui/transpiled/react/Icon"));
|
|
@@ -35,21 +37,17 @@ var _Plus = _interopRequireDefault(require("cozy-ui/transpiled/react/Icons/Plus"
|
|
|
35
37
|
|
|
36
38
|
var _WarningCircle = _interopRequireDefault(require("cozy-ui/transpiled/react/Icons/WarningCircle"));
|
|
37
39
|
|
|
38
|
-
var _InfosBadge = _interopRequireDefault(require("cozy-ui/transpiled/react/InfosBadge"));
|
|
39
|
-
|
|
40
40
|
var _ListItemText = _interopRequireDefault(require("cozy-ui/transpiled/react/ListItemText"));
|
|
41
41
|
|
|
42
42
|
var _Spinner = _interopRequireDefault(require("cozy-ui/transpiled/react/Spinner"));
|
|
43
43
|
|
|
44
44
|
var _Typography = _interopRequireDefault(require("cozy-ui/transpiled/react/Typography"));
|
|
45
45
|
|
|
46
|
-
var _helpers = require("cozy-ui/transpiled/react/legacy/Avatar/helpers");
|
|
47
|
-
|
|
48
46
|
var _styles = require("cozy-ui/transpiled/react/styles");
|
|
49
47
|
|
|
50
48
|
var _AppIcon = _interopRequireDefault(require("../AppIcon"));
|
|
51
49
|
|
|
52
|
-
var _CozyTheme =
|
|
50
|
+
var _CozyTheme = require("../providers/CozyTheme");
|
|
53
51
|
|
|
54
52
|
var _excluded = ["display", "name", "variant", "IconContent", "description", "hideShortcutBadge"];
|
|
55
53
|
|
|
@@ -94,9 +92,6 @@ var useStyles = (0, _styles.makeStyles)(function (theme) {
|
|
|
94
92
|
margin: '0.25rem 0.25rem 0 0.25rem',
|
|
95
93
|
height: '2rem'
|
|
96
94
|
}),
|
|
97
|
-
nameInverted: {
|
|
98
|
-
textShadow: theme.textShadows[1]
|
|
99
|
-
},
|
|
100
95
|
squareAppIconGhost: {
|
|
101
96
|
backgroundColor: (0, _styles.alpha)(theme.palette.primary.main, theme.palette.action.ghostOpacity),
|
|
102
97
|
border: "1px dashed ".concat((0, _styles.alpha)(theme.palette.primary.main, theme.palette.border.ghostOpacity))
|
|
@@ -157,7 +152,6 @@ var SquareAppIcon = function SquareAppIcon(_ref2) {
|
|
|
157
152
|
appIconProps = (0, _objectWithoutProperties2.default)(_ref2, _excluded);
|
|
158
153
|
|
|
159
154
|
var _useCozyTheme = (0, _CozyTheme.useCozyTheme)(),
|
|
160
|
-
themeVariant = _useCozyTheme.variant,
|
|
161
155
|
type = _useCozyTheme.type;
|
|
162
156
|
|
|
163
157
|
var classes = useStyles();
|
|
@@ -179,25 +173,32 @@ var SquareAppIcon = function SquareAppIcon(_ref2) {
|
|
|
179
173
|
var curr = prevVariant.current; // eslint-disable-next-line react-hooks/set-state-in-effect
|
|
180
174
|
|
|
181
175
|
if (curr === 'loading' && variant === 'error') setAnimationState('failed');
|
|
182
|
-
if (curr === 'loading' && (variant === 'default' || variant === undefined))
|
|
183
|
-
setAnimationState('success');
|
|
176
|
+
if (curr === 'loading' && (variant === 'default' || variant === undefined)) setAnimationState('success');
|
|
184
177
|
prevVariant.current = variant;
|
|
185
178
|
}, [variant]);
|
|
186
179
|
var exceptionVariant = ['ghost'];
|
|
187
|
-
var squareTheme = exceptionVariant.includes(variant) ? themeVariant : 'normal';
|
|
188
180
|
return /*#__PURE__*/_react.default.createElement("div", {
|
|
189
181
|
"data-testid": "square-app-icon",
|
|
190
182
|
className: (0, _classnames.default)(classes.tileWrapper, (0, _defineProperty2.default)({}, classes.detailedTileWrapper, display === 'detailed'))
|
|
191
|
-
}, /*#__PURE__*/_react.default.createElement(
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
183
|
+
}, /*#__PURE__*/_react.default.createElement(_Badge.default, {
|
|
184
|
+
badgeContent: variant === 'shortcut' && !hideShortcutBadge ? /*#__PURE__*/_react.default.createElement("div", {
|
|
185
|
+
className: "u-h-1-half u-miw-1-half u-bdrs-circle u-flex u-flex-items-center u-flex-justify-center",
|
|
186
|
+
style: {
|
|
187
|
+
backgroundColor: 'var(--paperBackgroundColor)',
|
|
188
|
+
color: 'var(--iconTextColor)',
|
|
189
|
+
boxShadow: 'var(--shadow3)'
|
|
190
|
+
}
|
|
191
|
+
}, /*#__PURE__*/_react.default.createElement(_Icon.default, {
|
|
195
192
|
size: "10",
|
|
196
193
|
icon: _LinkOut.default
|
|
197
|
-
}) : null,
|
|
194
|
+
})) : null,
|
|
198
195
|
className: (0, _classnames.default)((0, _defineProperty2.default)({}, 'u-mr-1', display === 'detailed')),
|
|
199
196
|
overlap: "rectangular",
|
|
200
|
-
invisible: variant !== 'shortcut' || hideShortcutBadge
|
|
197
|
+
invisible: variant !== 'shortcut' || hideShortcutBadge,
|
|
198
|
+
anchorOrigin: {
|
|
199
|
+
vertical: 'bottom',
|
|
200
|
+
horizontal: 'right'
|
|
201
|
+
}
|
|
201
202
|
}, /*#__PURE__*/_react.default.createElement(SquareAppIconSpinner, {
|
|
202
203
|
variant: variant,
|
|
203
204
|
animationState: animationState
|
|
@@ -218,7 +219,7 @@ var SquareAppIcon = function SquareAppIcon(_ref2) {
|
|
|
218
219
|
variant: "h2",
|
|
219
220
|
align: "center"
|
|
220
221
|
}, letter.toUpperCase()) : /*#__PURE__*/_react.default.createElement("div", {
|
|
221
|
-
className: (0, _classnames.default)(styles['SquareAppIcon-icon-container'],
|
|
222
|
+
className: (0, _classnames.default)(styles['SquareAppIcon-icon-container'], [styles['SquareAppIcon-icon-container-normal']])
|
|
222
223
|
}, /*#__PURE__*/_react.default.createElement("div", {
|
|
223
224
|
className: (0, _classnames.default)(styles['onEnd'], (0, _defineProperty2.default)({}, styles['isSuccess'], animationState === 'success'), (0, _defineProperty2.default)({}, styles['isFailed'], animationState === 'failed')),
|
|
224
225
|
onAnimationEnd: handleAnimationEnd
|
|
@@ -230,11 +231,11 @@ var SquareAppIcon = function SquareAppIcon(_ref2) {
|
|
|
230
231
|
color: "var(--primaryColor)"
|
|
231
232
|
}) : IconContent ? IconContent : /*#__PURE__*/_react.default.createElement("div", {
|
|
232
233
|
className: "u-w-2 u-h-2"
|
|
233
|
-
}, /*#__PURE__*/_react.default.createElement(_AppIcon.default, appIconProps)))))
|
|
234
|
+
}, /*#__PURE__*/_react.default.createElement(_AppIcon.default, appIconProps))))), display === 'detailed' ? /*#__PURE__*/_react.default.createElement(_ListItemText.default, {
|
|
234
235
|
primary: appName,
|
|
235
236
|
secondary: description
|
|
236
237
|
}) : /*#__PURE__*/_react.default.createElement(_Typography.default, {
|
|
237
|
-
className: (0, _classnames.default)(classes.name,
|
|
238
|
+
className: (0, _classnames.default)(classes.name, 'u-spacellipsis'),
|
|
238
239
|
variant: "h6",
|
|
239
240
|
align: "center"
|
|
240
241
|
}, appName));
|
|
@@ -39,8 +39,6 @@ var CozyTheme = function CozyTheme(_ref) {
|
|
|
39
39
|
};
|
|
40
40
|
|
|
41
41
|
CozyTheme.propTypes = {
|
|
42
|
-
variant: _propTypes.default.oneOf(['normal', 'inverted']),
|
|
43
|
-
|
|
44
42
|
/** Causes this element's children to appear as if they were direct children of the element's parent, ignoring the element itself. */
|
|
45
43
|
ignoreItself: _propTypes.default.bool,
|
|
46
44
|
|
|
@@ -50,7 +48,6 @@ CozyTheme.propTypes = {
|
|
|
50
48
|
children: _propTypes.default.node
|
|
51
49
|
};
|
|
52
50
|
CozyTheme.defaultProps = {
|
|
53
|
-
variant: 'normal',
|
|
54
51
|
ignoreCozySettings: false,
|
|
55
52
|
ignoreItself: true
|
|
56
53
|
};
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export default FieldInput;
|
|
2
|
-
declare function FieldInput({ name, labelProps, className, attributes: { subFields, ...restAttributes }, contacts, contact, error, helperText, label, isInvisible }: {
|
|
2
|
+
declare function FieldInput({ name, labelProps, className, attributes: { subFields, ...restAttributes }, contacts, contact, error, onRemove, showRemove, helperText, label, isInvisible }: {
|
|
3
3
|
name: any;
|
|
4
4
|
labelProps: any;
|
|
5
5
|
className: any;
|
|
@@ -10,6 +10,8 @@ declare function FieldInput({ name, labelProps, className, attributes: { subFiel
|
|
|
10
10
|
contacts: any;
|
|
11
11
|
contact: any;
|
|
12
12
|
error: any;
|
|
13
|
+
onRemove: any;
|
|
14
|
+
showRemove: any;
|
|
13
15
|
helperText: any;
|
|
14
16
|
label: any;
|
|
15
17
|
isInvisible: any;
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
export default FieldInputWrapper;
|
|
2
|
-
declare function FieldInputWrapper({ input, attributes: { component, layout, icon, isSecondary, validate, ...restAttributes }, variant, fullWidth, ...props }: {
|
|
2
|
+
declare function FieldInputWrapper({ input, attributes: { component, layout, isHalfWidth, 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
8
|
layout: any;
|
|
9
|
+
isHalfWidth: any;
|
|
9
10
|
icon: any;
|
|
10
11
|
isSecondary: any;
|
|
11
12
|
validate: any;
|
|
@@ -6,15 +6,12 @@ declare function CozyTheme({ ignoreCozySettings, ...props }: {
|
|
|
6
6
|
}): JSX.Element;
|
|
7
7
|
declare namespace CozyTheme {
|
|
8
8
|
namespace propTypes {
|
|
9
|
-
let variant: PropTypes.Requireable<string>;
|
|
10
9
|
let ignoreItself: PropTypes.Requireable<boolean>;
|
|
11
10
|
let ignoreCozySettings: PropTypes.Requireable<boolean>;
|
|
12
11
|
let className: PropTypes.Requireable<string>;
|
|
13
12
|
let children: PropTypes.Requireable<PropTypes.ReactNodeLike>;
|
|
14
13
|
}
|
|
15
14
|
namespace defaultProps {
|
|
16
|
-
let variant_1: string;
|
|
17
|
-
export { variant_1 as variant };
|
|
18
15
|
let ignoreCozySettings_1: boolean;
|
|
19
16
|
export { ignoreCozySettings_1 as ignoreCozySettings };
|
|
20
17
|
let ignoreItself_1: boolean;
|
package/dist/stylesheet.css
CHANGED
|
@@ -220,11 +220,6 @@
|
|
|
220
220
|
}
|
|
221
221
|
@media (max-width: 48rem) {
|
|
222
222
|
}
|
|
223
|
-
/* imported from styles.styl */
|
|
224
|
-
|
|
225
|
-
.styles__contact-form-field__wrapper___13Usq {
|
|
226
|
-
width: calc(100% - 3rem);
|
|
227
|
-
}
|
|
228
223
|
/* imported from styles.styl */
|
|
229
224
|
|
|
230
225
|
.styles__container___w8t8I {
|
|
@@ -343,26 +338,6 @@ it overrides nothing so there's no need for
|
|
|
343
338
|
}
|
|
344
339
|
/* imported from styles.styl */
|
|
345
340
|
|
|
346
|
-
.styles__c-label___24c92 {
|
|
347
|
-
text-transform: uppercase;
|
|
348
|
-
color: var(--secondaryTextColor);
|
|
349
|
-
font-size: 0.813rem;
|
|
350
|
-
font-weight: bold;
|
|
351
|
-
line-height: 1rem;
|
|
352
|
-
}
|
|
353
|
-
.styles__c-label___24c92.styles__is-error___1gUPb {
|
|
354
|
-
color: var(--errorColor);
|
|
355
|
-
}
|
|
356
|
-
.styles__c-label--block___1Zska {
|
|
357
|
-
display: block;
|
|
358
|
-
padding: 0.5rem 0;
|
|
359
|
-
}
|
|
360
|
-
@media (max-width: 48rem) {
|
|
361
|
-
}
|
|
362
|
-
@media (max-width: 48rem) {
|
|
363
|
-
}
|
|
364
|
-
/* imported from styles.styl */
|
|
365
|
-
|
|
366
341
|
.styles__o-field___2B6P3 {
|
|
367
342
|
position: relative;
|
|
368
343
|
display: flex;
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "cozy-ui-plus",
|
|
3
|
-
"version": "
|
|
3
|
+
"version": "6.1.0",
|
|
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",
|
|
@@ -37,7 +37,7 @@
|
|
|
37
37
|
"cozy-intent": "^2.31.1",
|
|
38
38
|
"cozy-logger": "^1.18.1",
|
|
39
39
|
"cozy-stack-client": "^60.21.1",
|
|
40
|
-
"cozy-ui": "^
|
|
40
|
+
"cozy-ui": "^138.1.0",
|
|
41
41
|
"jest": "30.3.0",
|
|
42
42
|
"jest-canvas-mock": "2.3.1",
|
|
43
43
|
"jest-environment-jsdom": "30.3.0",
|
|
@@ -68,10 +68,10 @@
|
|
|
68
68
|
"cozy-device-helper": ">=2.0.0",
|
|
69
69
|
"cozy-intent": ">=2.30.0",
|
|
70
70
|
"cozy-logger": ">=1.17.0",
|
|
71
|
-
"cozy-ui": ">=
|
|
71
|
+
"cozy-ui": ">=138.1.0",
|
|
72
72
|
"react": "^16 || ^17 || ^18",
|
|
73
73
|
"react-dom": "^16 || ^17 || ^18",
|
|
74
74
|
"twake-i18n": ">=0.3.0"
|
|
75
75
|
},
|
|
76
|
-
"gitHead": "
|
|
76
|
+
"gitHead": "0ac8873a7ba8909f3b02cb719d9fc05133bf5a1d"
|
|
77
77
|
}
|
|
@@ -4,7 +4,7 @@ import React, { useRef } from 'react'
|
|
|
4
4
|
import Icon from 'cozy-ui/transpiled/react/Icon'
|
|
5
5
|
import CrossSmallIcon from 'cozy-ui/transpiled/react/Icons/CrossSmall'
|
|
6
6
|
import PlusIcon from 'cozy-ui/transpiled/react/Icons/Plus'
|
|
7
|
-
import
|
|
7
|
+
import InputLabel from 'cozy-ui/transpiled/react/InputLabel'
|
|
8
8
|
import Stack from 'cozy-ui/transpiled/react/Stack'
|
|
9
9
|
import Button from 'cozy-ui/transpiled/react/deprecated/Button'
|
|
10
10
|
|
|
@@ -70,7 +70,7 @@ const CollectionField = props => {
|
|
|
70
70
|
|
|
71
71
|
return (
|
|
72
72
|
<FieldContainer {...rest}>
|
|
73
|
-
<
|
|
73
|
+
<InputLabel>{label}</InputLabel>
|
|
74
74
|
<Stack>
|
|
75
75
|
{values.length > 0 ? (
|
|
76
76
|
<Stack spacing="s">
|
|
@@ -4,16 +4,32 @@ import PropTypes from 'prop-types'
|
|
|
4
4
|
import React, { useState } from 'react'
|
|
5
5
|
import { Field } from 'react-final-form'
|
|
6
6
|
|
|
7
|
+
import { useBreakpoints } from 'cozy-ui/transpiled/react/providers/Breakpoints'
|
|
7
8
|
import { useI18n, useExtendI18n } from 'twake-i18n'
|
|
8
9
|
|
|
9
10
|
import FieldInputWrapper from './FieldInputWrapper'
|
|
10
11
|
import HasValueCondition from './HasValueCondition'
|
|
11
12
|
import { RelatedContactList } from './RelatedContactList'
|
|
13
|
+
import RemoveButton from './RemoveButton'
|
|
12
14
|
import { locales } from './locales'
|
|
13
|
-
import styles from './styles.styl'
|
|
14
15
|
import ContactAddressDialog from '../ContactAddressDialog'
|
|
15
16
|
import { fieldInputAttributesTypes, labelPropTypes } from '../types'
|
|
16
17
|
|
|
18
|
+
const FieldAndRemove = ({ showRemove, onRemove, ...props }) => {
|
|
19
|
+
const { isMobile } = useBreakpoints()
|
|
20
|
+
|
|
21
|
+
if (isMobile) {
|
|
22
|
+
return (
|
|
23
|
+
<div className="u-flex u-flex-items-center u-w-100">
|
|
24
|
+
<Field {...props} />
|
|
25
|
+
{showRemove && <RemoveButton onRemove={onRemove} />}
|
|
26
|
+
</div>
|
|
27
|
+
)
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
return <Field {...props} />
|
|
31
|
+
}
|
|
32
|
+
|
|
17
33
|
const FieldInput = ({
|
|
18
34
|
name,
|
|
19
35
|
labelProps,
|
|
@@ -22,6 +38,8 @@ const FieldInput = ({
|
|
|
22
38
|
contacts,
|
|
23
39
|
contact,
|
|
24
40
|
error,
|
|
41
|
+
onRemove,
|
|
42
|
+
showRemove,
|
|
25
43
|
helperText,
|
|
26
44
|
label,
|
|
27
45
|
isInvisible
|
|
@@ -33,6 +51,7 @@ const FieldInput = ({
|
|
|
33
51
|
useState(false)
|
|
34
52
|
useExtendI18n(locales)
|
|
35
53
|
const { t } = useI18n()
|
|
54
|
+
const { isMobile } = useBreakpoints()
|
|
36
55
|
|
|
37
56
|
const handleClick = () => {
|
|
38
57
|
if (name.includes('address')) {
|
|
@@ -50,14 +69,12 @@ const FieldInput = ({
|
|
|
50
69
|
|
|
51
70
|
return (
|
|
52
71
|
<div
|
|
53
|
-
className={cx(
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
{ 'u-flex': !isInvisible, 'u-dn': isInvisible }
|
|
58
|
-
)}
|
|
72
|
+
className={cx(className, 'u-flex-column-s u-flex-items-center u-w-100', {
|
|
73
|
+
'u-flex': !isInvisible,
|
|
74
|
+
'u-dn': isInvisible
|
|
75
|
+
})}
|
|
59
76
|
>
|
|
60
|
-
<
|
|
77
|
+
<FieldAndRemove
|
|
61
78
|
error={error}
|
|
62
79
|
helperText={helperText}
|
|
63
80
|
label={label}
|
|
@@ -66,6 +83,8 @@ const FieldInput = ({
|
|
|
66
83
|
name={name}
|
|
67
84
|
contact={contact}
|
|
68
85
|
component={FieldInputWrapper}
|
|
86
|
+
showRemove={showRemove}
|
|
87
|
+
onRemove={onRemove}
|
|
69
88
|
onFocus={onFocus}
|
|
70
89
|
onClick={handleClick}
|
|
71
90
|
/>
|
|
@@ -85,7 +104,7 @@ const FieldInput = ({
|
|
|
85
104
|
)}
|
|
86
105
|
{labelProps && (
|
|
87
106
|
<HasValueCondition name={name} otherCondition={hasBeenFocused}>
|
|
88
|
-
<div className="u-mt-half-s u-ml-half u-ml-0-s u-flex-shrink-0 u-w-auto u-miw-4">
|
|
107
|
+
<div className="u-mt-half-s u-ml-half u-ml-0-s u-flex-shrink-0 u-w-100-s u-w-auto u-miw-4">
|
|
89
108
|
<Field
|
|
90
109
|
attributes={labelProps}
|
|
91
110
|
name={`${name}Label`}
|
|
@@ -97,6 +116,7 @@ const FieldInput = ({
|
|
|
97
116
|
</div>
|
|
98
117
|
</HasValueCondition>
|
|
99
118
|
)}
|
|
119
|
+
{showRemove && !isMobile && <RemoveButton onRemove={onRemove} />}
|
|
100
120
|
</div>
|
|
101
121
|
)
|
|
102
122
|
}
|
|
@@ -4,10 +4,7 @@ import { FieldArray } from 'react-final-form-arrays'
|
|
|
4
4
|
|
|
5
5
|
import Button from 'cozy-ui/transpiled/react/Buttons'
|
|
6
6
|
import Icon from 'cozy-ui/transpiled/react/Icon'
|
|
7
|
-
import IconButton from 'cozy-ui/transpiled/react/IconButton'
|
|
8
|
-
import CrossCircleIcon from 'cozy-ui/transpiled/react/Icons/CrossCircle'
|
|
9
7
|
import PlusIcon from 'cozy-ui/transpiled/react/Icons/Plus'
|
|
10
|
-
import ListItemIcon from 'cozy-ui/transpiled/react/ListItemIcon'
|
|
11
8
|
import { useI18n, useExtendI18n } from 'twake-i18n'
|
|
12
9
|
|
|
13
10
|
import FieldInput from './FieldInput'
|
|
@@ -53,22 +50,14 @@ const FieldInputArray = ({
|
|
|
53
50
|
contacts={contacts}
|
|
54
51
|
contact={contact}
|
|
55
52
|
error={isError}
|
|
53
|
+
index={index}
|
|
54
|
+
showRemove={showRemove}
|
|
56
55
|
helperText={isError ? errors[inputName] : null}
|
|
57
56
|
name={inputName}
|
|
58
57
|
label={t(`Contacts.AddModal.ContactForm.fields.${name}`)}
|
|
59
58
|
labelProps={label}
|
|
59
|
+
onRemove={() => removeField(fields, index)}
|
|
60
60
|
/>
|
|
61
|
-
{showRemove && (
|
|
62
|
-
<ListItemIcon className="u-ml-half">
|
|
63
|
-
<IconButton
|
|
64
|
-
aria-label="delete"
|
|
65
|
-
size="medium"
|
|
66
|
-
onClick={() => removeField(fields, index)}
|
|
67
|
-
>
|
|
68
|
-
<Icon icon={CrossCircleIcon} />
|
|
69
|
-
</IconButton>
|
|
70
|
-
</ListItemIcon>
|
|
71
|
-
)}
|
|
72
61
|
</div>
|
|
73
62
|
)
|
|
74
63
|
})}
|
|
@@ -35,9 +35,11 @@ const FieldInputLayout = ({
|
|
|
35
35
|
'u-dn': isSecondary && !showSecondaryFields
|
|
36
36
|
})}
|
|
37
37
|
>
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
38
|
+
{icon && (
|
|
39
|
+
<div className="u-w-2-half">
|
|
40
|
+
<Icon icon={icon} color="var(--iconTextColor)" />
|
|
41
|
+
</div>
|
|
42
|
+
)}
|
|
41
43
|
<div className="u-w-100">
|
|
42
44
|
{layout === 'array' ? (
|
|
43
45
|
<FieldInputArray
|
|
@@ -13,11 +13,12 @@ const FieldInputWrapper = ({
|
|
|
13
13
|
attributes: {
|
|
14
14
|
component,
|
|
15
15
|
layout,
|
|
16
|
+
isHalfWidth,
|
|
16
17
|
icon,
|
|
17
18
|
isSecondary,
|
|
18
19
|
validate,
|
|
19
20
|
...restAttributes
|
|
20
|
-
}, // ⚠️ `layout` `icon` `isSecondary` `validate` are removed from attributes to avoid DOM propagration, only used for business rules
|
|
21
|
+
}, // ⚠️ `layout` `isHalfWidth` `icon` `isSecondary` `validate` are removed from attributes to avoid DOM propagration, only used for business rules
|
|
21
22
|
variant,
|
|
22
23
|
fullWidth,
|
|
23
24
|
...props
|
|
@@ -37,6 +38,7 @@ const FieldInputWrapper = ({
|
|
|
37
38
|
{...props}
|
|
38
39
|
variant={variant}
|
|
39
40
|
fullWidth={fullWidth}
|
|
41
|
+
size="small"
|
|
40
42
|
minRows="2"
|
|
41
43
|
/>
|
|
42
44
|
)
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import React from 'react'
|
|
2
|
+
|
|
3
|
+
import Icon from 'cozy-ui/transpiled/react/Icon'
|
|
4
|
+
import IconButton from 'cozy-ui/transpiled/react/IconButton'
|
|
5
|
+
import CrossCircleIcon from 'cozy-ui/transpiled/react/Icons/CrossCircle'
|
|
6
|
+
import ListItemIcon from 'cozy-ui/transpiled/react/ListItemIcon'
|
|
7
|
+
|
|
8
|
+
const RemoveButton = ({ onRemove }) => {
|
|
9
|
+
return (
|
|
10
|
+
<ListItemIcon className="u-ml-half">
|
|
11
|
+
<IconButton aria-label="delete" size="medium" onClick={onRemove}>
|
|
12
|
+
<Icon icon={CrossCircleIcon} />
|
|
13
|
+
</IconButton>
|
|
14
|
+
</ListItemIcon>
|
|
15
|
+
)
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
export default RemoveButton
|
|
@@ -40,6 +40,7 @@ export const fields = [
|
|
|
40
40
|
icon: null,
|
|
41
41
|
type: 'text',
|
|
42
42
|
layout: 'accordion',
|
|
43
|
+
isHalfWidth: true,
|
|
43
44
|
subFields: [
|
|
44
45
|
{
|
|
45
46
|
name: 'additionalName',
|
|
@@ -56,7 +57,8 @@ export const fields = [
|
|
|
56
57
|
{
|
|
57
58
|
name: 'familyName',
|
|
58
59
|
icon: null,
|
|
59
|
-
type: 'text'
|
|
60
|
+
type: 'text',
|
|
61
|
+
isHalfWidth: true
|
|
60
62
|
},
|
|
61
63
|
{
|
|
62
64
|
name: 'company',
|
|
@@ -460,17 +460,26 @@ export const makeFields = (customFields, defaultFields) => {
|
|
|
460
460
|
return defaultFields
|
|
461
461
|
}
|
|
462
462
|
|
|
463
|
-
|
|
463
|
+
let fields = [...defaultFields]
|
|
464
464
|
|
|
465
465
|
customFields.forEach(customField => {
|
|
466
466
|
const defaultField = fields.find(field => field.name === customField.name)
|
|
467
|
+
|
|
468
|
+
// If isRemoved is true, remove the field from the result
|
|
469
|
+
if (customField.isRemoved) {
|
|
470
|
+
if (defaultField) {
|
|
471
|
+
fields = fields.filter(field => field.name !== customField.name)
|
|
472
|
+
}
|
|
473
|
+
return
|
|
474
|
+
}
|
|
475
|
+
|
|
467
476
|
const _field = defaultField || customField
|
|
468
477
|
|
|
469
478
|
if (defaultField) {
|
|
470
479
|
Object.assign(_field, customField)
|
|
471
480
|
}
|
|
472
481
|
|
|
473
|
-
if (_field.position) {
|
|
482
|
+
if (_field.position !== undefined) {
|
|
474
483
|
if (defaultField) {
|
|
475
484
|
const fieldIndex = fields.indexOf(defaultField)
|
|
476
485
|
fields.splice(fieldIndex, 1)
|
|
@@ -441,6 +441,68 @@ describe('makeFields', () => {
|
|
|
441
441
|
}
|
|
442
442
|
])
|
|
443
443
|
})
|
|
444
|
+
|
|
445
|
+
it('should remove default field when custom field has isRemoved set to true', () => {
|
|
446
|
+
const defaultFields = [
|
|
447
|
+
{ name: 'firstname' },
|
|
448
|
+
{ name: 'lastname' },
|
|
449
|
+
{ name: 'email' }
|
|
450
|
+
]
|
|
451
|
+
const customFields = [{ name: 'lastname', isRemoved: true }]
|
|
452
|
+
|
|
453
|
+
const res = makeFields(customFields, defaultFields)
|
|
454
|
+
|
|
455
|
+
expect(res).toStrictEqual([{ name: 'firstname' }, { name: 'email' }])
|
|
456
|
+
})
|
|
457
|
+
|
|
458
|
+
it('should remove multiple default fields when multiple custom fields have isRemoved set to true', () => {
|
|
459
|
+
const defaultFields = [
|
|
460
|
+
{ name: 'firstname' },
|
|
461
|
+
{ name: 'lastname' },
|
|
462
|
+
{ name: 'email' },
|
|
463
|
+
{ name: 'phone' }
|
|
464
|
+
]
|
|
465
|
+
const customFields = [
|
|
466
|
+
{ name: 'lastname', isRemoved: true },
|
|
467
|
+
{ name: 'phone', isRemoved: true }
|
|
468
|
+
]
|
|
469
|
+
|
|
470
|
+
const res = makeFields(customFields, defaultFields)
|
|
471
|
+
|
|
472
|
+
expect(res).toStrictEqual([{ name: 'firstname' }, { name: 'email' }])
|
|
473
|
+
})
|
|
474
|
+
|
|
475
|
+
it('should ignore custom fields with isRemoved but no matching default field', () => {
|
|
476
|
+
const defaultFields = [{ name: 'firstname' }, { name: 'lastname' }]
|
|
477
|
+
const customFields = [{ name: 'nonexistent', isRemoved: true }]
|
|
478
|
+
|
|
479
|
+
const res = makeFields(customFields, defaultFields)
|
|
480
|
+
|
|
481
|
+
expect(res).toStrictEqual(defaultFields)
|
|
482
|
+
})
|
|
483
|
+
|
|
484
|
+
it('should handle mixed custom fields with isRemoved, position, and property overrides', () => {
|
|
485
|
+
const defaultFields = [
|
|
486
|
+
{ name: 'firstname', type: 'text' },
|
|
487
|
+
{ name: 'lastname', type: 'text' },
|
|
488
|
+
{ name: 'email', type: 'email' },
|
|
489
|
+
{ name: 'phone', type: 'tel' }
|
|
490
|
+
]
|
|
491
|
+
const customFields = [
|
|
492
|
+
{ name: 'lastname', isRemoved: true },
|
|
493
|
+
{ name: 'email', isSecondary: true, position: 0 },
|
|
494
|
+
{ name: 'middlename', position: 1 }
|
|
495
|
+
]
|
|
496
|
+
|
|
497
|
+
const res = makeFields(customFields, defaultFields)
|
|
498
|
+
|
|
499
|
+
expect(res).toStrictEqual([
|
|
500
|
+
{ name: 'email', type: 'email', isSecondary: true, position: 0 },
|
|
501
|
+
{ name: 'middlename', position: 1 },
|
|
502
|
+
{ name: 'firstname', type: 'text' },
|
|
503
|
+
{ name: 'phone', type: 'tel' }
|
|
504
|
+
])
|
|
505
|
+
})
|
|
444
506
|
})
|
|
445
507
|
|
|
446
508
|
describe('hasNoValues', () => {
|
|
@@ -3,7 +3,9 @@ import React, { useState } from 'react'
|
|
|
3
3
|
import { Form } from 'react-final-form'
|
|
4
4
|
|
|
5
5
|
import { getHasManyItems } from 'cozy-client/dist/associations/HasMany'
|
|
6
|
+
import Box from 'cozy-ui/transpiled/react/Box'
|
|
6
7
|
import Button from 'cozy-ui/transpiled/react/Buttons'
|
|
8
|
+
import { useBreakpoints } from 'cozy-ui/transpiled/react/providers/Breakpoints'
|
|
7
9
|
import { useI18n, useExtendI18n } from 'twake-i18n'
|
|
8
10
|
|
|
9
11
|
import FieldInputLayout from './FieldInputLayout'
|
|
@@ -49,6 +51,7 @@ const ContactForm = ({ contacts, contact, customFieldsProps, onSubmit }) => {
|
|
|
49
51
|
const { t } = useI18n()
|
|
50
52
|
const { fields, makeCustomFieldsFormValues, makeCustomContactValues } =
|
|
51
53
|
customFieldsProps
|
|
54
|
+
const { isMobile } = useBreakpoints()
|
|
52
55
|
|
|
53
56
|
const _fields = makeFields(fields, defaultFields)
|
|
54
57
|
const hasSecondaryFields = _fields.some(el => el.isSecondary)
|
|
@@ -90,20 +93,30 @@ const ContactForm = ({ contacts, contact, customFieldsProps, onSubmit }) => {
|
|
|
90
93
|
onSubmit={handleSubmit}
|
|
91
94
|
className="u-flex u-flex-column"
|
|
92
95
|
>
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
96
|
+
<div className="u-flex u-flex-wrap u-flex-justify-between">
|
|
97
|
+
{_fields.map((attributes, index) => (
|
|
98
|
+
<Box
|
|
99
|
+
key={index}
|
|
100
|
+
width={
|
|
101
|
+
attributes.isHalfWidth && !isMobile
|
|
102
|
+
? 'calc(50% - 0.5rem)'
|
|
103
|
+
: '100%'
|
|
104
|
+
}
|
|
105
|
+
>
|
|
106
|
+
<FieldInputLayout
|
|
107
|
+
attributes={attributes}
|
|
108
|
+
contacts={contacts}
|
|
109
|
+
contact={contact}
|
|
110
|
+
showSecondaryFields={showSecondaryFields}
|
|
111
|
+
formProps={{
|
|
112
|
+
valid,
|
|
113
|
+
submitFailed,
|
|
114
|
+
errors
|
|
115
|
+
}}
|
|
116
|
+
/>
|
|
117
|
+
</Box>
|
|
118
|
+
))}
|
|
119
|
+
</div>
|
|
107
120
|
{hasSecondaryFields && !showSecondaryFields && (
|
|
108
121
|
<div>
|
|
109
122
|
<Button
|
|
@@ -22,7 +22,6 @@ import AddContactDialog from './AddContact/AddContactDialog'
|
|
|
22
22
|
import ContactsListContent from './ContactsListContent'
|
|
23
23
|
import MobileHeader from './MobileHeader'
|
|
24
24
|
import styles from './styles.styl'
|
|
25
|
-
import CozyTheme from '../providers/CozyTheme'
|
|
26
25
|
|
|
27
26
|
const ContactsListModal = ({
|
|
28
27
|
onItemClick,
|
|
@@ -64,9 +63,7 @@ const ContactsListModal = ({
|
|
|
64
63
|
|
|
65
64
|
return (
|
|
66
65
|
<TopAnchoredDialog {...dialogProps}>
|
|
67
|
-
<
|
|
68
|
-
<DialogCloseButton onClick={dismissAction} />
|
|
69
|
-
</CozyTheme>
|
|
66
|
+
<DialogCloseButton onClick={dismissAction} />
|
|
70
67
|
<DialogTitle
|
|
71
68
|
{...dialogTitleProps}
|
|
72
69
|
className={cx(dialogTitleProps.className, {
|