All files / components/Toaster ToasterProvider.tsx

100% Statements 56/56
100% Branches 7/7
100% Functions 2/2
100% Lines 56/56

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 571x 1x 1x 1x 1x 1x 1x 1x 1x 1x 6x 6x 6x 6x 6x 6x 6x 6x 6x 1x 1x 6x 6x 5x 5x 5x 5x 6x 6x 6x 6x 6x 6x 6x 6x 2x 2x 2x 2x 2x 5x 5x 5x 5x 5x 5x 2x 2x 6x 6x 6x 6x 6x 6x 6x 6x  
import { useCallback, useRef, useState } from 'react';
import { createPortal } from 'react-dom';
 
import { c } from '../../helpers';
import ToasterItem from './ToasterItem';
import ToasterListContext from './ToasterListContext';
import type { Toaster, ToasterProviderProps } from './ToasterProps';
 
import styles from './Toaster.module.css';
 
export default function ToasterProvider({
  children,
  listClassName,
  itemClassName,
}: ToasterProviderProps): JSX.Element {
  const [portalId] = useState<string>(crypto.randomUUID());
  const [toasters, setToasters] = useState<Toaster[]>([]);
 
  const handleToasterClose = (id: string): void => {
    setToasters(toasters.filter(toaster => toaster.id !== id));
  };
 
  const addToaster = useCallback((toaster: Toaster): void => {
    setToasters((prevToasters: Toaster[]) => [
      ...prevToasters,
      { ...toaster, id: crypto.randomUUID() },
    ]);
  }, []);
 
  const toasterListRef = useRef<HTMLDivElement>(null);
 
  return (
    <ToasterListContext.Provider value={{ toasters, addToaster }}>
      {createPortal(
        toasters.length > 0 && (
          <div
            ref={toasterListRef}
            className={c(styles.toaster_list, listClassName)}
          >
            {toasters.map(toaster => (
              <ToasterItem
                className={c(itemClassName)}
                key={toaster.id}
                onClose={handleToasterClose}
                toaster={toaster}
              />
            ))}
          </div>
        ),
        document.body,
        portalId
      )}
      {children}
    </ToasterListContext.Provider>
  );
}