carbon-react 111.17.0 → 111.19.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/esm/__internal__/form-field/form-field.component.js +18 -4
- package/esm/components/card/card.component.d.ts +3 -1
- package/esm/components/card/card.component.js +4 -1
- package/esm/components/card/card.style.d.ts +1 -0
- package/esm/components/card/card.style.js +6 -1
- package/esm/components/tabs/tab/tab.component.js +9 -9
- package/esm/components/tabs/tab/tab.d.ts +3 -3
- package/esm/components/tabs/tabs.component.js +43 -19
- package/esm/components/tabs/tabs.d.ts +4 -0
- package/lib/__internal__/form-field/form-field.component.js +17 -3
- package/lib/components/card/card.component.d.ts +3 -1
- package/lib/components/card/card.component.js +4 -1
- package/lib/components/card/card.style.d.ts +1 -0
- package/lib/components/card/card.style.js +6 -1
- package/lib/components/tabs/tab/tab.component.js +9 -9
- package/lib/components/tabs/tab/tab.d.ts +3 -3
- package/lib/components/tabs/tabs.component.js +42 -19
- package/lib/components/tabs/tabs.d.ts +4 -0
- package/package.json +1 -1
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
|
|
2
2
|
|
|
3
|
-
import React, { useContext, useEffect, useMemo } from "react";
|
|
3
|
+
import React, { useContext, useEffect, useLayoutEffect, useMemo, useRef } from "react";
|
|
4
4
|
import PropTypes from "prop-types";
|
|
5
5
|
import invariant from "invariant";
|
|
6
6
|
import { filterStyledSystemMarginProps } from "../../style/utils";
|
|
@@ -62,10 +62,24 @@ const FormField = ({
|
|
|
62
62
|
setWarning,
|
|
63
63
|
setInfo
|
|
64
64
|
} = useContext(TabContext);
|
|
65
|
+
const isMounted = useRef(false);
|
|
66
|
+
useLayoutEffect(() => {
|
|
67
|
+
isMounted.current = true;
|
|
68
|
+
return () => {
|
|
69
|
+
isMounted.current = false;
|
|
70
|
+
};
|
|
71
|
+
}, []);
|
|
65
72
|
useEffect(() => {
|
|
66
|
-
if (setError) setError(id,
|
|
67
|
-
if (setWarning) setWarning(id,
|
|
68
|
-
if (setInfo) setInfo(id,
|
|
73
|
+
if (setError) setError(id, error);
|
|
74
|
+
if (setWarning) setWarning(id, warning);
|
|
75
|
+
if (setInfo) setInfo(id, info);
|
|
76
|
+
return () => {
|
|
77
|
+
if (!isMounted.current) {
|
|
78
|
+
if (setError && error) setError(id, false);
|
|
79
|
+
if (setWarning && warning) setWarning(id, false);
|
|
80
|
+
if (setInfo && info) setInfo(id, false);
|
|
81
|
+
}
|
|
82
|
+
};
|
|
69
83
|
}, [id, setError, setWarning, setInfo, error, warning, info]);
|
|
70
84
|
const marginProps = filterStyledSystemMarginProps(rest);
|
|
71
85
|
const fieldHelp = fieldHelpContent ? /*#__PURE__*/React.createElement(FieldHelp, {
|
|
@@ -22,6 +22,8 @@ export interface CardProps extends MarginProps {
|
|
|
22
22
|
children: React.ReactNode;
|
|
23
23
|
/** Flag to indicate if card is draggable */
|
|
24
24
|
draggable?: boolean;
|
|
25
|
+
/** Height of the component (any valid CSS value) */
|
|
26
|
+
height?: string;
|
|
25
27
|
/** Flag to indicate if card is interactive */
|
|
26
28
|
interactive?: boolean;
|
|
27
29
|
/** Size of card for applying padding */
|
|
@@ -32,7 +34,7 @@ export interface CardProps extends MarginProps {
|
|
|
32
34
|
hoverBoxShadow?: BoxShadowsType;
|
|
33
35
|
}
|
|
34
36
|
declare const Card: {
|
|
35
|
-
({ "data-element": dataElement, "data-role": dataRole, dataRole: oldDataRole, action, children, cardWidth, draggable, interactive, spacing, boxShadow, hoverBoxShadow, ...rest }: CardProps): JSX.Element;
|
|
37
|
+
({ "data-element": dataElement, "data-role": dataRole, dataRole: oldDataRole, action, children, cardWidth, draggable, height, interactive, spacing, boxShadow, hoverBoxShadow, ...rest }: CardProps): JSX.Element;
|
|
36
38
|
displayName: string;
|
|
37
39
|
};
|
|
38
40
|
export default Card;
|
|
@@ -22,6 +22,7 @@ const Card = ({
|
|
|
22
22
|
children,
|
|
23
23
|
cardWidth = "500px",
|
|
24
24
|
draggable,
|
|
25
|
+
height,
|
|
25
26
|
interactive,
|
|
26
27
|
spacing = "medium",
|
|
27
28
|
boxShadow,
|
|
@@ -60,7 +61,8 @@ const Card = ({
|
|
|
60
61
|
spacing: spacing,
|
|
61
62
|
boxShadow: boxShadow,
|
|
62
63
|
hoverBoxShadow: hoverBoxShadow,
|
|
63
|
-
onClick: interactive && !draggable ? action : undefined
|
|
64
|
+
onClick: interactive && !draggable ? action : undefined,
|
|
65
|
+
height: height
|
|
64
66
|
}, interactive && {
|
|
65
67
|
tabIndex: 0,
|
|
66
68
|
type: "button"
|
|
@@ -78,6 +80,7 @@ Card.propTypes = {
|
|
|
78
80
|
"data-role": PropTypes.string,
|
|
79
81
|
"dataRole": PropTypes.string,
|
|
80
82
|
"draggable": PropTypes.bool,
|
|
83
|
+
"height": PropTypes.string,
|
|
81
84
|
"hoverBoxShadow": PropTypes.any,
|
|
82
85
|
"interactive": PropTypes.bool,
|
|
83
86
|
"m": PropTypes.oneOfType([PropTypes.arrayOf(PropTypes.oneOfType([PropTypes.oneOf([null]), PropTypes.number, PropTypes.shape({
|
|
@@ -11,6 +11,7 @@ const StyledCard = styled.div`
|
|
|
11
11
|
cardWidth,
|
|
12
12
|
interactive,
|
|
13
13
|
draggable,
|
|
14
|
+
height,
|
|
14
15
|
spacing,
|
|
15
16
|
boxShadow = "boxShadow050",
|
|
16
17
|
hoverBoxShadow = "boxShadow100"
|
|
@@ -19,12 +20,16 @@ const StyledCard = styled.div`
|
|
|
19
20
|
border: none;
|
|
20
21
|
box-shadow: var(--${boxShadow});
|
|
21
22
|
color: var(--colorsUtilityYin090);
|
|
23
|
+
display: flex;
|
|
24
|
+
flex-direction: column;
|
|
25
|
+
height: ${height};
|
|
26
|
+
justify-content: space-between;
|
|
22
27
|
margin: 25px;
|
|
28
|
+
outline: none;
|
|
23
29
|
padding: ${paddingSizes[spacing]};
|
|
24
30
|
transition: all 0.3s ease-in-out;
|
|
25
31
|
vertical-align: top;
|
|
26
32
|
width: ${cardWidth};
|
|
27
|
-
outline: none;
|
|
28
33
|
${margin}
|
|
29
34
|
|
|
30
35
|
${interactive && css`
|
|
@@ -27,24 +27,24 @@ const Tab = ({
|
|
|
27
27
|
const [tabErrors, setTabErrors] = useState({});
|
|
28
28
|
const [tabWarnings, setTabWarnings] = useState({});
|
|
29
29
|
const [tabInfos, setTabInfos] = useState({});
|
|
30
|
-
const setError = useCallback((childId,
|
|
31
|
-
if (tabErrors[childId] !==
|
|
30
|
+
const setError = useCallback((childId, error) => {
|
|
31
|
+
if (tabErrors[childId] !== error) {
|
|
32
32
|
setTabErrors({ ...tabErrors,
|
|
33
|
-
[childId]:
|
|
33
|
+
[childId]: error
|
|
34
34
|
});
|
|
35
35
|
}
|
|
36
36
|
}, [tabErrors]);
|
|
37
|
-
const setWarning = useCallback((childId,
|
|
38
|
-
if (tabWarnings[childId] !==
|
|
37
|
+
const setWarning = useCallback((childId, warning) => {
|
|
38
|
+
if (tabWarnings[childId] !== warning) {
|
|
39
39
|
setTabWarnings({ ...tabWarnings,
|
|
40
|
-
[childId]:
|
|
40
|
+
[childId]: warning
|
|
41
41
|
});
|
|
42
42
|
}
|
|
43
43
|
}, [tabWarnings]);
|
|
44
|
-
const setInfo = useCallback((childId,
|
|
45
|
-
if (tabInfos[childId] !==
|
|
44
|
+
const setInfo = useCallback((childId, info) => {
|
|
45
|
+
if (tabInfos[childId] !== info) {
|
|
46
46
|
setTabInfos({ ...tabInfos,
|
|
47
|
-
[childId]:
|
|
47
|
+
[childId]: info
|
|
48
48
|
});
|
|
49
49
|
}
|
|
50
50
|
}, [tabInfos]);
|
|
@@ -2,9 +2,9 @@ import * as React from "react";
|
|
|
2
2
|
import { PaddingProps } from "styled-system";
|
|
3
3
|
|
|
4
4
|
export interface TabContextProps {
|
|
5
|
-
setError?: (childId: string,
|
|
6
|
-
setWarning?: (childId: string,
|
|
7
|
-
setInfo?: (childId: string,
|
|
5
|
+
setError?: (childId: string, error?: boolean | string) => void;
|
|
6
|
+
setWarning?: (childId: string, warning?: boolean | string) => void;
|
|
7
|
+
setInfo?: (childId: string, info?: boolean | string) => void;
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
export interface TabProps extends PaddingProps {
|
|
@@ -27,6 +27,7 @@ const Tabs = ({
|
|
|
27
27
|
variant = "default",
|
|
28
28
|
validationStatusOverride,
|
|
29
29
|
headerWidth,
|
|
30
|
+
showValidationsSummary,
|
|
30
31
|
...rest
|
|
31
32
|
}) => {
|
|
32
33
|
/** The children nodes converted into an Array */
|
|
@@ -48,24 +49,24 @@ const Tabs = ({
|
|
|
48
49
|
const [tabsErrors, setTabsErrors] = useState({});
|
|
49
50
|
const [tabsWarnings, setTabsWarnings] = useState({});
|
|
50
51
|
const [tabsInfos, setTabsInfos] = useState({});
|
|
51
|
-
const updateErrors = useCallback((id,
|
|
52
|
-
if (tabsErrors[id] !==
|
|
52
|
+
const updateErrors = useCallback((id, error) => {
|
|
53
|
+
if (tabsErrors[id] !== error) {
|
|
53
54
|
setTabsErrors({ ...tabsErrors,
|
|
54
|
-
[id]:
|
|
55
|
+
[id]: error
|
|
55
56
|
});
|
|
56
57
|
}
|
|
57
58
|
}, [tabsErrors]);
|
|
58
|
-
const updateWarnings = useCallback((id,
|
|
59
|
-
if (tabsWarnings[id] !==
|
|
59
|
+
const updateWarnings = useCallback((id, warning) => {
|
|
60
|
+
if (tabsWarnings[id] !== warning) {
|
|
60
61
|
setTabsWarnings({ ...tabsWarnings,
|
|
61
|
-
[id]:
|
|
62
|
+
[id]: warning
|
|
62
63
|
});
|
|
63
64
|
}
|
|
64
65
|
}, [tabsWarnings]);
|
|
65
|
-
const updateInfos = useCallback((id,
|
|
66
|
-
if (tabsInfos[id] !==
|
|
66
|
+
const updateInfos = useCallback((id, info) => {
|
|
67
|
+
if (tabsInfos[id] !== info) {
|
|
67
68
|
setTabsInfos({ ...tabsInfos,
|
|
68
|
-
[id]:
|
|
69
|
+
[id]: info
|
|
69
70
|
});
|
|
70
71
|
}
|
|
71
72
|
}, [tabsInfos]);
|
|
@@ -182,16 +183,34 @@ const Tabs = ({
|
|
|
182
183
|
customLayout
|
|
183
184
|
} = child.props;
|
|
184
185
|
const refId = `${tabId}-tab`;
|
|
185
|
-
const errors = tabsErrors[tabId]
|
|
186
|
-
const warnings = tabsWarnings[tabId]
|
|
187
|
-
const infos = tabsInfos[tabId]
|
|
186
|
+
const errors = tabsErrors[tabId];
|
|
187
|
+
const warnings = tabsWarnings[tabId];
|
|
188
|
+
const infos = tabsInfos[tabId];
|
|
189
|
+
const errorsCount = errors && Object.entries(errors).filter(tab => tab[1]).length;
|
|
190
|
+
const warningsCount = warnings && Object.entries(warnings).filter(tab => tab[1]).length;
|
|
191
|
+
const infosCount = infos && Object.entries(infos).filter(tab => tab[1]).length;
|
|
188
192
|
const hasOverride = validationStatusOverride && validationStatusOverride[tabId];
|
|
189
193
|
const errorOverride = hasOverride && validationStatusOverride[tabId].error;
|
|
190
194
|
const warningOverride = hasOverride && validationStatusOverride[tabId].warning;
|
|
191
195
|
const infoOverride = hasOverride && validationStatusOverride[tabId].info;
|
|
192
|
-
const tabHasError = errorOverride !== undefined ? errorOverride :
|
|
193
|
-
const tabHasWarning = warningOverride !== undefined ? warningOverride :
|
|
194
|
-
const tabHasInfo = infoOverride !== undefined ? infoOverride :
|
|
196
|
+
const tabHasError = errorOverride !== undefined ? errorOverride : !!errorsCount;
|
|
197
|
+
const tabHasWarning = warningOverride !== undefined ? warningOverride : !!warningsCount && !tabHasError;
|
|
198
|
+
const tabHasInfo = infoOverride !== undefined ? infoOverride : !!infosCount && !tabHasError && !tabHasWarning;
|
|
199
|
+
|
|
200
|
+
const getValidationMessage = (message, validations = {}) => {
|
|
201
|
+
const summaryOfMessages = Object.values(validations).filter(value => value && typeof value === "string");
|
|
202
|
+
|
|
203
|
+
if (!showValidationsSummary || !summaryOfMessages.length) {
|
|
204
|
+
return message;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
if (summaryOfMessages.length === 1) {
|
|
208
|
+
return summaryOfMessages[0];
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
return summaryOfMessages.map(value => `• ${value}`).join("\n");
|
|
212
|
+
};
|
|
213
|
+
|
|
195
214
|
const tabTitle = /*#__PURE__*/React.createElement(TabTitle, {
|
|
196
215
|
position: isInSidebar ? "left" : position,
|
|
197
216
|
className: child.props.className || "",
|
|
@@ -212,9 +231,9 @@ const Tabs = ({
|
|
|
212
231
|
borders: borders !== "off",
|
|
213
232
|
siblings: siblings,
|
|
214
233
|
titlePosition: titlePosition,
|
|
215
|
-
errorMessage: errorMessage,
|
|
216
|
-
warningMessage: warningMessage,
|
|
217
|
-
infoMessage: infoMessage,
|
|
234
|
+
errorMessage: getValidationMessage(errorMessage, errors),
|
|
235
|
+
warningMessage: getValidationMessage(warningMessage, warnings),
|
|
236
|
+
infoMessage: getValidationMessage(infoMessage, infos),
|
|
218
237
|
alternateStyling: variant === "alternate",
|
|
219
238
|
noLeftBorder: ["no left side", "no sides"].includes(borders),
|
|
220
239
|
noRightBorder: ["no right side", "no sides"].includes(borders),
|
|
@@ -341,6 +360,11 @@ Tabs.propTypes = { ...marginPropTypes,
|
|
|
341
360
|
warning: PropTypes.bool,
|
|
342
361
|
info: PropTypes.bool
|
|
343
362
|
})
|
|
344
|
-
})
|
|
363
|
+
}),
|
|
364
|
+
|
|
365
|
+
/** When this prop is set any string validation failures in the children of each Tab
|
|
366
|
+
* will be summaraised in the Tooltip next to the Tab title
|
|
367
|
+
*/
|
|
368
|
+
showValidationsSummary: PropTypes.bool
|
|
345
369
|
};
|
|
346
370
|
export { Tabs, Tab };
|
|
@@ -40,6 +40,10 @@ export interface TabsProps extends MarginProps {
|
|
|
40
40
|
info?: boolean;
|
|
41
41
|
};
|
|
42
42
|
};
|
|
43
|
+
/** When this prop is set any string validation failures in the children of each Tab
|
|
44
|
+
* will be summaraised in the Tooltip next to the Tab title
|
|
45
|
+
*/
|
|
46
|
+
showValidationsSummary?: boolean;
|
|
43
47
|
}
|
|
44
48
|
|
|
45
49
|
declare function Tabs(props: TabsProps): JSX.Element;
|
|
@@ -84,10 +84,24 @@ const FormField = ({
|
|
|
84
84
|
setWarning,
|
|
85
85
|
setInfo
|
|
86
86
|
} = (0, _react.useContext)(_tab.TabContext);
|
|
87
|
+
const isMounted = (0, _react.useRef)(false);
|
|
88
|
+
(0, _react.useLayoutEffect)(() => {
|
|
89
|
+
isMounted.current = true;
|
|
90
|
+
return () => {
|
|
91
|
+
isMounted.current = false;
|
|
92
|
+
};
|
|
93
|
+
}, []);
|
|
87
94
|
(0, _react.useEffect)(() => {
|
|
88
|
-
if (setError) setError(id,
|
|
89
|
-
if (setWarning) setWarning(id,
|
|
90
|
-
if (setInfo) setInfo(id,
|
|
95
|
+
if (setError) setError(id, error);
|
|
96
|
+
if (setWarning) setWarning(id, warning);
|
|
97
|
+
if (setInfo) setInfo(id, info);
|
|
98
|
+
return () => {
|
|
99
|
+
if (!isMounted.current) {
|
|
100
|
+
if (setError && error) setError(id, false);
|
|
101
|
+
if (setWarning && warning) setWarning(id, false);
|
|
102
|
+
if (setInfo && info) setInfo(id, false);
|
|
103
|
+
}
|
|
104
|
+
};
|
|
91
105
|
}, [id, setError, setWarning, setInfo, error, warning, info]);
|
|
92
106
|
const marginProps = (0, _utils.filterStyledSystemMarginProps)(rest);
|
|
93
107
|
const fieldHelp = fieldHelpContent ? /*#__PURE__*/_react.default.createElement(_fieldHelp.default, {
|
|
@@ -22,6 +22,8 @@ export interface CardProps extends MarginProps {
|
|
|
22
22
|
children: React.ReactNode;
|
|
23
23
|
/** Flag to indicate if card is draggable */
|
|
24
24
|
draggable?: boolean;
|
|
25
|
+
/** Height of the component (any valid CSS value) */
|
|
26
|
+
height?: string;
|
|
25
27
|
/** Flag to indicate if card is interactive */
|
|
26
28
|
interactive?: boolean;
|
|
27
29
|
/** Size of card for applying padding */
|
|
@@ -32,7 +34,7 @@ export interface CardProps extends MarginProps {
|
|
|
32
34
|
hoverBoxShadow?: BoxShadowsType;
|
|
33
35
|
}
|
|
34
36
|
declare const Card: {
|
|
35
|
-
({ "data-element": dataElement, "data-role": dataRole, dataRole: oldDataRole, action, children, cardWidth, draggable, interactive, spacing, boxShadow, hoverBoxShadow, ...rest }: CardProps): JSX.Element;
|
|
37
|
+
({ "data-element": dataElement, "data-role": dataRole, dataRole: oldDataRole, action, children, cardWidth, draggable, height, interactive, spacing, boxShadow, hoverBoxShadow, ...rest }: CardProps): JSX.Element;
|
|
36
38
|
displayName: string;
|
|
37
39
|
};
|
|
38
40
|
export default Card;
|
|
@@ -41,6 +41,7 @@ const Card = ({
|
|
|
41
41
|
children,
|
|
42
42
|
cardWidth = "500px",
|
|
43
43
|
draggable,
|
|
44
|
+
height,
|
|
44
45
|
interactive,
|
|
45
46
|
spacing = "medium",
|
|
46
47
|
boxShadow,
|
|
@@ -80,7 +81,8 @@ const Card = ({
|
|
|
80
81
|
spacing: spacing,
|
|
81
82
|
boxShadow: boxShadow,
|
|
82
83
|
hoverBoxShadow: hoverBoxShadow,
|
|
83
|
-
onClick: interactive && !draggable ? action : undefined
|
|
84
|
+
onClick: interactive && !draggable ? action : undefined,
|
|
85
|
+
height: height
|
|
84
86
|
}, interactive && {
|
|
85
87
|
tabIndex: 0,
|
|
86
88
|
type: "button"
|
|
@@ -98,6 +100,7 @@ Card.propTypes = {
|
|
|
98
100
|
"data-role": _propTypes.default.string,
|
|
99
101
|
"dataRole": _propTypes.default.string,
|
|
100
102
|
"draggable": _propTypes.default.bool,
|
|
103
|
+
"height": _propTypes.default.string,
|
|
101
104
|
"hoverBoxShadow": _propTypes.default.any,
|
|
102
105
|
"interactive": _propTypes.default.bool,
|
|
103
106
|
"m": _propTypes.default.oneOfType([_propTypes.default.arrayOf(_propTypes.default.oneOfType([_propTypes.default.oneOf([null]), _propTypes.default.number, _propTypes.default.shape({
|
|
@@ -27,6 +27,7 @@ const StyledCard = _styledComponents.default.div`
|
|
|
27
27
|
cardWidth,
|
|
28
28
|
interactive,
|
|
29
29
|
draggable,
|
|
30
|
+
height,
|
|
30
31
|
spacing,
|
|
31
32
|
boxShadow = "boxShadow050",
|
|
32
33
|
hoverBoxShadow = "boxShadow100"
|
|
@@ -35,12 +36,16 @@ const StyledCard = _styledComponents.default.div`
|
|
|
35
36
|
border: none;
|
|
36
37
|
box-shadow: var(--${boxShadow});
|
|
37
38
|
color: var(--colorsUtilityYin090);
|
|
39
|
+
display: flex;
|
|
40
|
+
flex-direction: column;
|
|
41
|
+
height: ${height};
|
|
42
|
+
justify-content: space-between;
|
|
38
43
|
margin: 25px;
|
|
44
|
+
outline: none;
|
|
39
45
|
padding: ${paddingSizes[spacing]};
|
|
40
46
|
transition: all 0.3s ease-in-out;
|
|
41
47
|
vertical-align: top;
|
|
42
48
|
width: ${cardWidth};
|
|
43
|
-
outline: none;
|
|
44
49
|
${_styledSystem.margin}
|
|
45
50
|
|
|
46
51
|
${interactive && (0, _styledComponents.css)`
|
|
@@ -48,24 +48,24 @@ const Tab = ({
|
|
|
48
48
|
const [tabErrors, setTabErrors] = (0, _react.useState)({});
|
|
49
49
|
const [tabWarnings, setTabWarnings] = (0, _react.useState)({});
|
|
50
50
|
const [tabInfos, setTabInfos] = (0, _react.useState)({});
|
|
51
|
-
const setError = (0, _react.useCallback)((childId,
|
|
52
|
-
if (tabErrors[childId] !==
|
|
51
|
+
const setError = (0, _react.useCallback)((childId, error) => {
|
|
52
|
+
if (tabErrors[childId] !== error) {
|
|
53
53
|
setTabErrors({ ...tabErrors,
|
|
54
|
-
[childId]:
|
|
54
|
+
[childId]: error
|
|
55
55
|
});
|
|
56
56
|
}
|
|
57
57
|
}, [tabErrors]);
|
|
58
|
-
const setWarning = (0, _react.useCallback)((childId,
|
|
59
|
-
if (tabWarnings[childId] !==
|
|
58
|
+
const setWarning = (0, _react.useCallback)((childId, warning) => {
|
|
59
|
+
if (tabWarnings[childId] !== warning) {
|
|
60
60
|
setTabWarnings({ ...tabWarnings,
|
|
61
|
-
[childId]:
|
|
61
|
+
[childId]: warning
|
|
62
62
|
});
|
|
63
63
|
}
|
|
64
64
|
}, [tabWarnings]);
|
|
65
|
-
const setInfo = (0, _react.useCallback)((childId,
|
|
66
|
-
if (tabInfos[childId] !==
|
|
65
|
+
const setInfo = (0, _react.useCallback)((childId, info) => {
|
|
66
|
+
if (tabInfos[childId] !== info) {
|
|
67
67
|
setTabInfos({ ...tabInfos,
|
|
68
|
-
[childId]:
|
|
68
|
+
[childId]: info
|
|
69
69
|
});
|
|
70
70
|
}
|
|
71
71
|
}, [tabInfos]);
|
|
@@ -2,9 +2,9 @@ import * as React from "react";
|
|
|
2
2
|
import { PaddingProps } from "styled-system";
|
|
3
3
|
|
|
4
4
|
export interface TabContextProps {
|
|
5
|
-
setError?: (childId: string,
|
|
6
|
-
setWarning?: (childId: string,
|
|
7
|
-
setInfo?: (childId: string,
|
|
5
|
+
setError?: (childId: string, error?: boolean | string) => void;
|
|
6
|
+
setWarning?: (childId: string, warning?: boolean | string) => void;
|
|
7
|
+
setInfo?: (childId: string, info?: boolean | string) => void;
|
|
8
8
|
}
|
|
9
9
|
|
|
10
10
|
export interface TabProps extends PaddingProps {
|
|
@@ -57,6 +57,7 @@ const Tabs = ({
|
|
|
57
57
|
variant = "default",
|
|
58
58
|
validationStatusOverride,
|
|
59
59
|
headerWidth,
|
|
60
|
+
showValidationsSummary,
|
|
60
61
|
...rest
|
|
61
62
|
}) => {
|
|
62
63
|
/** The children nodes converted into an Array */
|
|
@@ -78,24 +79,24 @@ const Tabs = ({
|
|
|
78
79
|
const [tabsErrors, setTabsErrors] = (0, _react.useState)({});
|
|
79
80
|
const [tabsWarnings, setTabsWarnings] = (0, _react.useState)({});
|
|
80
81
|
const [tabsInfos, setTabsInfos] = (0, _react.useState)({});
|
|
81
|
-
const updateErrors = (0, _react.useCallback)((id,
|
|
82
|
-
if (tabsErrors[id] !==
|
|
82
|
+
const updateErrors = (0, _react.useCallback)((id, error) => {
|
|
83
|
+
if (tabsErrors[id] !== error) {
|
|
83
84
|
setTabsErrors({ ...tabsErrors,
|
|
84
|
-
[id]:
|
|
85
|
+
[id]: error
|
|
85
86
|
});
|
|
86
87
|
}
|
|
87
88
|
}, [tabsErrors]);
|
|
88
|
-
const updateWarnings = (0, _react.useCallback)((id,
|
|
89
|
-
if (tabsWarnings[id] !==
|
|
89
|
+
const updateWarnings = (0, _react.useCallback)((id, warning) => {
|
|
90
|
+
if (tabsWarnings[id] !== warning) {
|
|
90
91
|
setTabsWarnings({ ...tabsWarnings,
|
|
91
|
-
[id]:
|
|
92
|
+
[id]: warning
|
|
92
93
|
});
|
|
93
94
|
}
|
|
94
95
|
}, [tabsWarnings]);
|
|
95
|
-
const updateInfos = (0, _react.useCallback)((id,
|
|
96
|
-
if (tabsInfos[id] !==
|
|
96
|
+
const updateInfos = (0, _react.useCallback)((id, info) => {
|
|
97
|
+
if (tabsInfos[id] !== info) {
|
|
97
98
|
setTabsInfos({ ...tabsInfos,
|
|
98
|
-
[id]:
|
|
99
|
+
[id]: info
|
|
99
100
|
});
|
|
100
101
|
}
|
|
101
102
|
}, [tabsInfos]);
|
|
@@ -216,16 +217,33 @@ const Tabs = ({
|
|
|
216
217
|
customLayout
|
|
217
218
|
} = child.props;
|
|
218
219
|
const refId = `${tabId}-tab`;
|
|
219
|
-
const errors = tabsErrors[tabId]
|
|
220
|
-
const warnings = tabsWarnings[tabId]
|
|
221
|
-
const infos = tabsInfos[tabId]
|
|
220
|
+
const errors = tabsErrors[tabId];
|
|
221
|
+
const warnings = tabsWarnings[tabId];
|
|
222
|
+
const infos = tabsInfos[tabId];
|
|
223
|
+
const errorsCount = errors && Object.entries(errors).filter(tab => tab[1]).length;
|
|
224
|
+
const warningsCount = warnings && Object.entries(warnings).filter(tab => tab[1]).length;
|
|
225
|
+
const infosCount = infos && Object.entries(infos).filter(tab => tab[1]).length;
|
|
222
226
|
const hasOverride = validationStatusOverride && validationStatusOverride[tabId];
|
|
223
227
|
const errorOverride = hasOverride && validationStatusOverride[tabId].error;
|
|
224
228
|
const warningOverride = hasOverride && validationStatusOverride[tabId].warning;
|
|
225
229
|
const infoOverride = hasOverride && validationStatusOverride[tabId].info;
|
|
226
|
-
const tabHasError = errorOverride !== undefined ? errorOverride :
|
|
227
|
-
const tabHasWarning = warningOverride !== undefined ? warningOverride :
|
|
228
|
-
const tabHasInfo = infoOverride !== undefined ? infoOverride :
|
|
230
|
+
const tabHasError = errorOverride !== undefined ? errorOverride : !!errorsCount;
|
|
231
|
+
const tabHasWarning = warningOverride !== undefined ? warningOverride : !!warningsCount && !tabHasError;
|
|
232
|
+
const tabHasInfo = infoOverride !== undefined ? infoOverride : !!infosCount && !tabHasError && !tabHasWarning;
|
|
233
|
+
|
|
234
|
+
const getValidationMessage = (message, validations = {}) => {
|
|
235
|
+
const summaryOfMessages = Object.values(validations).filter(value => value && typeof value === "string");
|
|
236
|
+
|
|
237
|
+
if (!showValidationsSummary || !summaryOfMessages.length) {
|
|
238
|
+
return message;
|
|
239
|
+
}
|
|
240
|
+
|
|
241
|
+
if (summaryOfMessages.length === 1) {
|
|
242
|
+
return summaryOfMessages[0];
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
return summaryOfMessages.map(value => `• ${value}`).join("\n");
|
|
246
|
+
};
|
|
229
247
|
|
|
230
248
|
const tabTitle = /*#__PURE__*/_react.default.createElement(_tabTitle.default, {
|
|
231
249
|
position: isInSidebar ? "left" : position,
|
|
@@ -247,9 +265,9 @@ const Tabs = ({
|
|
|
247
265
|
borders: borders !== "off",
|
|
248
266
|
siblings: siblings,
|
|
249
267
|
titlePosition: titlePosition,
|
|
250
|
-
errorMessage: errorMessage,
|
|
251
|
-
warningMessage: warningMessage,
|
|
252
|
-
infoMessage: infoMessage,
|
|
268
|
+
errorMessage: getValidationMessage(errorMessage, errors),
|
|
269
|
+
warningMessage: getValidationMessage(warningMessage, warnings),
|
|
270
|
+
infoMessage: getValidationMessage(infoMessage, infos),
|
|
253
271
|
alternateStyling: variant === "alternate",
|
|
254
272
|
noLeftBorder: ["no left side", "no sides"].includes(borders),
|
|
255
273
|
noRightBorder: ["no right side", "no sides"].includes(borders),
|
|
@@ -378,5 +396,10 @@ Tabs.propTypes = { ...marginPropTypes,
|
|
|
378
396
|
warning: _propTypes.default.bool,
|
|
379
397
|
info: _propTypes.default.bool
|
|
380
398
|
})
|
|
381
|
-
})
|
|
399
|
+
}),
|
|
400
|
+
|
|
401
|
+
/** When this prop is set any string validation failures in the children of each Tab
|
|
402
|
+
* will be summaraised in the Tooltip next to the Tab title
|
|
403
|
+
*/
|
|
404
|
+
showValidationsSummary: _propTypes.default.bool
|
|
382
405
|
};
|
|
@@ -40,6 +40,10 @@ export interface TabsProps extends MarginProps {
|
|
|
40
40
|
info?: boolean;
|
|
41
41
|
};
|
|
42
42
|
};
|
|
43
|
+
/** When this prop is set any string validation failures in the children of each Tab
|
|
44
|
+
* will be summaraised in the Tooltip next to the Tab title
|
|
45
|
+
*/
|
|
46
|
+
showValidationsSummary?: boolean;
|
|
43
47
|
}
|
|
44
48
|
|
|
45
49
|
declare function Tabs(props: TabsProps): JSX.Element;
|