{"version":3,"file":"Toast.mjs","sources":["../../../../../../../../../web/src/ui/components/atoms/Toast.tsx"],"sourcesContent":["import React, { useEffect, useRef } from 'react';\n\nimport { getTransitionDuration } from './animation';\nimport styles from './Toast.module.css';\n\nconst DEFAULT_DURATION = 10_000;\n\ntype Toast = {\n  message: string;\n  durationMs?: number;\n};\n\n// Really simple event bus. We assume ToastContainer is always mounted so no error handling in case there's\n// no listeners\nconst listeners: ((newToast: Toast) => void)[] = [];\nexport function errorToast(toast: Toast) {\n  for (const listener of listeners) {\n    listener(toast);\n  }\n}\n\nconst steps = {\n  start: { opacity: 0, translate: '0 var(--st-spacing-2)' },\n  end: { opacity: 1, translate: '0' },\n};\n\nfunction animateToastOut(element: HTMLElement, duration: number) {\n  const animation = element.animate([steps.end, steps.start], { duration, easing: 'ease-in-out' });\n  animation.addEventListener('finish', () => element.remove());\n}\n\nexport const ToastContainer = () => {\n  const containerRef = useRef<HTMLDivElement>(null);\n  const toastRef = useRef<HTMLDivElement>();\n  const timeoutRef = useRef<number>();\n\n  // We're just going to run all of these via manual DOM manipulation since we want finer control over the element\n  // lifecycle than React is going to give us\n  useEffect(() => {\n    const listener = (toast: Toast) => {\n      if (!containerRef.current) return;\n\n      const duration = getTransitionDuration(containerRef.current) * 2;\n\n      const toastElement = document.createElement('div');\n      toastElement.textContent = toast.message;\n      toastElement.className = styles.toast;\n\n      // Animate existing toast out\n      if (toastRef.current) animateToastOut(toastRef.current, duration);\n\n      // Create new toast and animate in\n      containerRef.current.appendChild(toastElement);\n      toastRef.current = toastElement;\n      toastElement.animate([steps.start, steps.end], { duration, easing: 'ease-in-out' });\n\n      // Animate out after set duration\n      timeoutRef.current = window.setTimeout(() => {\n        if (!toastRef.current) return;\n        animateToastOut(toastRef.current, duration);\n        toastRef.current = undefined;\n      }, toast.durationMs ?? DEFAULT_DURATION);\n    };\n\n    listeners.push(listener);\n    return () => {\n      clearTimeout(timeoutRef.current);\n      const index = listeners.indexOf(listener);\n      if (index !== -1) listeners.splice(index, 1);\n    };\n  }, []);\n\n  return <div className={styles.container} ref={containerRef} aria-live=\"polite\"></div>;\n};\n"],"names":["DEFAULT_DURATION","listeners","errorToast","toast","listener","steps","start","opacity","translate","end","animateToastOut","element","duration","animation","animate","easing","addEventListener","remove","ToastContainer","containerRef","useRef","toastRef","timeoutRef","useEffect","current","getTransitionDuration","toastElement","document","createElement","textContent","message","className","styles","appendChild","window","setTimeout","undefined","durationMs","push","clearTimeout","index","indexOf","splice","React","div","container","ref","aria-live"],"mappings":"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"}