@madie/madie-design-system 1.2.56 → 1.2.58
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 +345 -140
- package/components/RichTextEditor/index.jsx +3 -3
- 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 +2 -2
- package/dist/react/index.js.map +1 -1
- package/package.json +1 -1
- package/styles/components/_madie-alert.scss +5 -1
- package/styles/components/_rich-text-editor.scss +160 -158
- package/styles/qppds/components/_rich-text-editor.scss +160 -159
- package/test/components/MadieAlert.test.js +321 -20
|
@@ -165,7 +165,11 @@ const AutoComplete = ({
|
|
|
165
165
|
disabled={disabled}
|
|
166
166
|
multiple={multiple}
|
|
167
167
|
disableCloseOnSelect={multiple}
|
|
168
|
-
disableClearable={
|
|
168
|
+
disableClearable={
|
|
169
|
+
!rest.value?.length ||
|
|
170
|
+
rest.value?.[0] === "" ||
|
|
171
|
+
rest.value?.[0] === "-"
|
|
172
|
+
}
|
|
169
173
|
sx={
|
|
170
174
|
multiple
|
|
171
175
|
? {
|
|
@@ -1,11 +1,12 @@
|
|
|
1
|
-
import React, { useEffect, useState } from "react";
|
|
1
|
+
import React, { useEffect, useState, useMemo } from "react";
|
|
2
2
|
|
|
3
3
|
import ErrorIcon from "@mui/icons-material/Error"; // warning
|
|
4
4
|
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
|
|
8
|
+
import FullscreenExitRoundedIcon from "@mui/icons-material/FullscreenExitRounded";
|
|
9
|
+
import WarningRoundedIcon from "@mui/icons-material/WarningRounded";
|
|
9
10
|
import Tooltip from "@mui/material/Tooltip";
|
|
10
11
|
import { IconButton } from "@mui/material";
|
|
11
12
|
import ClearIcon from "@mui/icons-material/Clear";
|
|
@@ -13,171 +14,362 @@ import Toast from "../Toast/index";
|
|
|
13
14
|
import classNames from "classnames";
|
|
14
15
|
import PropTypes from "prop-types";
|
|
15
16
|
|
|
16
|
-
//
|
|
17
|
+
// Define icon mapping outside component to avoid recreation on each render
|
|
18
|
+
const typeToIconMap = {
|
|
19
|
+
warning: ErrorIcon,
|
|
20
|
+
info: InfoIcon,
|
|
21
|
+
error: CancelIcon,
|
|
22
|
+
success: CheckCircleIcon,
|
|
23
|
+
};
|
|
24
|
+
|
|
25
|
+
// Common button styles
|
|
26
|
+
const buttonBaseSx = {
|
|
27
|
+
marginLeft: "auto",
|
|
28
|
+
};
|
|
29
|
+
|
|
30
|
+
const buttonWithDividerSx = {
|
|
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
|
+
};
|
|
42
|
+
|
|
43
|
+
// Extract alert content processing to a separate function
|
|
44
|
+
const processContent = (content) => {
|
|
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;
|
|
73
|
+
};
|
|
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();
|
|
122
|
+
}
|
|
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
|
+
};
|
|
136
|
+
};
|
|
137
|
+
|
|
138
|
+
// Define ActionButton as a separate component outside MadieAlert
|
|
139
|
+
const ActionButton = ({ tooltip, onClick, icon, testId, sx }) => (
|
|
140
|
+
<Tooltip title={tooltip} data-testid={`${testId}-tooltip`} arrow>
|
|
141
|
+
<IconButton onClick={onClick} sx={sx} data-testid={testId}>
|
|
142
|
+
{icon}
|
|
143
|
+
</IconButton>
|
|
144
|
+
</Tooltip>
|
|
145
|
+
);
|
|
146
|
+
|
|
147
|
+
// Add PropTypes for ActionButton
|
|
148
|
+
ActionButton.propTypes = {
|
|
149
|
+
tooltip: PropTypes.string.isRequired,
|
|
150
|
+
onClick: PropTypes.func.isRequired,
|
|
151
|
+
icon: PropTypes.node.isRequired,
|
|
152
|
+
testId: PropTypes.string.isRequired,
|
|
153
|
+
sx: PropTypes.object,
|
|
154
|
+
};
|
|
155
|
+
|
|
17
156
|
const MadieAlert = ({
|
|
18
157
|
type = "warning",
|
|
19
158
|
visible = true,
|
|
20
159
|
content,
|
|
21
160
|
canClose = true,
|
|
22
|
-
minimizeAlerts = false,
|
|
23
|
-
alertProps,
|
|
24
|
-
closeButtonProps,
|
|
161
|
+
minimizeAlerts = false,
|
|
162
|
+
alertProps,
|
|
163
|
+
closeButtonProps,
|
|
25
164
|
copyButton,
|
|
165
|
+
alerts = null,
|
|
26
166
|
}) => {
|
|
27
|
-
|
|
28
|
-
const [
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
let result = contentNode.type === "ul" ? "\n" : "";
|
|
35
|
-
if (Array.isArray(contentNode.props?.children)) {
|
|
36
|
-
contentNode.props.children.forEach((child, index) => {
|
|
37
|
-
result += traversal(child, false);
|
|
38
|
-
if (
|
|
39
|
-
(parentNode && index == 1) ||
|
|
40
|
-
contentNode.type === "ul"
|
|
41
|
-
) {
|
|
42
|
-
result += "\n";
|
|
43
|
-
}
|
|
44
|
-
});
|
|
45
|
-
} else if (typeof contentNode.props?.children === "object") {
|
|
46
|
-
result += traversal(contentNode.props.children, false);
|
|
47
|
-
} else if (
|
|
48
|
-
typeof contentNode.props?.children === "string" ||
|
|
49
|
-
typeof contentNode.props?.children === "number"
|
|
50
|
-
) {
|
|
51
|
-
result += contentNode.props.children.toString();
|
|
52
|
-
} else if (
|
|
53
|
-
typeof contentNode === "string" ||
|
|
54
|
-
typeof contentNode === "number"
|
|
55
|
-
) {
|
|
56
|
-
result += contentNode.toString();
|
|
57
|
-
}
|
|
58
|
-
return result;
|
|
59
|
-
};
|
|
60
|
-
return traversal(content, false).trim();
|
|
61
|
-
};
|
|
167
|
+
// Consolidate related state
|
|
168
|
+
const [state, setState] = useState({
|
|
169
|
+
toastOpen: false,
|
|
170
|
+
copyText: "",
|
|
171
|
+
minimizedAlerts: {},
|
|
172
|
+
individualErrors: {},
|
|
173
|
+
});
|
|
62
174
|
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
const typeSelect = {
|
|
70
|
-
warning: ErrorIcon,
|
|
71
|
-
info: InfoIcon,
|
|
72
|
-
error: CancelIcon,
|
|
73
|
-
success: CheckCircleIcon,
|
|
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 }));
|
|
74
181
|
};
|
|
75
|
-
const Icon = typeSelect[type];
|
|
76
|
-
const alertClass = classNames("madie-alert", type);
|
|
77
|
-
const iconClass = classNames("alert-icon", type);
|
|
78
182
|
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
toastKey="copy-success-toast"
|
|
84
|
-
data-testid="copy-success"
|
|
85
|
-
toastType="success"
|
|
86
|
-
open={toastOpen}
|
|
87
|
-
message="Copied to clipboard!"
|
|
88
|
-
onClose={() => {
|
|
89
|
-
setToastOpen(false);
|
|
90
|
-
}}
|
|
91
|
-
autoHideDuration={1500}
|
|
92
|
-
/>
|
|
93
|
-
<Icon className={iconClass} />
|
|
94
|
-
<div id="content">{content && content}</div>
|
|
183
|
+
// Prepare alerts array once
|
|
184
|
+
const alertsArray = useMemo(() => {
|
|
185
|
+
return (
|
|
186
|
+
alerts || [
|
|
95
187
|
{
|
|
96
|
-
|
|
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";
|
|
97
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
|
|
250
|
+
);
|
|
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
|
+
|
|
98
276
|
{minimizeAlerts && (
|
|
99
|
-
<
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
height: "40px",
|
|
108
|
-
backgroundColor: "#B0B0B0",
|
|
109
|
-
pointerEvents: "none",
|
|
110
|
-
},
|
|
111
|
-
}}
|
|
112
|
-
>
|
|
113
|
-
<FullscreenExitRoundedIcon
|
|
114
|
-
onClick={(e) => {
|
|
115
|
-
e.preventDefault();
|
|
116
|
-
setMinimized(true);
|
|
117
|
-
}}
|
|
277
|
+
<ActionButton
|
|
278
|
+
tooltip="Minimize"
|
|
279
|
+
onClick={(e) => {
|
|
280
|
+
e.preventDefault();
|
|
281
|
+
minimizeAlert(index);
|
|
282
|
+
}}
|
|
283
|
+
icon={
|
|
284
|
+
<FullscreenExitRoundedIcon
|
|
118
285
|
sx={{ color: "#242424" }}
|
|
119
286
|
/>
|
|
120
|
-
|
|
121
|
-
|
|
287
|
+
}
|
|
288
|
+
testId={`minimize-button-${index}`}
|
|
289
|
+
sx={buttonWithDividerSx}
|
|
290
|
+
/>
|
|
122
291
|
)}
|
|
292
|
+
|
|
123
293
|
{copyButton && (
|
|
124
|
-
<
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
}
|
|
142
|
-
})
|
|
143
|
-
}}
|
|
144
|
-
>
|
|
145
|
-
<ContentCopyIcon
|
|
146
|
-
onClick={(e) => {
|
|
147
|
-
e.preventDefault();
|
|
148
|
-
navigator.clipboard.writeText(copyText);
|
|
149
|
-
setToastOpen(true);
|
|
150
|
-
}}
|
|
151
|
-
sx={{ color: "#242424" }}
|
|
152
|
-
/>
|
|
153
|
-
</IconButton>
|
|
154
|
-
</Tooltip>
|
|
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
|
+
/>
|
|
155
311
|
)}
|
|
156
312
|
|
|
157
313
|
{canClose && (
|
|
158
|
-
<IconButton
|
|
159
|
-
sx={{
|
|
160
|
-
marginLeft: "auto",
|
|
161
|
-
"&:after": {
|
|
162
|
-
content: `''`,
|
|
163
|
-
position: "absolute",
|
|
164
|
-
left: "0px",
|
|
165
|
-
width: "1px",
|
|
166
|
-
height: "40px",
|
|
167
|
-
backgroundColor: "#B0B0B0",
|
|
168
|
-
pointerEvents: "none",
|
|
169
|
-
},
|
|
170
|
-
}}
|
|
171
|
-
{...closeButtonProps}
|
|
172
|
-
>
|
|
314
|
+
<IconButton sx={buttonWithDividerSx} {...closeButtonProps}>
|
|
173
315
|
<ClearIcon sx={{ color: "#242424" }} />
|
|
174
316
|
</IconButton>
|
|
175
317
|
)}
|
|
176
318
|
</div>
|
|
177
|
-
)
|
|
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
|
+
)}
|
|
368
|
+
</div>
|
|
178
369
|
);
|
|
179
370
|
};
|
|
180
371
|
|
|
372
|
+
// PropTypes definition
|
|
181
373
|
MadieAlert.propTypes = {
|
|
182
374
|
type: PropTypes.string,
|
|
183
375
|
visible: PropTypes.bool,
|
|
@@ -187,10 +379,23 @@ MadieAlert.propTypes = {
|
|
|
187
379
|
closeButtonProps: PropTypes.object,
|
|
188
380
|
copyButton: PropTypes.bool,
|
|
189
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
|
+
),
|
|
190
393
|
};
|
|
394
|
+
|
|
191
395
|
MadieAlert.defaultProps = {
|
|
192
396
|
copyButton: false,
|
|
193
397
|
minimizeAlerts: false,
|
|
398
|
+
alerts: null,
|
|
194
399
|
};
|
|
195
400
|
|
|
196
401
|
export default MadieAlert;
|
|
@@ -179,6 +179,7 @@ const RichTextEditor = ({
|
|
|
179
179
|
{
|
|
180
180
|
extensions: [
|
|
181
181
|
StarterKit,
|
|
182
|
+
Markdown,
|
|
182
183
|
Gapcursor,
|
|
183
184
|
Table.configure({
|
|
184
185
|
resizable: true,
|
|
@@ -187,7 +188,6 @@ const RichTextEditor = ({
|
|
|
187
188
|
TableHeader,
|
|
188
189
|
TableCell,
|
|
189
190
|
Underline,
|
|
190
|
-
Markdown,
|
|
191
191
|
],
|
|
192
192
|
shouldRerenderOnTransaction: false,
|
|
193
193
|
content,
|
|
@@ -200,7 +200,7 @@ const RichTextEditor = ({
|
|
|
200
200
|
[content]
|
|
201
201
|
);
|
|
202
202
|
return (
|
|
203
|
-
|
|
203
|
+
<div className="rich-text-editor">
|
|
204
204
|
<InputLabel
|
|
205
205
|
shrink
|
|
206
206
|
required={required}
|
|
@@ -243,7 +243,7 @@ const RichTextEditor = ({
|
|
|
243
243
|
</InputLabel>
|
|
244
244
|
<MenuBar editor={editor} />
|
|
245
245
|
<EditorContent editor={editor} />
|
|
246
|
-
|
|
246
|
+
</div>
|
|
247
247
|
);
|
|
248
248
|
};
|
|
249
249
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import React, { useState } from "react";
|
|
2
2
|
import { withKnobs } from "@storybook/addon-knobs";
|
|
3
|
-
|
|
3
|
+
import "./tabs.scss";
|
|
4
4
|
import Tabs from "./index";
|
|
5
5
|
import Tab from "./Tab";
|
|
6
6
|
|
|
@@ -147,44 +147,46 @@ export const TypeA = () => {
|
|
|
147
147
|
/>
|
|
148
148
|
</Tabs>
|
|
149
149
|
</div>
|
|
150
|
-
<div>
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
value={selected}
|
|
155
|
-
onChange={handleChange}
|
|
156
|
-
orientation="vertical"
|
|
157
|
-
>
|
|
158
|
-
<Tab
|
|
150
|
+
<div className={"vertical-standard-type-c-wrapper"}>
|
|
151
|
+
<div className={"vertical-standard-type-c"}>
|
|
152
|
+
<h4>Vertical Standard: C</h4>
|
|
153
|
+
<Tabs
|
|
159
154
|
type="C"
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
value={1}
|
|
155
|
+
value={selected}
|
|
156
|
+
onChange={handleChange}
|
|
163
157
|
orientation="vertical"
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
158
|
+
>
|
|
159
|
+
<Tab
|
|
160
|
+
type="C"
|
|
161
|
+
size="standard"
|
|
162
|
+
label="Item One"
|
|
163
|
+
value={1}
|
|
164
|
+
orientation="vertical"
|
|
165
|
+
/>
|
|
166
|
+
<Tab
|
|
167
|
+
type="C"
|
|
168
|
+
size="standard"
|
|
169
|
+
label="Item Two"
|
|
170
|
+
value={2}
|
|
171
|
+
orientation="vertical"
|
|
172
|
+
/>
|
|
173
|
+
<Tab
|
|
174
|
+
type="C"
|
|
175
|
+
size="standard"
|
|
176
|
+
label="Item Three"
|
|
177
|
+
value={3}
|
|
178
|
+
orientation="vertical"
|
|
179
|
+
/>
|
|
180
|
+
<Tab
|
|
181
|
+
type="C"
|
|
182
|
+
size="standard"
|
|
183
|
+
label="disabled"
|
|
184
|
+
value={4}
|
|
185
|
+
disabled
|
|
186
|
+
orientation="vertical"
|
|
187
|
+
/>
|
|
188
|
+
</Tabs>
|
|
189
|
+
</div>
|
|
188
190
|
</div>
|
|
189
191
|
<div style={{ width: "fit-content" }}>
|
|
190
192
|
Standard: D
|