@nocios/crudify-ui 3.0.58 → 3.0.62
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/dist/index.d.mts +4 -0
- package/dist/index.d.ts +4 -0
- package/dist/index.js +36 -9
- package/dist/index.mjs +36 -9
- package/package.json +3 -1
package/dist/index.d.mts
CHANGED
|
@@ -399,6 +399,7 @@ type NotificationOptions = {
|
|
|
399
399
|
vertical: "top" | "bottom";
|
|
400
400
|
horizontal: "left" | "center" | "right";
|
|
401
401
|
};
|
|
402
|
+
allowHtml?: boolean;
|
|
402
403
|
};
|
|
403
404
|
type SessionProviderProps = {
|
|
404
405
|
children: ReactNode;
|
|
@@ -751,11 +752,13 @@ interface Notification {
|
|
|
751
752
|
severity: NotificationSeverity;
|
|
752
753
|
autoHideDuration?: number;
|
|
753
754
|
persistent?: boolean;
|
|
755
|
+
allowHtml?: boolean;
|
|
754
756
|
}
|
|
755
757
|
interface GlobalNotificationContextValue {
|
|
756
758
|
showNotification: (message: string, severity?: NotificationSeverity, options?: {
|
|
757
759
|
autoHideDuration?: number;
|
|
758
760
|
persistent?: boolean;
|
|
761
|
+
allowHtml?: boolean;
|
|
759
762
|
}) => string;
|
|
760
763
|
hideNotification: (id: string) => void;
|
|
761
764
|
clearAllNotifications: () => void;
|
|
@@ -769,6 +772,7 @@ interface GlobalNotificationProviderProps {
|
|
|
769
772
|
horizontal: "left" | "center" | "right";
|
|
770
773
|
};
|
|
771
774
|
enabled?: boolean;
|
|
775
|
+
allowHtml?: boolean;
|
|
772
776
|
}
|
|
773
777
|
declare const GlobalNotificationProvider: React.FC<GlobalNotificationProviderProps>;
|
|
774
778
|
declare const useGlobalNotification: () => GlobalNotificationContextValue;
|
package/dist/index.d.ts
CHANGED
|
@@ -399,6 +399,7 @@ type NotificationOptions = {
|
|
|
399
399
|
vertical: "top" | "bottom";
|
|
400
400
|
horizontal: "left" | "center" | "right";
|
|
401
401
|
};
|
|
402
|
+
allowHtml?: boolean;
|
|
402
403
|
};
|
|
403
404
|
type SessionProviderProps = {
|
|
404
405
|
children: ReactNode;
|
|
@@ -751,11 +752,13 @@ interface Notification {
|
|
|
751
752
|
severity: NotificationSeverity;
|
|
752
753
|
autoHideDuration?: number;
|
|
753
754
|
persistent?: boolean;
|
|
755
|
+
allowHtml?: boolean;
|
|
754
756
|
}
|
|
755
757
|
interface GlobalNotificationContextValue {
|
|
756
758
|
showNotification: (message: string, severity?: NotificationSeverity, options?: {
|
|
757
759
|
autoHideDuration?: number;
|
|
758
760
|
persistent?: boolean;
|
|
761
|
+
allowHtml?: boolean;
|
|
759
762
|
}) => string;
|
|
760
763
|
hideNotification: (id: string) => void;
|
|
761
764
|
clearAllNotifications: () => void;
|
|
@@ -769,6 +772,7 @@ interface GlobalNotificationProviderProps {
|
|
|
769
772
|
horizontal: "left" | "center" | "right";
|
|
770
773
|
};
|
|
771
774
|
enabled?: boolean;
|
|
775
|
+
allowHtml?: boolean;
|
|
772
776
|
}
|
|
773
777
|
declare const GlobalNotificationProvider: React.FC<GlobalNotificationProviderProps>;
|
|
774
778
|
declare const useGlobalNotification: () => GlobalNotificationContextValue;
|
package/dist/index.js
CHANGED
|
@@ -1401,15 +1401,33 @@ var isTokenExpired = (token) => {
|
|
|
1401
1401
|
var import_react6 = require("react");
|
|
1402
1402
|
var import_material = require("@mui/material");
|
|
1403
1403
|
var import_uuid = require("uuid");
|
|
1404
|
+
var import_dompurify = __toESM(require("dompurify"));
|
|
1404
1405
|
var import_jsx_runtime4 = require("react/jsx-runtime");
|
|
1405
1406
|
var GlobalNotificationContext = (0, import_react6.createContext)(null);
|
|
1407
|
+
var sanitizeNotificationContent = (html) => {
|
|
1408
|
+
return import_dompurify.default.sanitize(html, {
|
|
1409
|
+
// Solo permitir tags seguros para notificaciones
|
|
1410
|
+
ALLOWED_TAGS: ["b", "i", "em", "strong", "br", "span"],
|
|
1411
|
+
ALLOWED_ATTR: ["class"],
|
|
1412
|
+
// Remover scripts y eventos
|
|
1413
|
+
FORBID_TAGS: ["script", "iframe", "object", "embed"],
|
|
1414
|
+
FORBID_ATTR: ["onload", "onerror", "onclick", "onmouseover", "onfocus", "onblur"],
|
|
1415
|
+
// Configuración adicional de seguridad
|
|
1416
|
+
WHOLE_DOCUMENT: false,
|
|
1417
|
+
RETURN_DOM: false,
|
|
1418
|
+
RETURN_DOM_FRAGMENT: false,
|
|
1419
|
+
RETURN_TRUSTED_TYPE: false
|
|
1420
|
+
});
|
|
1421
|
+
};
|
|
1406
1422
|
var GlobalNotificationProvider = ({
|
|
1407
1423
|
children,
|
|
1408
1424
|
maxNotifications = 5,
|
|
1409
1425
|
defaultAutoHideDuration = 6e3,
|
|
1410
1426
|
position = { vertical: "top", horizontal: "right" },
|
|
1411
|
-
enabled = false
|
|
1427
|
+
enabled = false,
|
|
1412
1428
|
// ✅ Por defecto DESACTIVADO
|
|
1429
|
+
allowHtml = false
|
|
1430
|
+
// Por defecto no permitir HTML
|
|
1413
1431
|
}) => {
|
|
1414
1432
|
const [notifications, setNotifications] = (0, import_react6.useState)([]);
|
|
1415
1433
|
const showNotification = (0, import_react6.useCallback)(
|
|
@@ -1417,13 +1435,23 @@ var GlobalNotificationProvider = ({
|
|
|
1417
1435
|
if (!enabled) {
|
|
1418
1436
|
return "";
|
|
1419
1437
|
}
|
|
1438
|
+
if (!message || typeof message !== "string") {
|
|
1439
|
+
console.warn("\u26A0\uFE0F GlobalNotificationProvider: Invalid message provided");
|
|
1440
|
+
return "";
|
|
1441
|
+
}
|
|
1442
|
+
if (message.length > 1e3) {
|
|
1443
|
+
console.warn("\u26A0\uFE0F GlobalNotificationProvider: Message too long, truncating");
|
|
1444
|
+
message = message.substring(0, 1e3) + "...";
|
|
1445
|
+
}
|
|
1420
1446
|
const id = (0, import_uuid.v4)();
|
|
1421
1447
|
const newNotification = {
|
|
1422
1448
|
id,
|
|
1423
1449
|
message,
|
|
1424
1450
|
severity,
|
|
1425
1451
|
autoHideDuration: options?.autoHideDuration ?? defaultAutoHideDuration,
|
|
1426
|
-
persistent: options?.persistent ?? false
|
|
1452
|
+
persistent: options?.persistent ?? false,
|
|
1453
|
+
allowHtml: options?.allowHtml ?? allowHtml
|
|
1454
|
+
// Usar valor del provider por defecto
|
|
1427
1455
|
};
|
|
1428
1456
|
setNotifications((prev) => {
|
|
1429
1457
|
const updatedNotifications = prev.length >= maxNotifications ? prev.slice(-(maxNotifications - 1)) : prev;
|
|
@@ -1431,7 +1459,7 @@ var GlobalNotificationProvider = ({
|
|
|
1431
1459
|
});
|
|
1432
1460
|
return id;
|
|
1433
1461
|
},
|
|
1434
|
-
[maxNotifications, defaultAutoHideDuration, enabled]
|
|
1462
|
+
[maxNotifications, defaultAutoHideDuration, enabled, allowHtml]
|
|
1435
1463
|
);
|
|
1436
1464
|
const hideNotification = (0, import_react6.useCallback)((id) => {
|
|
1437
1465
|
setNotifications((prev) => prev.filter((notification) => notification.id !== id));
|
|
@@ -1513,7 +1541,7 @@ var NotificationItem = ({ notification, onClose }) => {
|
|
|
1513
1541
|
maxWidth: "400px",
|
|
1514
1542
|
wordBreak: "break-word"
|
|
1515
1543
|
},
|
|
1516
|
-
children: /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { dangerouslySetInnerHTML: { __html: notification.message } })
|
|
1544
|
+
children: notification.allowHtml ? /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { dangerouslySetInnerHTML: { __html: sanitizeNotificationContent(notification.message) } }) : /* @__PURE__ */ (0, import_jsx_runtime4.jsx)("span", { children: notification.message })
|
|
1517
1545
|
}
|
|
1518
1546
|
)
|
|
1519
1547
|
}
|
|
@@ -1657,7 +1685,9 @@ function SessionProvider(props) {
|
|
|
1657
1685
|
enabled: props.showNotifications,
|
|
1658
1686
|
maxNotifications: props.notificationOptions?.maxNotifications || 5,
|
|
1659
1687
|
defaultAutoHideDuration: props.notificationOptions?.defaultAutoHideDuration || 6e3,
|
|
1660
|
-
position: props.notificationOptions?.position || { vertical: "top", horizontal: "right" }
|
|
1688
|
+
position: props.notificationOptions?.position || { vertical: "top", horizontal: "right" },
|
|
1689
|
+
allowHtml: props.notificationOptions?.allowHtml || false
|
|
1690
|
+
// Pasar allowHtml desde notificationOptions
|
|
1661
1691
|
};
|
|
1662
1692
|
return /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(GlobalNotificationProvider, { ...notificationConfig, children: /* @__PURE__ */ (0, import_jsx_runtime5.jsx)(InnerSessionProvider, { ...props }) });
|
|
1663
1693
|
}
|
|
@@ -4778,10 +4808,7 @@ var useCrudifyWithNotifications = (options = {}) => {
|
|
|
4778
4808
|
moduleKey = actionConfig.moduleKey;
|
|
4779
4809
|
}
|
|
4780
4810
|
}
|
|
4781
|
-
if (operation
|
|
4782
|
-
const message = getSafeTranslation("resetPassword.successMessage", "Contrase\xF1a restablecida exitosamente");
|
|
4783
|
-
showNotification(message, "success", { autoHideDuration });
|
|
4784
|
-
} else if (shouldShowSuccessNotification(operation, moduleKey)) {
|
|
4811
|
+
if (shouldShowSuccessNotification(operation, moduleKey)) {
|
|
4785
4812
|
const message = getSuccessMessage(operation, moduleKey, actionConfig);
|
|
4786
4813
|
showNotification(message, "success", { autoHideDuration });
|
|
4787
4814
|
}
|
package/dist/index.mjs
CHANGED
|
@@ -1328,15 +1328,33 @@ var isTokenExpired = (token) => {
|
|
|
1328
1328
|
import { useState as useState4, createContext as createContext4, useContext as useContext4, useCallback as useCallback2, useEffect as useEffect5 } from "react";
|
|
1329
1329
|
import { Snackbar, Alert, Box, Portal } from "@mui/material";
|
|
1330
1330
|
import { v4 as uuidv4 } from "uuid";
|
|
1331
|
+
import DOMPurify from "dompurify";
|
|
1331
1332
|
import { jsx as jsx4, jsxs } from "react/jsx-runtime";
|
|
1332
1333
|
var GlobalNotificationContext = createContext4(null);
|
|
1334
|
+
var sanitizeNotificationContent = (html) => {
|
|
1335
|
+
return DOMPurify.sanitize(html, {
|
|
1336
|
+
// Solo permitir tags seguros para notificaciones
|
|
1337
|
+
ALLOWED_TAGS: ["b", "i", "em", "strong", "br", "span"],
|
|
1338
|
+
ALLOWED_ATTR: ["class"],
|
|
1339
|
+
// Remover scripts y eventos
|
|
1340
|
+
FORBID_TAGS: ["script", "iframe", "object", "embed"],
|
|
1341
|
+
FORBID_ATTR: ["onload", "onerror", "onclick", "onmouseover", "onfocus", "onblur"],
|
|
1342
|
+
// Configuración adicional de seguridad
|
|
1343
|
+
WHOLE_DOCUMENT: false,
|
|
1344
|
+
RETURN_DOM: false,
|
|
1345
|
+
RETURN_DOM_FRAGMENT: false,
|
|
1346
|
+
RETURN_TRUSTED_TYPE: false
|
|
1347
|
+
});
|
|
1348
|
+
};
|
|
1333
1349
|
var GlobalNotificationProvider = ({
|
|
1334
1350
|
children,
|
|
1335
1351
|
maxNotifications = 5,
|
|
1336
1352
|
defaultAutoHideDuration = 6e3,
|
|
1337
1353
|
position = { vertical: "top", horizontal: "right" },
|
|
1338
|
-
enabled = false
|
|
1354
|
+
enabled = false,
|
|
1339
1355
|
// ✅ Por defecto DESACTIVADO
|
|
1356
|
+
allowHtml = false
|
|
1357
|
+
// Por defecto no permitir HTML
|
|
1340
1358
|
}) => {
|
|
1341
1359
|
const [notifications, setNotifications] = useState4([]);
|
|
1342
1360
|
const showNotification = useCallback2(
|
|
@@ -1344,13 +1362,23 @@ var GlobalNotificationProvider = ({
|
|
|
1344
1362
|
if (!enabled) {
|
|
1345
1363
|
return "";
|
|
1346
1364
|
}
|
|
1365
|
+
if (!message || typeof message !== "string") {
|
|
1366
|
+
console.warn("\u26A0\uFE0F GlobalNotificationProvider: Invalid message provided");
|
|
1367
|
+
return "";
|
|
1368
|
+
}
|
|
1369
|
+
if (message.length > 1e3) {
|
|
1370
|
+
console.warn("\u26A0\uFE0F GlobalNotificationProvider: Message too long, truncating");
|
|
1371
|
+
message = message.substring(0, 1e3) + "...";
|
|
1372
|
+
}
|
|
1347
1373
|
const id = uuidv4();
|
|
1348
1374
|
const newNotification = {
|
|
1349
1375
|
id,
|
|
1350
1376
|
message,
|
|
1351
1377
|
severity,
|
|
1352
1378
|
autoHideDuration: options?.autoHideDuration ?? defaultAutoHideDuration,
|
|
1353
|
-
persistent: options?.persistent ?? false
|
|
1379
|
+
persistent: options?.persistent ?? false,
|
|
1380
|
+
allowHtml: options?.allowHtml ?? allowHtml
|
|
1381
|
+
// Usar valor del provider por defecto
|
|
1354
1382
|
};
|
|
1355
1383
|
setNotifications((prev) => {
|
|
1356
1384
|
const updatedNotifications = prev.length >= maxNotifications ? prev.slice(-(maxNotifications - 1)) : prev;
|
|
@@ -1358,7 +1386,7 @@ var GlobalNotificationProvider = ({
|
|
|
1358
1386
|
});
|
|
1359
1387
|
return id;
|
|
1360
1388
|
},
|
|
1361
|
-
[maxNotifications, defaultAutoHideDuration, enabled]
|
|
1389
|
+
[maxNotifications, defaultAutoHideDuration, enabled, allowHtml]
|
|
1362
1390
|
);
|
|
1363
1391
|
const hideNotification = useCallback2((id) => {
|
|
1364
1392
|
setNotifications((prev) => prev.filter((notification) => notification.id !== id));
|
|
@@ -1440,7 +1468,7 @@ var NotificationItem = ({ notification, onClose }) => {
|
|
|
1440
1468
|
maxWidth: "400px",
|
|
1441
1469
|
wordBreak: "break-word"
|
|
1442
1470
|
},
|
|
1443
|
-
children: /* @__PURE__ */ jsx4("span", { dangerouslySetInnerHTML: { __html: notification.message } })
|
|
1471
|
+
children: notification.allowHtml ? /* @__PURE__ */ jsx4("span", { dangerouslySetInnerHTML: { __html: sanitizeNotificationContent(notification.message) } }) : /* @__PURE__ */ jsx4("span", { children: notification.message })
|
|
1444
1472
|
}
|
|
1445
1473
|
)
|
|
1446
1474
|
}
|
|
@@ -1584,7 +1612,9 @@ function SessionProvider(props) {
|
|
|
1584
1612
|
enabled: props.showNotifications,
|
|
1585
1613
|
maxNotifications: props.notificationOptions?.maxNotifications || 5,
|
|
1586
1614
|
defaultAutoHideDuration: props.notificationOptions?.defaultAutoHideDuration || 6e3,
|
|
1587
|
-
position: props.notificationOptions?.position || { vertical: "top", horizontal: "right" }
|
|
1615
|
+
position: props.notificationOptions?.position || { vertical: "top", horizontal: "right" },
|
|
1616
|
+
allowHtml: props.notificationOptions?.allowHtml || false
|
|
1617
|
+
// Pasar allowHtml desde notificationOptions
|
|
1588
1618
|
};
|
|
1589
1619
|
return /* @__PURE__ */ jsx5(GlobalNotificationProvider, { ...notificationConfig, children: /* @__PURE__ */ jsx5(InnerSessionProvider, { ...props }) });
|
|
1590
1620
|
}
|
|
@@ -4764,10 +4794,7 @@ var useCrudifyWithNotifications = (options = {}) => {
|
|
|
4764
4794
|
moduleKey = actionConfig.moduleKey;
|
|
4765
4795
|
}
|
|
4766
4796
|
}
|
|
4767
|
-
if (operation
|
|
4768
|
-
const message = getSafeTranslation("resetPassword.successMessage", "Contrase\xF1a restablecida exitosamente");
|
|
4769
|
-
showNotification(message, "success", { autoHideDuration });
|
|
4770
|
-
} else if (shouldShowSuccessNotification(operation, moduleKey)) {
|
|
4797
|
+
if (shouldShowSuccessNotification(operation, moduleKey)) {
|
|
4771
4798
|
const message = getSuccessMessage(operation, moduleKey, actionConfig);
|
|
4772
4799
|
showNotification(message, "success", { autoHideDuration });
|
|
4773
4800
|
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@nocios/crudify-ui",
|
|
3
|
-
"version": "3.0.
|
|
3
|
+
"version": "3.0.62",
|
|
4
4
|
"description": "Biblioteca de componentes UI para Crudify",
|
|
5
5
|
"author": "Nocios",
|
|
6
6
|
"license": "MIT",
|
|
@@ -26,8 +26,10 @@
|
|
|
26
26
|
"@mui/material": "^7.1.0",
|
|
27
27
|
"@mui/x-data-grid": "^8.5.1",
|
|
28
28
|
"@nocios/crudify-browser": "^2.0.6",
|
|
29
|
+
"@types/dompurify": "^3.0.5",
|
|
29
30
|
"@types/uuid": "^10.0.0",
|
|
30
31
|
"crypto-js": "^4.2.0",
|
|
32
|
+
"dompurify": "^3.2.7",
|
|
31
33
|
"i18next-browser-languagedetector": "^8.1.0",
|
|
32
34
|
"i18next-http-backend": "^3.0.2",
|
|
33
35
|
"react": "^19.1.0",
|