{"version":3,"sources":["../src/components/toaster.tsx","../src/core/store.ts","../src/components/toast.tsx","#style-inject:#style-inject","../src/core/styles.css","../src/components/assets.tsx","../src/core/toast.ts"],"sourcesContent":["import React, { useCallback, useEffect, useMemo, useState } from 'react';\r\nimport { IToast, ToastState, ToasterProps } from '../core/types';\r\nimport { Store } from '../core/store';\r\nimport { Toast } from './toast';\r\n\r\n/**\r\n * Toaster component for displaying toast notifications.\r\n * @param {object} ToasterProps - Props for configuring the toaster.\r\n * @returns {JSX.Element} - A component for displaying toast notifications.\r\n */\r\nconst Toaster = ({ position = 'bottom-right', duration = 3000, theme = 'light', options }: ToasterProps) => {\r\n  const [toasts, setToasts] = useState<IToast[]>([]);\r\n  const [positionState, setPositionState] = useState<React.CSSProperties>({});\r\n  const [height, setHeight] = useState(0);\r\n  useEffect(() => {\r\n    const unsubscribe = Store.subscribe((toast) => {\r\n      setToasts((toasts) => {\r\n        var index = toasts.findIndex((x) => x.id === toast.id);\r\n        if (index === -1) {\r\n          return [...toasts, toast];\r\n        } else {\r\n          var copy = [...toasts];\r\n          copy[index] = toast;\r\n          return copy;\r\n        }\r\n      });\r\n      handleToast(toast);\r\n    });\r\n\r\n    return () => {\r\n      unsubscribe();\r\n    };\r\n  }, []);\r\n\r\n  useEffect(() => {\r\n    const [y, x] = position.split('-');\r\n    setPositionState({\r\n      [y]: 0,\r\n      [x]: 0,\r\n    });\r\n  }, [position]);\r\n\r\n  useEffect(() => {\r\n    setHeight(toasts.length * 41);\r\n  }, [toasts]);\r\n\r\n  function handleToast(toast: IToast) {\r\n    setTimeout(() => updateToastState(toast, 'idle'), 300);\r\n    if (toast.type === 'loading') return;\r\n    setTimeout(() => updateToastState(toast, 'leave'), duration - 100);\r\n    setTimeout(() => removeToast(toast), duration);\r\n  }\r\n\r\n  function updateToastState(toast: IToast, state: ToastState) {\r\n    setToasts((toasts) => {\r\n      var copy = toasts.slice();\r\n      var index = copy.findIndex((x) => x.id === toast.id);\r\n      copy[index] = { ...copy[index], state: state };\r\n      return copy;\r\n    });\r\n  }\r\n\r\n  const removeToast = useCallback(\r\n    (toast: IToast) => setToasts((toasts) => toasts.filter((x) => x.id !== toast.id)),\r\n    [],\r\n  );\r\n\r\n  const isTop = position.startsWith('top');\r\n  const reversedToasts = useMemo(() => (isTop ? toasts.slice().reverse() : toasts), [isTop, toasts]);\r\n\r\n  return (\r\n    <section\r\n      style={{\r\n        position: 'fixed',\r\n        zIndex: 9999,\r\n        display: 'flex',\r\n        flexDirection: 'column',\r\n        gap: 5,\r\n        margin: 16,\r\n        transform: 'translateY(0)',\r\n        height: height,\r\n        transition: 'all 230ms cubic-bezier(.21, 1.02, .73, 1)',\r\n        ...positionState,\r\n      }}\r\n    >\r\n      {!isTop && <div className=\"flex h-full w-full grow\" />}\r\n      {reversedToasts.map((toast, index) => (\r\n        <Toast\r\n          key={toast.id}\r\n          toast={{ ...toast, zIndex: index, theme, ...options, ...options?.[toast.type] }}\r\n          position={position}\r\n        />\r\n      ))}\r\n      {isTop && <div className=\"flex h-full w-full grow\" />}\r\n    </section>\r\n  );\r\n};\r\n\r\nexport { Toaster };\r\n","import { IToast, ToastType } from './types';\r\n\r\nclass Reducer {\r\n  toasts: Array<IToast>;\r\n  subscribers: Array<(toast: IToast) => void>;\r\n\r\n  constructor() {\r\n    this.toasts = [];\r\n    this.subscribers = [];\r\n  }\r\n\r\n  /**\r\n   * Subscribe a function to receive toast updates.\r\n   * @param {function} func - A function that will be called when a new toast is published.\r\n   * @returns {function} - A function to unsubscribe from toast updates.\r\n   */\r\n  subscribe(func: (toast: IToast) => void) {\r\n    this.subscribers = [...this.subscribers, func];\r\n    return () => {\r\n      this.subscribers.splice(this.subscribers.indexOf(func), 1);\r\n    };\r\n  }\r\n\r\n  /**\r\n   * Publish a new toast to all subscribers.\r\n   * @param {IToast} toast - The toast object to publish.\r\n   */\r\n  publish(toast: IToast) {\r\n    this.subscribers.forEach((func) => func(toast));\r\n  }\r\n\r\n  /**\r\n   * Add a new toast to the store and publish it to subscribers.\r\n   * @param {string} message - The message to display in the toast.\r\n   * @param {ToastType} type - The type of the toast (e.g., 'info', 'success', 'error').\r\n   * @returns {IToast} - The added toast.\r\n   */\r\n  add(message: string, type: ToastType): IToast {\r\n    const toast = {\r\n      id: this.toasts.length,\r\n      state: 'enter',\r\n      type: type,\r\n      title: message,\r\n    } as IToast;\r\n\r\n    this.toasts = [...this.toasts, toast];\r\n    this.publish(toast);\r\n    return toast;\r\n  }\r\n\r\n  /**\r\n   * Update an existing toast and publish it to subscribers.\r\n   * @param {IToast} message - The toast to update.\r\n   */\r\n  update(toast: IToast) {\r\n    const index = this.toasts.findIndex((x) => x.id === toast.id);\r\n    this.toasts[index] = toast;\r\n    this.publish(toast);\r\n  }\r\n}\r\n\r\nexport const Store = new Reducer();\r\n","import React from 'react';\r\nimport { ToastProps } from '../core/types';\r\nimport '../core/styles.css';\r\nimport { ErrorIcon, LoadingIcon, SuccessIcon } from './assets';\r\n\r\nconst Toast = React.memo(({ toast, position }: ToastProps) => {\r\n  const themeBackground = toast.theme === 'light' ? 'rgb(243, 244, 246)' : 'rgb(17, 24, 39)';\r\n  const themeFont = toast.theme === 'light' ? 'rgb(17, 24, 39)' : 'rgb(243, 244, 246)';\r\n\r\n  const isTop = position.startsWith('top');\r\n  return (\r\n    <div\r\n      className={`toast-${isTop ? 'top' : 'bottom'}-${toast.state} ${toast.className}`}\r\n      style={{\r\n        paddingTop: '0.5rem',\r\n        paddingBottom: '0.5rem',\r\n        paddingLeft: '1rem',\r\n        paddingRight: '1rem',\r\n        borderRadius: '0.375rem',\r\n        backgroundColor: themeBackground,\r\n        fontWeight: 500,\r\n        fontSize: '0.875rem',\r\n        lineHeight: '1.25rem',\r\n        color: themeFont,\r\n        zIndex: isTop ? 9999 - toast.zIndex : toast.zIndex,\r\n        display: 'flex',\r\n        gap: 4,\r\n        minWidth: 220,\r\n        position: 'relative',\r\n        alignItems: 'center',\r\n        ...toast.style,\r\n      }}\r\n      key={toast.id}\r\n    >\r\n      {toast.type === 'success' && SuccessIcon}\r\n      {toast.type === 'error' && ErrorIcon}\r\n      {toast.type === 'loading' && LoadingIcon}\r\n      {toast.title}\r\n    </div>\r\n  );\r\n});\r\n\r\nexport { Toast };\r\n","\n          export default function styleInject(css, { insertAt } = {}) {\n            if (!css || typeof document === 'undefined') return\n          \n            const head = document.head || document.getElementsByTagName('head')[0]\n            const style = document.createElement('style')\n            style.type = 'text/css'\n          \n            if (insertAt === 'top') {\n              if (head.firstChild) {\n                head.insertBefore(style, head.firstChild)\n              } else {\n                head.appendChild(style)\n              }\n            } else {\n              head.appendChild(style)\n            }\n          \n            if (style.styleSheet) {\n              style.styleSheet.cssText = css\n            } else {\n              style.appendChild(document.createTextNode(css))\n            }\n          }\n          ","import styleInject from '#style-inject';styleInject(\".toast-bottom-enter{animation:enterAnimationBottom .35s cubic-bezier(.21,1.02,.73,1) forwards}.toast-bottom-leave{animation:leaveAnimationBottom .4s cubic-bezier(.06,.71,.55,1) forwards}.toast-top-enter{animation:enterAnimationTop .35s cubic-bezier(.21,1.02,.73,1) forwards}.toast-top-leave{animation:leaveAnimationTop .4s cubic-bezier(.06,.71,.55,1) forwards}.loading-icon{width:16px;height:16px;margin-right:4px;box-sizing:border-box;border:2px solid;border-radius:100%;border-color:#e0e0e0;border-right-color:#111827;animation:rotateAnimation 1s linear infinite}@keyframes enterAnimationBottom{0%{transform:translate3d(0,200%,0) scale(.6);opacity:.5}to{transform:translateZ(0) scale(1);opacity:1}}@keyframes leaveAnimationBottom{0%{transform:translateZ(-1px) scale(1);opacity:1}to{transform:translate3d(0,150%,-1px) scale(.6);opacity:0}}@keyframes enterAnimationTop{0%{transform:translate3d(0,-200%,0) scale(.6);opacity:.5}to{transform:translateZ(0) scale(1);opacity:1}}@keyframes leaveAnimationTop{0%{transform:translateZ(-1px) scale(1);opacity:1}to{transform:translate3d(0,-150%,-1px) scale(.6);opacity:0}}@keyframes rotateAnimation{0%{transform:rotate(0)}to{transform:rotate(360deg)}}\\n\")","import React from 'react';\r\nimport '../core/styles.css';\r\n\r\nconst SuccessIcon = (\r\n  <svg\r\n    xmlns=\"http://www.w3.org/2000/svg\"\r\n    viewBox=\"0 0 20 20\"\r\n    fill=\"currentColor\"\r\n    height=\"20\"\r\n    width=\"20\"\r\n    data-testid=\"success-icon\"\r\n  >\r\n    <path\r\n      fillRule=\"evenodd\"\r\n      d=\"M10 18a8 8 0 100-16 8 8 0 000 16zm3.857-9.809a.75.75 0 00-1.214-.882l-3.483 4.79-1.88-1.88a.75.75 0 10-1.06 1.061l2.5 2.5a.75.75 0 001.137-.089l4-5.5z\"\r\n      clipRule=\"evenodd\"\r\n    />\r\n  </svg>\r\n);\r\n\r\nconst ErrorIcon = (\r\n  <svg\r\n    xmlns=\"http://www.w3.org/2000/svg\"\r\n    viewBox=\"0 0 20 20\"\r\n    fill=\"currentColor\"\r\n    height=\"20\"\r\n    width=\"20\"\r\n    data-testid=\"error-icon\"\r\n  >\r\n    <path\r\n      fillRule=\"evenodd\"\r\n      d=\"M18 10a8 8 0 11-16 0 8 8 0 0116 0zm-8-5a.75.75 0 01.75.75v4.5a.75.75 0 01-1.5 0v-4.5A.75.75 0 0110 5zm0 10a1 1 0 100-2 1 1 0 000 2z\"\r\n      clipRule=\"evenodd\"\r\n    />\r\n  </svg>\r\n);\r\n\r\nconst LoadingIcon = <div className=\"loading-icon\" data-testid=\"loading-icon\" />;\r\n\r\nexport { SuccessIcon, ErrorIcon, LoadingIcon };\r\n","/**\r\n * Creates a new toast notification\r\n * @param {string} message - The message to be displayed in the toast.\r\n * @returns {void}\r\n */\r\n\r\nimport { Store } from './store';\r\n\r\nconst promise = <T>(\r\n  promiseFn: () => Promise<T>,\r\n  options: {\r\n    loading: string;\r\n    success: string;\r\n    error: string;\r\n  },\r\n): Promise<T> => {\r\n  var toast = Store.add(options.loading, 'loading');\r\n\r\n  return promiseFn().then(\r\n    (value: T) => {\r\n      toast.type = 'success';\r\n      toast.title = options.success;\r\n      toast.state = 'idle';\r\n      Store.update(toast);\r\n      return value;\r\n    },\r\n    (error: any) => {\r\n      toast.type = 'error';\r\n      toast.title = options.error;\r\n      toast.state = 'idle';\r\n      Store.update(toast);\r\n      return Promise.reject(error);\r\n    },\r\n  );\r\n};\r\n\r\nconst success = (message: string) => {\r\n  Store.add(message, 'success');\r\n};\r\n\r\nconst error = (message: string) => {\r\n  Store.add(message, 'error');\r\n};\r\n\r\nconst defaultToast = (message: string) => {\r\n  Store.add(message, 'default');\r\n};\r\n\r\nconst toast = Object.assign(defaultToast, {\r\n  success: success,\r\n  error: error,\r\n  promise: promise,\r\n});\r\n\r\nexport { toast };\r\n"],"mappings":"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","names":["React","useCallback","useEffect","useMemo","useState","Reducer","__publicField","func","toast","message","type","index","x","Store","React","styleInject","css","insertAt","head","style","styleInject","React","SuccessIcon","React","ErrorIcon","LoadingIcon","Toast","React","toast","position","themeBackground","themeFont","isTop","SuccessIcon","ErrorIcon","LoadingIcon","Toaster","position","duration","theme","options","toasts","setToasts","useState","positionState","setPositionState","height","setHeight","useEffect","unsubscribe","Store","toast","index","x","copy","handleToast","y","updateToastState","removeToast","state","useCallback","isTop","reversedToasts","useMemo","React","Toast","promise","promiseFn","options","toast","Store","value","error","success","message","defaultToast"]}