'use client' import type { ToastManagerAddOptions, ToastManagerUpdateOptions, ToastObject, } from '@base-ui/react/toast' import type { ReactNode } from 'react' import { Toast as BaseToast } from '@base-ui/react/toast' import { useTranslation } from 'react-i18next' import { cn } from '@/utils/classnames' type ToastData = Record type ToastToneStyle = { gradientClassName: string iconClassName: string } const TOAST_TONE_STYLES = { success: { iconClassName: 'i-ri-checkbox-circle-fill text-text-success', gradientClassName: 'from-components-badge-status-light-success-halo to-background-gradient-mask-transparent', }, error: { iconClassName: 'i-ri-error-warning-fill text-text-destructive', gradientClassName: 'from-components-badge-status-light-error-halo to-background-gradient-mask-transparent', }, warning: { iconClassName: 'i-ri-alert-fill text-text-warning-secondary', gradientClassName: 'from-components-badge-status-light-warning-halo to-background-gradient-mask-transparent', }, info: { iconClassName: 'i-ri-information-2-fill text-text-accent', gradientClassName: 'from-components-badge-status-light-normal-halo to-background-gradient-mask-transparent', }, } satisfies Record export type ToastType = keyof typeof TOAST_TONE_STYLES export type ToastAddOptions = Omit, 'data' | 'positionerProps' | 'type'> & { type?: ToastType } export type ToastUpdateOptions = Omit, 'data' | 'positionerProps' | 'type'> & { type?: ToastType } export type ToastOptions = Omit export type TypedToastOptions = Omit type ToastPromiseResultOption = string | ToastUpdateOptions | ((value: Value) => string | ToastUpdateOptions) export type ToastPromiseOptions = { loading: string | ToastUpdateOptions success: ToastPromiseResultOption error: ToastPromiseResultOption } export type ToastHostProps = { timeout?: number limit?: number } type ToastDismiss = (toastId?: string) => void type ToastCall = (title: ReactNode, options?: ToastOptions) => string type TypedToastCall = (title: ReactNode, options?: TypedToastOptions) => string export type ToastApi = { (title: ReactNode, options?: ToastOptions): string success: TypedToastCall error: TypedToastCall warning: TypedToastCall info: TypedToastCall dismiss: ToastDismiss update: (toastId: string, options: ToastUpdateOptions) => void promise: (promiseValue: Promise, options: ToastPromiseOptions) => Promise } const toastManager = BaseToast.createToastManager() function isToastType(type: string): type is ToastType { return Object.prototype.hasOwnProperty.call(TOAST_TONE_STYLES, type) } function getToastType(type?: string): ToastType | undefined { return type && isToastType(type) ? type : undefined } function addToast(options: ToastAddOptions) { return toastManager.add(options) } const showToast: ToastCall = (title, options) => addToast({ ...options, title, }) const dismissToast: ToastDismiss = (toastId) => { toastManager.close(toastId) } function createTypedToast(type: ToastType): TypedToastCall { return (title, options) => addToast({ ...options, title, type, }) } function updateToast(toastId: string, options: ToastUpdateOptions) { toastManager.update(toastId, options) } function promiseToast(promiseValue: Promise, options: ToastPromiseOptions) { return toastManager.promise(promiseValue, options) } export const toast: ToastApi = Object.assign( showToast, { success: createTypedToast('success'), error: createTypedToast('error'), warning: createTypedToast('warning'), info: createTypedToast('info'), dismiss: dismissToast, update: updateToast, promise: promiseToast, }, ) function ToastIcon({ type }: { type?: ToastType }) { return type ?