{"version":3,"sources":["../src/components/Toast/Toast.tsx","../src/store/toastStore.ts","../src/components/Toast/Toast.styles.ts","../src/components/Toast/Icon/Close.tsx","../src/components/Toast/ToastContent.tsx","../src/store/action.ts"],"sourcesContent":["import React from 'react';\nimport ReactDOM from 'react-dom';\nimport { Position, ToastType } from '../../types/toast';\nimport { useToastState } from '../../store/toastStore';\n\nimport { Wrapper } from './Toast.styles';\n\nimport ToastContent from './ToastContent';\n\nconst Toast = () => {\n  const toasts = useToastState();\n\n  const groupByToast = toasts.reduce(\n    (acc, toast) => {\n      const position = toast.position ?? 'bottom';\n      (acc[position] ??= []).push(toast);\n      return acc;\n    },\n    {} as Record<Position, ToastType[]>\n  );\n\n  return ReactDOM.createPortal(\n    <>\n      {(Object.keys(groupByToast) as Array<keyof typeof groupByToast>).map(\n        (key) => (\n          <Wrapper key={key} position={key}>\n            {groupByToast[key].map(\n              ({\n                id,\n                message = '',\n                type = 'default',\n                isClosable = true,\n                duration = 3000,\n                variants = 'filled',\n                position = 'bottom',\n                ...rest\n              }: ToastType) =>\n                React.cloneElement((<ToastContent />) as React.ReactElement, {\n                  id,\n                  message,\n                  type,\n                  isClosable,\n                  duration,\n                  variants,\n                  position,\n                  key: id,\n                  ...rest,\n                })\n            )}\n          </Wrapper>\n        )\n      )}\n    </>,\n    document.body\n  );\n};\n\nexport default Toast;\n","import { useState, useEffect } from 'react';\nimport { ToastType } from '../types/toast';\nimport { ActionType } from './type';\n\nlet globalToasts: ToastType[] = [];\nlet setGlobalToasts: (toasts: ToastType[]) => void = () => {};\n\nconst reducer = (state: ToastType[], action: ActionType): ToastType[] => {\n  switch (action.type) {\n    case 'ADD_TOAST':\n      return [...state, { ...action.payload }];\n    case 'REMOVE_TOAST':\n      return state.filter((toast) => toast.id !== action.payload);\n    default:\n      return state;\n  }\n};\n\nexport const dispatch = (action: ActionType) => {\n  globalToasts = reducer(globalToasts, action);\n  setGlobalToasts(globalToasts);\n};\n\nexport const useToastState = () => {\n  const [toasts, setToasts] = useState<ToastType[]>(globalToasts);\n\n  useEffect(() => {\n    setGlobalToasts = setToasts;\n\n    return () => {\n      setGlobalToasts = () => {};\n    };\n  }, []);\n\n  return toasts;\n};\n","import { css, keyframes } from '@emotion/react';\nimport styled from '@emotion/styled';\n\nimport { ToastType, Position } from '../../types/toast';\n\nimport ToastCloseIcon from './Icon/Close';\n\nconst topAnimation = keyframes({\n  '0%': {\n    transform: 'translateY(-120%)',\n  },\n  '100%': {\n    transform: 'translateY(0)',\n  },\n});\n\nconst LeftAnimation = keyframes({\n  '0%': {\n    transform: 'translateX(-120%)',\n  },\n  '100%': {\n    transform: 'translateX(0)',\n  },\n});\n\nconst RightAnimation = keyframes({\n  '0%': {\n    transform: 'translateX(120%)',\n  },\n  '100%': {\n    transform: 'translateX(0)',\n  },\n});\n\nconst bottomAnimation = keyframes({\n  '0%': {\n    transform: 'translateY(120%)',\n  },\n  '100%': {\n    transform: 'translateY(0)',\n  },\n});\n\nconst positionAnimation = {\n  top: topAnimation,\n  'top-left': LeftAnimation,\n  'top-right': RightAnimation,\n  bottom: bottomAnimation,\n  'bottom-left': LeftAnimation,\n  'bottom-right': RightAnimation,\n};\n\nconst toastStyle = {\n  type: {\n    success: css`\n      --main-color: #ffffff;\n      --main-background: #55a0ee;\n    `,\n    warn: css`\n      --main-color: #ffffff;\n      --main-background: #f1ad0f;\n    `,\n    error: css`\n      --main-color: #ffffff;\n      --main-background: #c9162b;\n    `,\n    default: css`\n      --main-color: #ffffff;\n      --main-background: #343a40;\n    `,\n  },\n  variants: {\n    filled: css`\n      color: var(--main-color);\n      background: var(--main-background);\n    `,\n    outlined: css`\n      color: var(--main-background);\n      background: #fff;\n      border: 1px solid var(--main-background);\n    `,\n  },\n};\n\nexport const StyledToastItem = styled.div<\n  Pick<ToastType, 'type' | 'variants' | 'position'>\n>`\n  display: flex;\n  gap: 16px;\n  align-items: center;\n  justify-content: space-between;\n\n  box-sizing: content-box;\n  min-width: 320px;\n  max-width: 640px;\n  min-height: 24px;\n  margin-bottom: 8px;\n  padding: 16px;\n\n  border-radius: 8px;\n\n  ${({ type }) => type && toastStyle.type[type]}\n  ${({ variants }) => variants && toastStyle.variants[variants]}\n  ${({ position }) =>\n    position &&\n    css`\n      animation: ${positionAnimation[position]} 0.3s forwards;\n    `}\n`;\n\nexport const StyledCloseButton = styled.button`\n  height: 24px;\n  padding: 0;\n  background: none;\n  border: none;\n`;\n\nexport const StyledModalCloseIcon = styled(ToastCloseIcon)<{\n  variant?: string;\n}>`\n  ${({ variant }) =>\n    variant === 'outlined'\n      ? css`\n          > path {\n            fill: var(--main-background);\n          }\n        `\n      : css`\n          > path {\n            fill: var(--main-color);\n          }\n        `}\n`;\n\nconst positionStyle = {\n  top: css`\n    top: 20px;\n    left: 50%;\n    transform: translateX(-50%);\n  `,\n  'top-left': css`\n    top: 20px;\n    left: 20px;\n  `,\n  'top-right': css`\n    top: 20px;\n    right: 20px;\n  `,\n  bottom: css`\n    bottom: 20px;\n    left: 50%;\n    transform: translateX(-50%);\n  `,\n  'bottom-left': css`\n    bottom: 20px;\n    left: 20px;\n  `,\n  'bottom-right': css`\n    right: 20px;\n    bottom: 20px;\n  `,\n};\n\nexport const Wrapper = styled.div<{ position: Position }>`\n  position: fixed;\n  z-index: 10000;\n  overflow: hidden;\n  box-sizing: border-box;\n\n  ${({ position }) => positionStyle[position]};\n`;\n","import { SVGProps } from 'react';\n\ntype ToastCloseIconProps = SVGProps<SVGSVGElement>;\n\nconst CloseIcon = (props: ToastCloseIconProps) => {\n  return (\n    <svg\n      xmlns=\"http://www.w3.org/2000/svg\"\n      width=\"24\"\n      height=\"24\"\n      viewBox=\"0 0 24 24\"\n      fill=\"none\"\n      {...props}\n    >\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M7.421 7.42167C7.69437 7.1483 8.13758 7.1483 8.41095 7.42167L16.5776 15.5883C16.851 15.8617 16.851 16.3049 16.5776 16.5783C16.3042 16.8517 15.861 16.8517 15.5877 16.5783L7.421 8.41162C7.14763 8.13825 7.14763 7.69504 7.421 7.42167Z\"\n        fill=\"white\"\n      />\n      <path\n        fillRule=\"evenodd\"\n        clipRule=\"evenodd\"\n        d=\"M16.5776 7.42167C16.851 7.69504 16.851 8.13825 16.5776 8.41162L8.41095 16.5783C8.13758 16.8517 7.69437 16.8517 7.421 16.5783C7.14763 16.3049 7.14763 15.8617 7.421 15.5883L15.5877 7.42167C15.861 7.1483 16.3042 7.1483 16.5776 7.42167Z\"\n        fill=\"white\"\n      />\n    </svg>\n  );\n};\n\nexport default CloseIcon;\n","import React, { useEffect } from 'react';\n\nimport { ToastType } from '../../types/toast';\n\nimport { removeToast } from '../../store/action';\nimport {\n  StyledToastItem,\n  StyledModalCloseIcon,\n  StyledCloseButton,\n} from './Toast.styles';\n\nconst ToastContent = ({\n  id,\n  message,\n  duration,\n  isClosable,\n  type,\n  custom,\n  variants,\n  position,\n}: ToastType) => {\n  useEffect(() => {\n    const timer = setTimeout(() => {\n      removeToast(String(id));\n    }, duration);\n\n    return () => clearTimeout(timer);\n  }, [id, duration]);\n\n  return (\n    <StyledToastItem type={type} variants={variants} position={position}>\n      {custom?.() ?? (\n        <span>\n          {message?.split('\\n').map((line, index) => (\n            <React.Fragment key={index}>\n              {line}\n              <br />\n            </React.Fragment>\n          ))}\n        </span>\n      )}\n      {isClosable && (\n        <StyledCloseButton onClick={() => removeToast(String(id))}>\n          <StyledModalCloseIcon variant={variants} />\n        </StyledCloseButton>\n      )}\n    </StyledToastItem>\n  );\n};\n\nexport default ToastContent;\n","import { v4 as uuid } from 'uuid';\nimport { dispatch } from './toastStore';\nimport { ToastType } from '../types/toast';\n\nexport const addToast = (toast: ToastType) => {\n  const id = uuid();\n  dispatch({\n    type: 'ADD_TOAST',\n    payload: { ...toast, id },\n  });\n};\n\n// 토스트 제거하는 함수\nexport const removeToast = (id: string) => {\n  dispatch({ type: 'REMOVE_TOAST', payload: id });\n};\n"],"mappings":"AAAA,OAAOA,MAAW,QAClB,OAAOC,MAAc,YCDrB,OAAS,YAAAC,EAAU,aAAAC,MAAiB,QAIpC,IAAIC,EAA4B,CAAC,EAC7BC,EAAiD,IAAM,CAAC,EAEtDC,EAAU,CAACC,EAAoBC,IAAoC,CACvE,OAAQA,EAAO,KAAM,CACnB,IAAK,YACH,MAAO,CAAC,GAAGD,EAAO,CAAE,GAAGC,EAAO,OAAQ,CAAC,EACzC,IAAK,eACH,OAAOD,EAAM,OAAQE,GAAUA,EAAM,KAAOD,EAAO,OAAO,EAC5D,QACE,OAAOD,CACX,CACF,EAEaG,EAAYF,GAAuB,CAC9CJ,EAAeE,EAAQF,EAAcI,CAAM,EAC3CH,EAAgBD,CAAY,CAC9B,EAEaO,EAAgB,IAAM,CACjC,GAAM,CAACC,EAAQC,CAAS,EAAIX,EAAsBE,CAAY,EAE9D,OAAAD,EAAU,KACRE,EAAkBQ,EAEX,IAAM,CACXR,EAAkB,IAAM,CAAC,CAC3B,GACC,CAAC,CAAC,EAEEO,CACT,ECnCA,OAAS,OAAAE,EAAK,aAAAC,MAAiB,iBAC/B,OAAOC,MAAY,kBCKf,OAQE,OAAAC,EARF,QAAAC,MAAA,oBAFJ,IAAMC,EAAaC,GAEfF,EAAC,OACC,MAAM,6BACN,MAAM,KACN,OAAO,KACP,QAAQ,YACR,KAAK,OACJ,GAAGE,EAEJ,UAAAH,EAAC,QACC,SAAS,UACT,SAAS,UACT,EAAE,yOACF,KAAK,QACP,EACAA,EAAC,QACC,SAAS,UACT,SAAS,UACT,EAAE,2OACF,KAAK,QACP,GACF,EAIGI,EAAQF,EDvBf,IAAMG,EAAeC,EAAU,CAC7B,KAAM,CACJ,UAAW,mBACb,EACA,OAAQ,CACN,UAAW,eACb,CACF,CAAC,EAEKC,EAAgBD,EAAU,CAC9B,KAAM,CACJ,UAAW,mBACb,EACA,OAAQ,CACN,UAAW,eACb,CACF,CAAC,EAEKE,EAAiBF,EAAU,CAC/B,KAAM,CACJ,UAAW,kBACb,EACA,OAAQ,CACN,UAAW,eACb,CACF,CAAC,EAEKG,EAAkBH,EAAU,CAChC,KAAM,CACJ,UAAW,kBACb,EACA,OAAQ,CACN,UAAW,eACb,CACF,CAAC,EAEKI,EAAoB,CACxB,IAAKL,EACL,WAAYE,EACZ,YAAaC,EACb,OAAQC,EACR,cAAeF,EACf,eAAgBC,CAClB,EAEMG,EAAa,CACjB,KAAM,CACJ,QAASC;AAAA;AAAA;AAAA,MAIT,KAAMA;AAAA;AAAA;AAAA,MAIN,MAAOA;AAAA;AAAA;AAAA,MAIP,QAASA;AAAA;AAAA;AAAA,KAIX,EACA,SAAU,CACR,OAAQA;AAAA;AAAA;AAAA,MAIR,SAAUA;AAAA;AAAA;AAAA;AAAA,KAKZ,CACF,EAEaC,EAAkBC,EAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAiBlC,CAAC,CAAE,KAAAC,CAAK,IAAMA,GAAQJ,EAAW,KAAKI,CAAI,CAAC;AAAA,IAC3C,CAAC,CAAE,SAAAC,CAAS,IAAMA,GAAYL,EAAW,SAASK,CAAQ,CAAC;AAAA,IAC3D,CAAC,CAAE,SAAAC,CAAS,IACZA,GACAL;AAAA,mBACeF,EAAkBO,CAAQ,CAAC;AAAA,KACzC;AAAA,EAGQC,EAAoBJ,EAAO;AAAA;AAAA;AAAA;AAAA;AAAA,EAO3BK,EAAuBL,EAAOM,CAAc;AAAA,IAGrD,CAAC,CAAE,QAAAC,CAAQ,IACXA,IAAY,WACRT;AAAA;AAAA;AAAA;AAAA,UAKAA;AAAA;AAAA;AAAA;AAAA,SAIC;AAAA,EAGHU,EAAgB,CACpB,IAAKV;AAAA;AAAA;AAAA;AAAA,IAKL,WAAYA;AAAA;AAAA;AAAA,IAIZ,YAAaA;AAAA;AAAA;AAAA,IAIb,OAAQA;AAAA;AAAA;AAAA;AAAA,IAKR,cAAeA;AAAA;AAAA;AAAA,IAIf,eAAgBA;AAAA;AAAA;AAAA,GAIlB,EAEaW,EAAUT,EAAO;AAAA;AAAA;AAAA;AAAA;AAAA;AAAA,IAM1B,CAAC,CAAE,SAAAG,CAAS,IAAMK,EAAcL,CAAQ,CAAC;EEzK7C,OAAOO,GAAS,aAAAC,MAAiB,QCAjC,OAAS,MAAMC,MAAY,OAIpB,IAAMC,EAAYC,GAAqB,CAC5C,IAAMC,EAAKC,EAAK,EAChBC,EAAS,CACP,KAAM,YACN,QAAS,CAAE,GAAGH,EAAO,GAAAC,CAAG,CAC1B,CAAC,CACH,EAGaG,EAAeH,GAAe,CACzCE,EAAS,CAAE,KAAM,eAAgB,QAASF,CAAG,CAAC,CAChD,EDmBY,OAEE,OAAAI,EAFF,QAAAC,MAAA,oBAvBZ,IAAMC,EAAe,CAAC,CACpB,GAAAC,EACA,QAAAC,EACA,SAAAC,EACA,WAAAC,EACA,KAAAC,EACA,OAAAC,EACA,SAAAC,EACA,SAAAC,CACF,KACEC,EAAU,IAAM,CACd,IAAMC,EAAQ,WAAW,IAAM,CAC7BC,EAAY,OAAOV,CAAE,CAAC,CACxB,EAAGE,CAAQ,EAEX,MAAO,IAAM,aAAaO,CAAK,CACjC,EAAG,CAACT,EAAIE,CAAQ,CAAC,EAGfJ,EAACa,EAAA,CAAgB,KAAMP,EAAM,SAAUE,EAAU,SAAUC,EACxD,UAAAF,IAAS,GACRR,EAAC,QACE,SAAAI,GAAS,MAAM;AAAA,CAAI,EAAE,IAAI,CAACW,EAAMC,IAC/Bf,EAACgB,EAAM,SAAN,CACE,UAAAF,EACDf,EAAC,OAAG,IAFegB,CAGrB,CACD,EACH,EAEDV,GACCN,EAACkB,EAAA,CAAkB,QAAS,IAAML,EAAY,OAAOV,CAAE,CAAC,EACtD,SAAAH,EAACmB,EAAA,CAAqB,QAASV,EAAU,EAC3C,GAEJ,GAIGW,EAAQlB,EJ5BX,mBAAAmB,EAegC,OAAAC,MAfhC,oBAbJ,IAAMC,EAAQ,IAAM,CAGlB,IAAMC,EAFSC,EAAc,EAED,OAC1B,CAACC,EAAKC,IAAU,CACd,IAAMC,EAAWD,EAAM,UAAY,SACnC,OAACD,EAAIE,CAAQ,IAAM,CAAC,GAAG,KAAKD,CAAK,EAC1BD,CACT,EACA,CAAC,CACH,EAEA,OAAOG,EAAS,aACdP,EAAAD,EAAA,CACI,gBAAO,KAAKG,CAAY,EAAuC,IAC9DM,GACCR,EAACS,EAAA,CAAkB,SAAUD,EAC1B,SAAAN,EAAaM,CAAG,EAAE,IACjB,CAAC,CACC,GAAAE,EACA,QAAAC,EAAU,GACV,KAAAC,EAAO,UACP,WAAAC,EAAa,GACb,SAAAC,EAAW,IACX,SAAAC,EAAW,SACX,SAAAT,EAAW,SACX,GAAGU,CACL,IACEC,EAAM,aAAcjB,EAACkB,EAAA,EAAa,EAA2B,CAC3D,GAAAR,EACA,QAAAC,EACA,KAAAC,EACA,WAAAC,EACA,SAAAC,EACA,SAAAC,EACA,SAAAT,EACA,IAAKI,EACL,GAAGM,CACL,CAAC,CACL,GAvBYR,CAwBd,CAEJ,EACF,EACA,SAAS,IACX,CACF,EAEOW,EAAQlB","names":["React","ReactDOM","useState","useEffect","globalToasts","setGlobalToasts","reducer","state","action","toast","dispatch","useToastState","toasts","setToasts","css","keyframes","styled","jsx","jsxs","CloseIcon","props","Close_default","topAnimation","keyframes","LeftAnimation","RightAnimation","bottomAnimation","positionAnimation","toastStyle","css","StyledToastItem","styled","type","variants","position","StyledCloseButton","StyledModalCloseIcon","Close_default","variant","positionStyle","Wrapper","React","useEffect","uuid","addToast","toast","id","uuid","dispatch","removeToast","jsx","jsxs","ToastContent","id","message","duration","isClosable","type","custom","variants","position","useEffect","timer","removeToast","StyledToastItem","line","index","React","StyledCloseButton","StyledModalCloseIcon","ToastContent_default","Fragment","jsx","Toast","groupByToast","useToastState","acc","toast","position","ReactDOM","key","Wrapper","id","message","type","isClosable","duration","variants","rest","React","ToastContent_default","Toast_default"]}