import { useNuiEvent } from '../../hooks/useNuiEvent'; import { toast, Toaster } from 'react-hot-toast'; import ReactMarkdown from 'react-markdown'; import { Box, Center, createStyles, Group, keyframes, RingProgress, Stack, Text, ThemeIcon } from '@mantine/core'; import React, { useRef } from 'react'; import tinycolor from 'tinycolor2'; import type { NotificationProps } from '../../typings'; import MarkdownComponents from '../../config/MarkdownComponents'; import LibIcon from '../../components/LibIcon'; const useStyles = createStyles((theme) => ({ container: { width: 300, height: 'fit-content', backgroundColor: theme.colors.dark[6], color: theme.colors.dark[0], padding: 12, borderRadius: theme.radius.sm, fontFamily: 'Roboto', boxShadow: theme.shadows.sm, }, title: { fontWeight: 500, lineHeight: 'normal', }, description: { fontSize: 12, color: theme.colors.dark[2], fontFamily: 'Roboto', lineHeight: 'normal', }, descriptionOnly: { fontSize: 14, color: theme.colors.dark[2], fontFamily: 'Roboto', lineHeight: 'normal', }, })); // I hate this const enterAnimationTop = keyframes({ from: { opacity: 0, transform: 'translateY(-30px)', }, to: { opacity: 1, transform: 'translateY(0px)', }, }); const enterAnimationBottom = keyframes({ from: { opacity: 0, transform: 'translateY(30px)', }, to: { opacity: 1, transform: 'translateY(0px)', }, }); const exitAnimationTop = keyframes({ from: { opacity: 1, transform: 'translateY(0px)', }, to: { opacity: 0, transform: 'translateY(-100%)', }, }); const exitAnimationRight = keyframes({ from: { opacity: 1, transform: 'translateX(0px)', }, to: { opacity: 0, transform: 'translateX(100%)', }, }); const exitAnimationLeft = keyframes({ from: { opacity: 1, transform: 'translateX(0px)', }, to: { opacity: 0, transform: 'translateX(-100%)', }, }); const exitAnimationBottom = keyframes({ from: { opacity: 1, transform: 'translateY(0px)', }, to: { opacity: 0, transform: 'translateY(100%)', }, }); const durationCircle = keyframes({ '0%': { strokeDasharray: `0, ${15.1 * 2 * Math.PI}` }, '100%': { strokeDasharray: `${15.1 * 2 * Math.PI}, 0` }, }); const Notifications: React.FC = () => { const { classes } = useStyles(); const toastKeyRef = useRef(0); useNuiEvent('notify', (data) => { const toastId = data.id?.toString(); if (toastId) toastKeyRef.current++; if (!data.title && !data.description) return; let iconColor: string; let duration = data.duration || 3000; data.showDuration = data.showDuration !== undefined ? data.showDuration : true; // Backwards compat with old notifications let position = data.position; switch (position) { case 'top': position = 'top-center'; break; case 'bottom': position = 'bottom-center'; break; } if (!data.icon) { switch (data.type) { case 'error': data.icon = 'circle-xmark'; break; case 'success': data.icon = 'circle-check'; break; case 'warning': data.icon = 'circle-exclamation'; break; default: data.icon = 'circle-info'; break; } } if (!data.iconColor) { switch (data.type) { case 'error': iconColor = 'red.6'; break; case 'success': iconColor = 'teal.6'; break; case 'warning': iconColor = 'yellow.6'; break; default: iconColor = 'blue.6'; break; } } else { iconColor = tinycolor(data.iconColor).toRgbString(); } toast.custom( (t) => ( {data.icon && ( <> {data.showDuration ? ( svg > circle:nth-of-type(2)': { animation: `${durationCircle} linear forwards reverse`, animationDuration: `${duration}ms`, }, margin: -3, }, }} label={
} /> ) : ( )} )} {data.title && {data.title}} {data.description && ( {data.description} )}
), { id: toastId, duration: duration, position: position || 'top-right', } ); }); return ; }; export default Notifications;