import { createContext, useCallback, useContext, useRef, useState } from "react"; import { StyledProvider, StyledViewport } from "./toast.styled"; import { Toast } from "./toast"; import type * as Stitches from "@stitches/react"; type ToastProps = React.ComponentProps & { id: number }; interface ToastContext { toasts: Array; publish: (newToast: Omit) => () => void; removeToastById: (id: ToastProps["id"]) => void; } const ToastContext = createContext({ toasts: [], publish: () => () => null, removeToastById: () => null, }); type ViewportVariants = Stitches.VariantProps; interface Props extends React.ComponentProps { /** * The position of the toast. */ position?: ViewportVariants["position"]; /** * Props to be passed to the __StyledViewport__ component. */ viewportProps?: React.ComponentProps; } export const ToastProvider: React.FC = ({ children, viewportProps, position, ...rest }) => { const [toasts, setToasts] = useState([]); const toastId = useRef(0); const removeToastById = useCallback((idToRemove: ToastProps["id"]) => { setToasts((prevToasts) => prevToasts.filter((toast) => toast.id !== idToRemove)); }, []); const publish = useCallback( (newToast: Omit) => { const newToastId = toastId.current++; setToasts((prevToasts) => { return [...prevToasts, { ...newToast, id: newToastId }]; }); return () => removeToastById(newToastId); }, [removeToastById] ); return ( {children} {toasts.map(({ id, ...toastProps }) => { return ; })} ); }; export const useToast = () => { return useContext(ToastContext); };