JFIFxxC      C  " }!1AQa"q2#BR$3br %&'()*456789:CDEFGHIJSTUVWXYZcdefghijstuvwxyz w!1AQaq"2B #3Rbr{ gilour

File "toast-container.tsx"

Full Path: /home/markqprx/iniasli.pro/client/ui/toast/toast-container.tsx
File size: 3.92 KB
MIME-type: text/plain
Charset: utf-8

import {AnimatePresence, m, Target, TargetAndTransition} from 'framer-motion';
import React from 'react';
import clsx from 'clsx';
import {IconButton} from '../buttons/icon-button';
import {CloseIcon} from '../../icons/material/Close';
import {MixedText} from '../../i18n/mixed-text';
import {Button} from '../buttons/button';
import {toastState, useToastStore} from './toast-store';
import {Link} from 'react-router-dom';
import {ErrorOutlineIcon} from '../../icons/material/ErrorOutline';
import {CheckCircleIcon} from '../../icons/material/CheckCircle';
import {ProgressCircle} from '@common/ui/progress/progress-circle';

const initial: Target = {opacity: 0, y: 50, scale: 0.3};
const animate: TargetAndTransition = {opacity: 1, y: 0, scale: 1};
const exit: TargetAndTransition = {
  opacity: 0,
  scale: 0.5,
};

export function ToastContainer() {
  const toasts = useToastStore(s => s.toasts);

  return (
    <div className="relative pointer-events-none">
      <AnimatePresence initial={false}>
        {toasts.map(toast => (
          <div
            key={toast.id}
            className={clsx(
              'fixed mx-auto p-20 z-toast',
              toast.position === 'bottom-center'
                ? 'left-0 right-0 bottom-0'
                : 'right-0 bottom-0'
            )}
          >
            <m.div
              initial={toast.disableEnterAnimation ? undefined : initial}
              animate={toast.disableEnterAnimation ? undefined : animate}
              exit={toast.disableExitAnimation ? undefined : exit}
              className={clsx(
                'flex items-center gap-10 min-w-288 max-w-500 shadow-lg w-min rounded-lg pl-16 pr-6 py-6 text-sm pointer-events-auto max-h-100 bg-paper text-main bg-paper border mx-auto min-h-50'
              )}
              onPointerEnter={() => toast.timer?.pause()}
              onPointerLeave={() => toast.timer?.resume()}
              role="alert"
              aria-live={toast.type === 'danger' ? 'assertive' : 'polite'}
            >
              {toast.type === 'danger' && (
                <ErrorOutlineIcon
                  className="text-danger flex-shrink-0"
                  size="md"
                />
              )}
              {toast.type === 'loading' && (
                <ProgressCircle
                  size="sm"
                  className="flex-shrink-0"
                  isIndeterminate
                />
              )}
              {toast.type === 'positive' && (
                <CheckCircleIcon
                  className="text-positive flex-shrink-0"
                  size="md"
                />
              )}

              <div
                className="overflow-hidden overflow-ellipsis w-max mr-auto"
                data-testid="toast-message"
              >
                <MixedText value={toast.message} />
              </div>

              {toast.action && (
                <Button
                  variant="text"
                  color="primary"
                  size="sm"
                  className="flex-shrink-0"
                  onFocus={() => toast.timer?.pause()}
                  onBlur={() => toast.timer?.resume()}
                  onClick={() => toastState().remove(toast.id)}
                  elementType={Link}
                  to={toast.action.action}
                >
                  <MixedText value={toast.action.label} />
                </Button>
              )}
              {toast.type !== 'loading' && (
                <IconButton
                  onFocus={() => toast.timer?.pause()}
                  onBlur={() => toast.timer?.resume()}
                  type="button"
                  className="flex-shrink-0"
                  onClick={() => {
                    toastState().remove(toast.id);
                  }}
                  size="sm"
                >
                  <CloseIcon />
                </IconButton>
              )}
            </m.div>
          </div>
        ))}
      </AnimatePresence>
    </div>
  );
}