UNPKG

mui-alert-provider

Version:

Make your alerts float! A lightweight provider for Material UI’s Alert that fits seamlessly into any web UI.

80 lines (79 loc) 3.54 kB
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime"; import React, { useCallback, useMemo, useState } from "react"; import AlertComponent from "./Alert"; import { Box, useMediaQuery } from "@mui/material"; const AlertContext = React.createContext(undefined); const AlertProvider = ({ children, limit = 4, mobileLimit = 1, position = "top-right", width = "20%", minWidth = "280px", containerSx = {}, duration = 300, mobileBreakpoint = "600px", muiAlertProps = {}, muiStackProps = {}, }) => { const [alerts, setAlerts] = useState([]); const isMobile = useMediaQuery(`(max-width:${mobileBreakpoint})`); const limitToApply = useMemo(() => { return isMobile ? mobileLimit : limit; }, [isMobile, limit, mobileLimit]); const addAlert = useCallback(({ message, severity }) => { const newAlert = { message, severity, isNewAlert: true }; setAlerts(prevAlerts => { if (prevAlerts.length >= limitToApply) { // Remove the oldest alert if the max number is reached. return [...prevAlerts.slice(1), newAlert]; } return [...prevAlerts, newAlert]; }); // Remove the isNewAlert property after the duration. setTimeout(() => { setAlerts(prevAlerts => { return prevAlerts.map(alert => { return Object.assign(Object.assign({}, alert), { isNewAlert: false }); }); }); }, duration); }, [limitToApply, duration]); const removeAlert = useCallback((index) => { setAlerts(prevAlerts => { // Reduce prevAlerts to exclude prevAlerts[index]. // Also remove the isNewAlert property from the alert. return prevAlerts.reduce((acc, alert, i) => { if (i !== index) { acc.push(Object.assign(Object.assign({}, alert), { isNewAlert: false })); } return acc; }, []); }); }, []); const getSxPosition = useCallback(() => { if (position === "top-right") { return { top: 0, right: 0, }; } else if (position === "top-left") { return { top: 0, left: 0, }; } else if (position === "bottom-right") { return { bottom: 0, right: 0, }; } else if (position === "bottom-left") { return { bottom: 0, left: 0, }; } else { // Default to top-right if the position is not recognized. console.warn(`Unrecognized position "${position}". Defaulting to "top-right".`); return { top: 0, right: 0, }; } }, [position]); return (_jsx(AlertContext.Provider, { value: { addAlert }, children: _jsxs(Box, { children: [_jsx(Box, { id: "mui-alerts-provider-container", sx: Object.assign(Object.assign({ boxSizing: "border-box", width: !isMobile ? width : "100%", minWidth: !isMobile ? minWidth : "100%", position: "absolute", zIndex: 9999, p: 1 }, getSxPosition()), containerSx), children: _jsx(AlertComponent, { alerts: alerts, removeAlert: removeAlert, duration: duration, muiAlertProps: muiAlertProps, muiStackProps: muiStackProps }) }), _jsx(Box, { children: children })] }) })); }; export { AlertContext }; export default AlertProvider;