@madie/madie-design-system 1.2.57 → 1.2.59
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/components/AutoComplete/AutoComplete.jsx +5 -1
- package/components/MadieAlert/index.jsx +347 -297
- package/components/RichTextEditor/RichTextEditor.stories.js +21 -1
- package/components/RichTextEditor/index.jsx +26 -9
- package/components/Select/index.jsx +0 -9
- package/components/Tabs/Tabs.stories.js +39 -37
- package/components/Tabs/index.js +51 -30
- package/components/Tabs/tabs.scss +13 -0
- package/components/TextArea/index.jsx +2 -2
- package/components/TextField/index.jsx +1 -1
- package/dist/browser.js +1 -1
- package/dist/index.js +1 -1
- package/dist/react/index.js +3 -3
- package/dist/react/index.js.LICENSE.txt +2 -0
- package/dist/react/index.js.map +1 -1
- package/package.json +2 -2
- package/styles/components/_madie-alert.scss +3 -2
- package/styles/qppds/components/_rich-text-editor.scss +1 -1
- package/test/components/MadieAlert.test.js +37 -25
- package/test/components/RichTextEditor.test.js +62 -0
|
@@ -5,8 +5,8 @@ import InfoIcon from "@mui/icons-material/Info"; // info
|
|
|
5
5
|
import CancelIcon from "@mui/icons-material/Cancel"; // error
|
|
6
6
|
import CheckCircleIcon from "@mui/icons-material/CheckCircle"; //success
|
|
7
7
|
import ContentCopyIcon from "@mui/icons-material/ContentCopy"; //copy
|
|
8
|
-
import FullscreenExitRoundedIcon from
|
|
9
|
-
import WarningRoundedIcon from
|
|
8
|
+
import FullscreenExitRoundedIcon from "@mui/icons-material/FullscreenExitRounded";
|
|
9
|
+
import WarningRoundedIcon from "@mui/icons-material/WarningRounded";
|
|
10
10
|
import Tooltip from "@mui/material/Tooltip";
|
|
11
11
|
import { IconButton } from "@mui/material";
|
|
12
12
|
import ClearIcon from "@mui/icons-material/Clear";
|
|
@@ -16,336 +16,386 @@ import PropTypes from "prop-types";
|
|
|
16
16
|
|
|
17
17
|
// Define icon mapping outside component to avoid recreation on each render
|
|
18
18
|
const typeToIconMap = {
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
19
|
+
warning: ErrorIcon,
|
|
20
|
+
info: InfoIcon,
|
|
21
|
+
error: CancelIcon,
|
|
22
|
+
success: CheckCircleIcon,
|
|
23
23
|
};
|
|
24
24
|
|
|
25
25
|
// Common button styles
|
|
26
26
|
const buttonBaseSx = {
|
|
27
|
-
|
|
27
|
+
marginLeft: "auto",
|
|
28
28
|
};
|
|
29
29
|
|
|
30
30
|
const buttonWithDividerSx = {
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
31
|
+
...buttonBaseSx,
|
|
32
|
+
"&:after": {
|
|
33
|
+
content: `''`,
|
|
34
|
+
position: "absolute",
|
|
35
|
+
left: "0px",
|
|
36
|
+
width: "1px",
|
|
37
|
+
height: "40px",
|
|
38
|
+
backgroundColor: "#B0B0B0",
|
|
39
|
+
pointerEvents: "none",
|
|
40
|
+
},
|
|
41
41
|
};
|
|
42
42
|
|
|
43
43
|
// Extract alert content processing to a separate function
|
|
44
44
|
const processContent = (content) => {
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
45
|
+
// Counts errors/warnings in ul/li elements
|
|
46
|
+
const countUlLiChildren = (element) => {
|
|
47
|
+
const counts = { ul: 0, li: 0 };
|
|
48
|
+
|
|
49
|
+
const traverse = (el) => {
|
|
50
|
+
if (!el || typeof el !== "object") return;
|
|
51
|
+
|
|
52
|
+
if (el.type === "ul" || el.type === "li") {
|
|
53
|
+
const children = el.props?.children;
|
|
54
|
+
const childCount = Array.isArray(children)
|
|
55
|
+
? children.length
|
|
56
|
+
: children
|
|
57
|
+
? 1
|
|
58
|
+
: 0;
|
|
59
|
+
counts[el.type] += childCount;
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
const children = el.props?.children;
|
|
63
|
+
if (Array.isArray(children)) {
|
|
64
|
+
children.forEach(traverse);
|
|
65
|
+
} else if (children && typeof children === "object") {
|
|
66
|
+
traverse(children);
|
|
67
|
+
}
|
|
68
|
+
};
|
|
69
|
+
|
|
70
|
+
traverse(element);
|
|
71
|
+
|
|
72
|
+
return counts.li > counts.ul ? counts.li : counts.ul;
|
|
64
73
|
};
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
74
|
+
|
|
75
|
+
// Converts content to text for copying - improved to avoid unwanted characters
|
|
76
|
+
const buildCopyText = (contentNode, parentNode = true) => {
|
|
77
|
+
if (!contentNode) return "";
|
|
78
|
+
|
|
79
|
+
// Initialize result string
|
|
80
|
+
let result = "";
|
|
81
|
+
|
|
82
|
+
// Handle specific node types that need special formatting
|
|
83
|
+
if (contentNode.type === "ul") {
|
|
84
|
+
// Start ul with a newline
|
|
85
|
+
result = "\n";
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
// Process children based on their type
|
|
89
|
+
if (Array.isArray(contentNode.props?.children)) {
|
|
90
|
+
contentNode.props.children.forEach((child, index) => {
|
|
91
|
+
const childText = buildCopyText(child, false);
|
|
92
|
+
// Only add non-empty text
|
|
93
|
+
if (childText.trim()) {
|
|
94
|
+
result += childText;
|
|
95
|
+
|
|
96
|
+
// Add line breaks after certain elements
|
|
97
|
+
if (
|
|
98
|
+
(parentNode && index === 1) ||
|
|
99
|
+
contentNode.type === "ul"
|
|
100
|
+
) {
|
|
101
|
+
result += "\n";
|
|
102
|
+
}
|
|
103
|
+
}
|
|
104
|
+
});
|
|
105
|
+
} else if (typeof contentNode.props?.children === "object") {
|
|
106
|
+
result += buildCopyText(contentNode.props.children, false);
|
|
107
|
+
} else if (
|
|
108
|
+
typeof contentNode.props?.children === "string" ||
|
|
109
|
+
typeof contentNode.props?.children === "number"
|
|
110
|
+
) {
|
|
111
|
+
// Clean the string by trimming and normalizing whitespace
|
|
112
|
+
result += contentNode.props.children
|
|
113
|
+
.toString()
|
|
114
|
+
.replace(/\s+/g, " ")
|
|
115
|
+
.trim();
|
|
116
|
+
} else if (
|
|
117
|
+
typeof contentNode === "string" ||
|
|
118
|
+
typeof contentNode === "number"
|
|
119
|
+
) {
|
|
120
|
+
// Clean the string by trimming and normalizing whitespace
|
|
121
|
+
result += contentNode.toString().replace(/\s+/g, " ").trim();
|
|
96
122
|
}
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
};
|
|
111
|
-
|
|
112
|
-
// Process content and ensure we trim the final result
|
|
113
|
-
const rawText = buildCopyText(content, false);
|
|
114
|
-
return {
|
|
115
|
-
errorCount: countUlLiChildren(content),
|
|
116
|
-
copyText: rawText.replace(/\s+\n/g, '\n').replace(/\n\s+/g, '\n').trim()
|
|
117
|
-
};
|
|
123
|
+
|
|
124
|
+
return result;
|
|
125
|
+
};
|
|
126
|
+
|
|
127
|
+
// Process content and ensure we trim the final result
|
|
128
|
+
const rawText = buildCopyText(content, false);
|
|
129
|
+
return {
|
|
130
|
+
errorCount: countUlLiChildren(content),
|
|
131
|
+
copyText: rawText
|
|
132
|
+
.replace(/\s+\n/g, "\n")
|
|
133
|
+
.replace(/\n\s+/g, "\n")
|
|
134
|
+
.trim(),
|
|
135
|
+
};
|
|
118
136
|
};
|
|
119
137
|
|
|
120
138
|
// Define ActionButton as a separate component outside MadieAlert
|
|
121
139
|
const ActionButton = ({ tooltip, onClick, icon, testId, sx }) => (
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
>
|
|
128
|
-
{icon}
|
|
129
|
-
</IconButton>
|
|
130
|
-
</Tooltip>
|
|
140
|
+
<Tooltip title={tooltip} data-testid={`${testId}-tooltip`} arrow>
|
|
141
|
+
<IconButton onClick={onClick} sx={sx} data-testid={testId}>
|
|
142
|
+
{icon}
|
|
143
|
+
</IconButton>
|
|
144
|
+
</Tooltip>
|
|
131
145
|
);
|
|
132
146
|
|
|
133
147
|
// Add PropTypes for ActionButton
|
|
134
148
|
ActionButton.propTypes = {
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
149
|
+
tooltip: PropTypes.string.isRequired,
|
|
150
|
+
onClick: PropTypes.func.isRequired,
|
|
151
|
+
icon: PropTypes.node.isRequired,
|
|
152
|
+
testId: PropTypes.string.isRequired,
|
|
153
|
+
sx: PropTypes.object,
|
|
140
154
|
};
|
|
141
155
|
|
|
142
156
|
const MadieAlert = ({
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
157
|
+
type = "warning",
|
|
158
|
+
visible = true,
|
|
159
|
+
content,
|
|
160
|
+
canClose = true,
|
|
161
|
+
minimizeAlerts = false,
|
|
162
|
+
alertProps,
|
|
163
|
+
closeButtonProps,
|
|
164
|
+
copyButton,
|
|
165
|
+
alerts = null,
|
|
152
166
|
}) => {
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
});
|
|
160
|
-
|
|
161
|
-
// Create alias for readability
|
|
162
|
-
const { toastOpen, copyText, minimizedAlerts, individualErrors } = state;
|
|
163
|
-
|
|
164
|
-
// Use a single update function
|
|
165
|
-
const updateState = (updates) => {
|
|
166
|
-
setState(prev => ({ ...prev, ...updates }));
|
|
167
|
-
};
|
|
168
|
-
|
|
169
|
-
// Prepare alerts array once
|
|
170
|
-
const alertsArray = useMemo(() => {
|
|
171
|
-
return alerts || [{
|
|
172
|
-
type, visible, content, canClose, alertProps, closeButtonProps, copyButton
|
|
173
|
-
}];
|
|
174
|
-
}, [alerts, type, visible, content, canClose, alertProps, closeButtonProps, copyButton]);
|
|
175
|
-
|
|
176
|
-
// Process all alerts content once
|
|
177
|
-
useEffect(() => {
|
|
178
|
-
const newIndividualErrors = {};
|
|
179
|
-
let totalCopyText = "";
|
|
180
|
-
|
|
181
|
-
alertsArray.forEach((alert, index) => {
|
|
182
|
-
if (alert.content && alert.visible !== false) {
|
|
183
|
-
const processed = processContent(alert.content);
|
|
184
|
-
newIndividualErrors[index] = processed.errorCount;
|
|
185
|
-
|
|
186
|
-
if (alert.copyButton) {
|
|
187
|
-
totalCopyText += processed.copyText + "\n\n";
|
|
188
|
-
}
|
|
189
|
-
}
|
|
190
|
-
});
|
|
191
|
-
|
|
192
|
-
updateState({
|
|
193
|
-
individualErrors: newIndividualErrors,
|
|
194
|
-
copyText: totalCopyText.trim(),
|
|
195
|
-
});
|
|
196
|
-
}, [alertsArray]);
|
|
197
|
-
|
|
198
|
-
// Utility functions for managing minimized state
|
|
199
|
-
const minimizeAlert = (index) => {
|
|
200
|
-
updateState({
|
|
201
|
-
minimizedAlerts: { ...minimizedAlerts, [index]: true }
|
|
167
|
+
// Consolidate related state
|
|
168
|
+
const [state, setState] = useState({
|
|
169
|
+
toastOpen: false,
|
|
170
|
+
copyText: "",
|
|
171
|
+
minimizedAlerts: {},
|
|
172
|
+
individualErrors: {},
|
|
202
173
|
});
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
229
|
-
|
|
230
|
-
|
|
231
|
-
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
|
|
235
|
-
|
|
236
|
-
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
|
|
240
|
-
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
|
|
246
|
-
|
|
247
|
-
|
|
248
|
-
|
|
249
|
-
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
)
|
|
253
|
-
|
|
254
|
-
{
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
{
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
276
|
-
|
|
174
|
+
|
|
175
|
+
// Create alias for readability
|
|
176
|
+
const { toastOpen, copyText, minimizedAlerts, individualErrors } = state;
|
|
177
|
+
|
|
178
|
+
// Use a single update function
|
|
179
|
+
const updateState = (updates) => {
|
|
180
|
+
setState((prev) => ({ ...prev, ...updates }));
|
|
181
|
+
};
|
|
182
|
+
|
|
183
|
+
// Prepare alerts array once
|
|
184
|
+
const alertsArray = useMemo(() => {
|
|
185
|
+
return (
|
|
186
|
+
alerts || [
|
|
187
|
+
{
|
|
188
|
+
type,
|
|
189
|
+
visible,
|
|
190
|
+
content,
|
|
191
|
+
canClose,
|
|
192
|
+
alertProps,
|
|
193
|
+
closeButtonProps,
|
|
194
|
+
copyButton,
|
|
195
|
+
},
|
|
196
|
+
]
|
|
197
|
+
);
|
|
198
|
+
}, [
|
|
199
|
+
alerts,
|
|
200
|
+
type,
|
|
201
|
+
visible,
|
|
202
|
+
content,
|
|
203
|
+
canClose,
|
|
204
|
+
alertProps,
|
|
205
|
+
closeButtonProps,
|
|
206
|
+
copyButton,
|
|
207
|
+
]);
|
|
208
|
+
|
|
209
|
+
// Process all alerts content once
|
|
210
|
+
useEffect(() => {
|
|
211
|
+
const newIndividualErrors = {};
|
|
212
|
+
let totalCopyText = "";
|
|
213
|
+
|
|
214
|
+
alertsArray.forEach((alert, index) => {
|
|
215
|
+
if (alert.content && alert.visible !== false) {
|
|
216
|
+
const processed = processContent(alert.content);
|
|
217
|
+
newIndividualErrors[index] = processed.errorCount;
|
|
218
|
+
|
|
219
|
+
if (alert.copyButton) {
|
|
220
|
+
totalCopyText += processed.copyText + "\n\n";
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
});
|
|
224
|
+
|
|
225
|
+
updateState({
|
|
226
|
+
individualErrors: newIndividualErrors,
|
|
227
|
+
copyText: totalCopyText.trim(),
|
|
228
|
+
});
|
|
229
|
+
}, [alertsArray]);
|
|
230
|
+
|
|
231
|
+
// Utility functions for managing minimized state
|
|
232
|
+
const minimizeAlert = (index) => {
|
|
233
|
+
updateState({
|
|
234
|
+
minimizedAlerts: { ...minimizedAlerts, [index]: true },
|
|
235
|
+
});
|
|
236
|
+
};
|
|
237
|
+
|
|
238
|
+
const restoreAllAlerts = () => {
|
|
239
|
+
updateState({ minimizedAlerts: {} });
|
|
240
|
+
};
|
|
241
|
+
|
|
242
|
+
// Calculate minimized alerts info
|
|
243
|
+
const minimizedIndices = Object.keys(minimizedAlerts)
|
|
244
|
+
.filter((key) => minimizedAlerts[key])
|
|
245
|
+
.map((key) => parseInt(key));
|
|
246
|
+
|
|
247
|
+
const totalMinimizedErrors = minimizedIndices.reduce(
|
|
248
|
+
(sum, index) => sum + (individualErrors[index] || 0),
|
|
249
|
+
0
|
|
277
250
|
);
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
296
|
-
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
|
|
300
|
-
|
|
301
|
-
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
|
|
307
|
-
|
|
308
|
-
|
|
309
|
-
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
251
|
+
|
|
252
|
+
// Render alert content
|
|
253
|
+
const renderAlert = (alert, index) => {
|
|
254
|
+
const {
|
|
255
|
+
type = "warning",
|
|
256
|
+
visible = true,
|
|
257
|
+
content,
|
|
258
|
+
canClose = true,
|
|
259
|
+
alertProps = {},
|
|
260
|
+
closeButtonProps = {},
|
|
261
|
+
copyButton = false,
|
|
262
|
+
} = alert;
|
|
263
|
+
|
|
264
|
+
if (!visible || minimizedAlerts[index]) return null;
|
|
265
|
+
|
|
266
|
+
const Icon = typeToIconMap[type];
|
|
267
|
+
const alertClass = classNames("madie-alert", type);
|
|
268
|
+
|
|
269
|
+
return (
|
|
270
|
+
<div key={index} className={alertClass} {...alertProps}>
|
|
271
|
+
<Icon className={classNames("alert-icon", type)} />
|
|
272
|
+
<div id="content" data-alert-index={index}>
|
|
273
|
+
{content}
|
|
274
|
+
</div>
|
|
275
|
+
|
|
276
|
+
{minimizeAlerts && (
|
|
277
|
+
<ActionButton
|
|
278
|
+
tooltip="Minimize"
|
|
279
|
+
onClick={(e) => {
|
|
280
|
+
e.preventDefault();
|
|
281
|
+
minimizeAlert(index);
|
|
282
|
+
}}
|
|
283
|
+
icon={
|
|
284
|
+
<FullscreenExitRoundedIcon
|
|
285
|
+
sx={{ color: "#242424" }}
|
|
286
|
+
/>
|
|
287
|
+
}
|
|
288
|
+
testId={`minimize-button-${index}`}
|
|
289
|
+
sx={buttonWithDividerSx}
|
|
290
|
+
/>
|
|
291
|
+
)}
|
|
292
|
+
|
|
293
|
+
{copyButton && (
|
|
294
|
+
<ActionButton
|
|
295
|
+
tooltip="Copy"
|
|
296
|
+
onClick={(e) => {
|
|
297
|
+
e.preventDefault();
|
|
298
|
+
navigator.clipboard.writeText(
|
|
299
|
+
copyButton
|
|
300
|
+
? processContent(content).copyText
|
|
301
|
+
: copyText
|
|
302
|
+
);
|
|
303
|
+
updateState({ toastOpen: true });
|
|
304
|
+
}}
|
|
305
|
+
icon={<ContentCopyIcon sx={{ color: "#242424" }} />}
|
|
306
|
+
testId="copy-button"
|
|
307
|
+
sx={
|
|
308
|
+
!minimizeAlerts ? buttonWithDividerSx : buttonBaseSx
|
|
309
|
+
}
|
|
310
|
+
/>
|
|
311
|
+
)}
|
|
312
|
+
|
|
313
|
+
{canClose && (
|
|
314
|
+
<IconButton sx={buttonWithDividerSx} {...closeButtonProps}>
|
|
315
|
+
<ClearIcon sx={{ color: "#242424" }} />
|
|
316
|
+
</IconButton>
|
|
317
|
+
)}
|
|
318
|
+
</div>
|
|
319
|
+
);
|
|
320
|
+
};
|
|
321
|
+
|
|
322
|
+
return (
|
|
323
|
+
<div>
|
|
324
|
+
<Toast
|
|
325
|
+
toastKey="copy-success-toast"
|
|
326
|
+
data-testid="copy-success"
|
|
327
|
+
toastType="success"
|
|
328
|
+
open={toastOpen}
|
|
329
|
+
message="Copied to clipboard!"
|
|
330
|
+
onClose={() => updateState({ toastOpen: false })}
|
|
331
|
+
autoHideDuration={1500}
|
|
332
|
+
/>
|
|
333
|
+
|
|
334
|
+
{/* Render visible alerts */}
|
|
335
|
+
{alertsArray.map((alert, index) => renderAlert(alert, index))}
|
|
336
|
+
|
|
337
|
+
{/* Show minimized indicator if any alerts are minimized */}
|
|
338
|
+
{minimizedIndices.length > 0 && (
|
|
339
|
+
<div
|
|
340
|
+
style={{
|
|
341
|
+
position: "absolute",
|
|
342
|
+
right: "32px",
|
|
343
|
+
top: "10px",
|
|
344
|
+
display: "flex",
|
|
345
|
+
alignItems: "center",
|
|
346
|
+
cursor: "pointer",
|
|
347
|
+
}}
|
|
348
|
+
data-testid="minimized-alert"
|
|
349
|
+
onClick={(e) => {
|
|
350
|
+
e.preventDefault();
|
|
351
|
+
restoreAllAlerts();
|
|
352
|
+
}}
|
|
353
|
+
>
|
|
354
|
+
<WarningRoundedIcon
|
|
355
|
+
sx={{ color: "yellow", marginRight: "5px" }}
|
|
356
|
+
/>
|
|
357
|
+
<span
|
|
358
|
+
data-testid="minimized-alert-text"
|
|
359
|
+
style={{ color: "white", fontSize: "16px" }}
|
|
360
|
+
>
|
|
361
|
+
Display Alerts{" "}
|
|
362
|
+
{totalMinimizedErrors > 0
|
|
363
|
+
? `(${totalMinimizedErrors})`
|
|
364
|
+
: ""}
|
|
365
|
+
</span>
|
|
366
|
+
</div>
|
|
367
|
+
)}
|
|
316
368
|
</div>
|
|
317
|
-
|
|
318
|
-
</div>
|
|
319
|
-
);
|
|
369
|
+
);
|
|
320
370
|
};
|
|
321
371
|
|
|
322
372
|
// PropTypes definition
|
|
323
373
|
MadieAlert.propTypes = {
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
331
|
-
|
|
332
|
-
|
|
333
|
-
|
|
334
|
-
|
|
335
|
-
|
|
336
|
-
|
|
337
|
-
|
|
338
|
-
|
|
339
|
-
|
|
340
|
-
|
|
341
|
-
|
|
342
|
-
|
|
374
|
+
type: PropTypes.string,
|
|
375
|
+
visible: PropTypes.bool,
|
|
376
|
+
content: PropTypes.node,
|
|
377
|
+
canClose: PropTypes.bool,
|
|
378
|
+
alertProps: PropTypes.object,
|
|
379
|
+
closeButtonProps: PropTypes.object,
|
|
380
|
+
copyButton: PropTypes.bool,
|
|
381
|
+
minimizeAlerts: PropTypes.bool,
|
|
382
|
+
alerts: PropTypes.arrayOf(
|
|
383
|
+
PropTypes.shape({
|
|
384
|
+
type: PropTypes.string,
|
|
385
|
+
visible: PropTypes.bool,
|
|
386
|
+
content: PropTypes.node,
|
|
387
|
+
canClose: PropTypes.bool,
|
|
388
|
+
alertProps: PropTypes.object,
|
|
389
|
+
closeButtonProps: PropTypes.object,
|
|
390
|
+
copyButton: PropTypes.bool,
|
|
391
|
+
})
|
|
392
|
+
),
|
|
343
393
|
};
|
|
344
394
|
|
|
345
395
|
MadieAlert.defaultProps = {
|
|
346
|
-
|
|
347
|
-
|
|
348
|
-
|
|
396
|
+
copyButton: false,
|
|
397
|
+
minimizeAlerts: false,
|
|
398
|
+
alerts: null,
|
|
349
399
|
};
|
|
350
400
|
|
|
351
401
|
export default MadieAlert;
|