mirror of https://github.com/acid-info/lsd.git
fix: implements PR comment changes
This commit is contained in:
parent
24ccbd04b2
commit
7041359c44
|
@ -2,23 +2,23 @@ export const toastClasses = {
|
|||
root: `lsd-toast`,
|
||||
|
||||
inlineContainer: 'lsd-toast__inline-container',
|
||||
blockContainer: 'lsd-toast__block-container',
|
||||
columnContainer: 'lsd-toast__column-container',
|
||||
|
||||
large: 'lsd-toast--large',
|
||||
medium: 'lsd-toast--medium',
|
||||
small: 'lsd-toast--small',
|
||||
|
||||
icon: 'lsd-toast__icon',
|
||||
|
||||
textContainer: 'lsd-toast__text-container',
|
||||
columnIconContainer: 'lsd-toast__column-icon-container',
|
||||
inlineIconContainer: 'lsd-toast__inline-icon-container',
|
||||
title: 'lsd-toast__title',
|
||||
information: 'lsd-toast__information',
|
||||
|
||||
inlineButtonContainer: 'lsd-toast__inline-button-container',
|
||||
hiddenButtonContainer: 'lsd-toast__hidden-button-container',
|
||||
blockButton: 'lsd-toast__block-button',
|
||||
columnButtonContainer: 'lsd-toast__column-button-container',
|
||||
buttonContainer: 'lsd-toast__button-container',
|
||||
|
||||
closeButton: 'lsd-toast__close-button',
|
||||
actionButton: 'lsd-toast__action-button',
|
||||
|
||||
errorIcon: 'lsd-toast__error-icon',
|
||||
errorIconContainer: 'lsd-toast__error-icon-container',
|
||||
}
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
import { Meta, Story } from '@storybook/react'
|
||||
import { Toast, ToastProps } from './Toast'
|
||||
import { Button } from '../Button'
|
||||
|
||||
export default {
|
||||
title: 'Toast',
|
||||
|
@ -15,13 +16,11 @@ export default {
|
|||
} as Meta
|
||||
|
||||
export const Root: Story<ToastProps> = (args) => {
|
||||
return <Toast {...args} />
|
||||
return <Toast {...args} actions={<Button>Button</Button>} />
|
||||
}
|
||||
|
||||
Root.args = {
|
||||
title: 'Toast Title',
|
||||
information: '',
|
||||
size: 'large',
|
||||
buttonText: 'Click me',
|
||||
inline: true,
|
||||
}
|
||||
|
|
|
@ -4,51 +4,42 @@ import { toastClasses } from './Toast.classes'
|
|||
export const ToastStyles = css`
|
||||
.${toastClasses.root} {
|
||||
box-sizing: border-box;
|
||||
display: flex;
|
||||
position: fixed;
|
||||
display: inline-flex;
|
||||
align-items: center;
|
||||
background: rgb(var(--lsd-surface-primary));
|
||||
border: 1px solid rgb(var(--lsd-border-primary));
|
||||
padding: 8px;
|
||||
|
||||
z-index: 9999;
|
||||
|
||||
height: fit-content;
|
||||
}
|
||||
|
||||
.${toastClasses.inlineButtonContainer} {
|
||||
margin: 0 8px;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.${toastClasses.hiddenButtonContainer} {
|
||||
visibility: hidden;
|
||||
}
|
||||
|
||||
.${toastClasses.blockButton} {
|
||||
.${toastClasses.columnButtonContainer} {
|
||||
margin-top: 18px;
|
||||
margin-bottom: 12px;
|
||||
margin-bottom: 6px;
|
||||
}
|
||||
|
||||
.${toastClasses.inlineContainer} {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
flex-grow: 1;
|
||||
}
|
||||
|
||||
.${toastClasses.blockContainer} {
|
||||
.${toastClasses.columnContainer} {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
flex-direction: column;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.${toastClasses.textContainer} {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
flex-grow: 1;
|
||||
color: rgb(var(--lsd-text-secondary));
|
||||
margin-left: 32px;
|
||||
padding-left: 12px;
|
||||
}
|
||||
|
||||
.${toastClasses.title} {
|
||||
|
@ -59,11 +50,11 @@ export const ToastStyles = css`
|
|||
margin-top: 4px;
|
||||
}
|
||||
|
||||
.${toastClasses.actionButton} {
|
||||
height: 28px;
|
||||
.${toastClasses.buttonContainer} {
|
||||
min-height: 28px;
|
||||
min-width: 60px;
|
||||
width: fit-content;
|
||||
padding: 6px 12px;
|
||||
padding: 0px 12px;
|
||||
}
|
||||
|
||||
.${toastClasses.closeButton} {
|
||||
|
@ -71,39 +62,43 @@ export const ToastStyles = css`
|
|||
flex-shrink: 0;
|
||||
height: 28px;
|
||||
width: 28px;
|
||||
|
||||
margin-left: auto;
|
||||
}
|
||||
|
||||
.${toastClasses.errorIconContainer} {
|
||||
width: 26px;
|
||||
.${toastClasses.columnIconContainer} {
|
||||
display: flex;
|
||||
position: relative;
|
||||
justify-content: center;
|
||||
margin-bottom: auto;
|
||||
|
||||
position: relative;
|
||||
top: 4px;
|
||||
padding-left: 4px;
|
||||
}
|
||||
|
||||
.${toastClasses.errorIcon} {
|
||||
position: absolute;
|
||||
top: 3px;
|
||||
left: -26px;
|
||||
.${toastClasses.inlineIconContainer} {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
padding-left: 4px;
|
||||
}
|
||||
|
||||
.${toastClasses.icon} {
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.${toastClasses.large} {
|
||||
.${toastClasses.textContainer} {
|
||||
min-width: 204px;
|
||||
}
|
||||
width: 364px;
|
||||
}
|
||||
|
||||
.${toastClasses.medium} {
|
||||
.${toastClasses.textContainer} {
|
||||
min-width: 184px;
|
||||
}
|
||||
width: 336px;
|
||||
}
|
||||
|
||||
.${toastClasses.small} {
|
||||
.${toastClasses.textContainer} {
|
||||
min-width: 144px;
|
||||
}
|
||||
width: 296px;
|
||||
|
||||
.${toastClasses.errorIcon} {
|
||||
.${toastClasses.icon} {
|
||||
top: 0px;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -5,60 +5,63 @@ import {
|
|||
useCommonProps,
|
||||
} from '../../utils/useCommonProps'
|
||||
import { toastClasses } from './Toast.classes'
|
||||
import { CloseIcon, ErrorIcon } from '../Icons'
|
||||
import { CloseIcon, ErrorIcon, LsdIconProps } from '../Icons'
|
||||
import { IconButton } from '../IconButton'
|
||||
import { Typography } from '../Typography'
|
||||
import { Button } from '../Button'
|
||||
|
||||
export type ToastProps = CommonProps &
|
||||
Omit<React.HTMLAttributes<HTMLDivElement>, 'label'> & {
|
||||
isOpen?: boolean
|
||||
title: string
|
||||
information?: string
|
||||
inline?: boolean
|
||||
buttonText?: string
|
||||
onButtonClick?: () => void
|
||||
onClose?: () => void
|
||||
size?: 'large' | 'medium' | 'small'
|
||||
toastRefFunction?: (el: HTMLDivElement | null) => void
|
||||
toastRef?: React.Ref<HTMLDivElement>
|
||||
icon?: React.ComponentType<LsdIconProps> | null | false
|
||||
actions?: React.ReactNode
|
||||
}
|
||||
|
||||
export const Toast: React.FC<ToastProps> & {
|
||||
classes: typeof toastClasses
|
||||
} = ({
|
||||
isOpen,
|
||||
title,
|
||||
information,
|
||||
inline = true,
|
||||
buttonText,
|
||||
onButtonClick,
|
||||
onClose,
|
||||
size = 'large',
|
||||
toastRefFunction,
|
||||
toastRef,
|
||||
children,
|
||||
icon,
|
||||
actions,
|
||||
...props
|
||||
}) => {
|
||||
const commonProps = useCommonProps(props)
|
||||
const isInlineButtonHidden = !inline || !!information || !buttonText
|
||||
const isInline = !information
|
||||
|
||||
// If the toast is not open, do not render anything.
|
||||
if (isOpen === false) {
|
||||
return null
|
||||
}
|
||||
const Icon = typeof icon === 'undefined' ? ErrorIcon : icon
|
||||
|
||||
return (
|
||||
<div
|
||||
ref={toastRefFunction}
|
||||
ref={toastRef}
|
||||
{...omitCommonProps(props)}
|
||||
className={clsx(
|
||||
props.className,
|
||||
commonProps.className,
|
||||
toastClasses.root,
|
||||
toastClasses[size],
|
||||
)}
|
||||
>
|
||||
<div
|
||||
className={clsx(
|
||||
isInline
|
||||
? toastClasses.inlineIconContainer
|
||||
: toastClasses.columnIconContainer,
|
||||
)}
|
||||
>
|
||||
{Icon && <Icon color="primary" className={toastClasses.icon} />}
|
||||
</div>
|
||||
|
||||
<div
|
||||
className={
|
||||
inline ? toastClasses.inlineContainer : toastClasses.blockContainer
|
||||
isInline ? toastClasses.inlineContainer : toastClasses.columnContainer
|
||||
}
|
||||
>
|
||||
<div className={clsx(toastClasses.textContainer)}>
|
||||
|
@ -68,11 +71,6 @@ export const Toast: React.FC<ToastProps> & {
|
|||
component="div"
|
||||
variant={size === 'small' ? 'label2' : 'label1'}
|
||||
>
|
||||
<ErrorIcon
|
||||
color="primary"
|
||||
className={toastClasses.errorIcon}
|
||||
style={{ width: '16px' }}
|
||||
/>
|
||||
{title}
|
||||
</Typography>
|
||||
)}
|
||||
|
@ -86,30 +84,20 @@ export const Toast: React.FC<ToastProps> & {
|
|||
{information}
|
||||
</Typography>
|
||||
)}
|
||||
|
||||
{!inline && !!buttonText && (
|
||||
<Button
|
||||
onClick={onButtonClick}
|
||||
className={clsx(
|
||||
toastClasses.actionButton,
|
||||
toastClasses.blockButton,
|
||||
)}
|
||||
>
|
||||
{buttonText}
|
||||
</Button>
|
||||
)}
|
||||
</div>
|
||||
|
||||
{!!actions && (
|
||||
<div
|
||||
className={clsx(
|
||||
toastClasses.inlineButtonContainer,
|
||||
isInlineButtonHidden && toastClasses.hiddenButtonContainer,
|
||||
toastClasses.buttonContainer,
|
||||
isInline
|
||||
? toastClasses.inlineButtonContainer
|
||||
: toastClasses.columnButtonContainer,
|
||||
)}
|
||||
>
|
||||
<Button onClick={onButtonClick} className={toastClasses.actionButton}>
|
||||
{`${isInlineButtonHidden ? '' : buttonText}`}
|
||||
</Button>
|
||||
{actions}
|
||||
</div>
|
||||
)}
|
||||
</div>
|
||||
|
||||
<IconButton
|
||||
|
|
|
@ -1,3 +1,9 @@
|
|||
export const toastProviderClasses = {
|
||||
toastsContainer: `lsd-toast-provider__toasts-container`,
|
||||
toastContainer: `lsd-toast-provider__toast-container`,
|
||||
topLeft: `lsd-toast-provider__toast--top-left`,
|
||||
topCenter: `lsd-toast-provider__toast--top-center`,
|
||||
topRight: `lsd-toast-provider__toast--top-right`,
|
||||
bottomLeft: `lsd-toast-provider__toast--bottom-left`,
|
||||
bottomCenter: `lsd-toast-provider__toast--bottom-center`,
|
||||
bottomRight: `lsd-toast-provider__toast--bottom-right`,
|
||||
}
|
||||
|
|
|
@ -1,9 +1,11 @@
|
|||
import { Meta, Story } from '@storybook/react'
|
||||
import { ToastProps } from '../Toast'
|
||||
import { ToastProvider, useLSDToast } from './ToastProvider'
|
||||
import {
|
||||
ToastContantAndOptions,
|
||||
ToastProvider,
|
||||
useToast,
|
||||
} from './ToastProvider'
|
||||
import { FC } from 'react'
|
||||
import { Button } from '../Button'
|
||||
import { ToastOptions } from 'react-hot-toast'
|
||||
import { pickCommonProps } from '../../utils/useCommonProps'
|
||||
|
||||
export default {
|
||||
|
@ -16,31 +18,43 @@ export default {
|
|||
value: ['small', 'medium', 'large'],
|
||||
},
|
||||
},
|
||||
position: {
|
||||
type: {
|
||||
name: 'enum',
|
||||
value: [
|
||||
'top-left',
|
||||
'top-center',
|
||||
'top-right',
|
||||
'bottom-left',
|
||||
'bottom-center',
|
||||
'bottom-right',
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
} as Meta
|
||||
|
||||
type ToastButtonProps = {
|
||||
toastArgs: ToastProps & ToastOptions
|
||||
}
|
||||
|
||||
const ToastButton: FC<ToastButtonProps> = ({ toastArgs }) => {
|
||||
const showToast = useLSDToast()
|
||||
const ToastButton: FC<ToastContantAndOptions> = ({
|
||||
information,
|
||||
title,
|
||||
...toastArgs
|
||||
}) => {
|
||||
const showToast = useToast()
|
||||
|
||||
return (
|
||||
<Button
|
||||
{...pickCommonProps(toastArgs)}
|
||||
onClick={() => showToast(toastArgs, { duration: toastArgs.duration })}
|
||||
style={{ marginBottom: 8 }}
|
||||
onClick={() => showToast({ title, information }, { ...toastArgs })}
|
||||
>
|
||||
Show Toast
|
||||
</Button>
|
||||
)
|
||||
}
|
||||
|
||||
export const Root: Story<ToastProps & ToastOptions> = (args) => {
|
||||
export const Root: Story<ToastContantAndOptions> = (args) => {
|
||||
return (
|
||||
<ToastProvider>
|
||||
<ToastButton toastArgs={args} />
|
||||
<ToastButton {...args} />
|
||||
</ToastProvider>
|
||||
)
|
||||
}
|
||||
|
@ -49,7 +63,6 @@ Root.args = {
|
|||
title: 'Toast Title',
|
||||
information: '',
|
||||
size: 'large',
|
||||
buttonText: 'Click me',
|
||||
inline: true,
|
||||
position: 'top-center',
|
||||
duration: 4000,
|
||||
}
|
||||
|
|
|
@ -2,6 +2,31 @@ import { css } from '@emotion/react'
|
|||
import { toastProviderClasses } from './ToastProvider.classes'
|
||||
|
||||
export const ToastProviderStyles = css`
|
||||
.${toastProviderClasses.toastsContainer} {
|
||||
.${toastProviderClasses.toastContainer} {
|
||||
position: fixed;
|
||||
|
||||
transition: all 230ms cubic-bezier(0.21, 1.02, 0.73, 1);
|
||||
|
||||
z-index: 9999;
|
||||
}
|
||||
|
||||
.${toastProviderClasses.topLeft},
|
||||
.${toastProviderClasses.topCenter},
|
||||
.${toastProviderClasses.topRight} {
|
||||
top: 0;
|
||||
}
|
||||
|
||||
.${toastProviderClasses.bottomLeft},
|
||||
.${toastProviderClasses.bottomCenter},
|
||||
.${toastProviderClasses.bottomRight} {
|
||||
bottom: 0;
|
||||
}
|
||||
|
||||
.${toastProviderClasses.topCenter}, .${toastProviderClasses.bottomCenter} {
|
||||
left: 50%;
|
||||
}
|
||||
|
||||
.${toastProviderClasses.topRight}, .${toastProviderClasses.bottomRight} {
|
||||
right: 0;
|
||||
}
|
||||
`
|
||||
|
|
|
@ -1,41 +1,94 @@
|
|||
import React, { createContext, useContext, ReactNode } from 'react'
|
||||
import {
|
||||
ToastOptions,
|
||||
ToastOptions as HotToastOptions,
|
||||
useToaster,
|
||||
toast as hotToast,
|
||||
} from 'react-hot-toast/headless'
|
||||
import { Toast, ToastProps } from '../Toast'
|
||||
import { toastProviderClasses } from './ToastProvider.classes'
|
||||
import { ToastPosition } from 'react-hot-toast'
|
||||
import { Portal } from '../PortalProvider/Portal'
|
||||
import clsx from 'clsx'
|
||||
|
||||
type ShowToastType = (props: ToastProps, options?: ToastOptions) => void
|
||||
|
||||
export const ToastContext = createContext<null | ShowToastType>(null)
|
||||
|
||||
type ToastsProps = {
|
||||
toastsPropsMap: Map<string, ToastProps>
|
||||
export type ToastContent = {
|
||||
title: ToastProps['title']
|
||||
information: ToastProps['information']
|
||||
}
|
||||
|
||||
const Toasts: React.FC<ToastsProps> = ({ toastsPropsMap }) => {
|
||||
export type ToastOptions = Pick<HotToastOptions, 'position' | 'duration'> &
|
||||
Omit<ToastProps, 'title' | 'information'>
|
||||
|
||||
export type ToastContantAndOptions = ToastContent & ToastOptions
|
||||
|
||||
type ShowToastType = (content: ToastContent, options?: ToastOptions) => void
|
||||
|
||||
const getPositionStyle = (
|
||||
position: ToastPosition | undefined,
|
||||
offset: number,
|
||||
): { positionClassName: string; transform: string } => {
|
||||
if (!position)
|
||||
return { positionClassName: '', transform: `translateY(${offset}px)` }
|
||||
|
||||
let positionClassName = ''
|
||||
const isCenter = position.includes('center')
|
||||
const isBottom = position.includes('bottom')
|
||||
// Dynamic style part, not included in CSS classes.
|
||||
const transform = `translateY(${isBottom ? -offset : offset}px) translateX(${
|
||||
isCenter ? '-50%' : '0'
|
||||
})`
|
||||
|
||||
if (position === 'top-left') {
|
||||
positionClassName = toastProviderClasses.topLeft
|
||||
} else if (position === 'top-center') {
|
||||
positionClassName = toastProviderClasses.topCenter
|
||||
} else if (position === 'top-right') {
|
||||
positionClassName = toastProviderClasses.topRight
|
||||
} else if (position === 'bottom-left') {
|
||||
positionClassName = toastProviderClasses.bottomLeft
|
||||
} else if (position === 'bottom-center') {
|
||||
positionClassName = toastProviderClasses.bottomCenter
|
||||
} else if (position === 'bottom-right') {
|
||||
positionClassName = toastProviderClasses.bottomRight
|
||||
}
|
||||
|
||||
return {
|
||||
positionClassName,
|
||||
transform,
|
||||
}
|
||||
}
|
||||
|
||||
type ToastContextType = ShowToastType | null
|
||||
|
||||
export const ToastContext = createContext<ToastContextType>(null)
|
||||
|
||||
type ToastContainerProps = React.HTMLAttributes<HTMLDivElement> & {
|
||||
toastsPropsMap: Map<string, ToastContantAndOptions>
|
||||
}
|
||||
|
||||
const ToastContainer: React.FC<ToastContainerProps> = ({
|
||||
toastsPropsMap,
|
||||
className,
|
||||
...containerProps
|
||||
}) => {
|
||||
const { toasts, handlers } = useToaster()
|
||||
const { startPause, endPause, calculateOffset, updateHeight } = handlers
|
||||
|
||||
return (
|
||||
<div
|
||||
onMouseEnter={startPause}
|
||||
onMouseLeave={endPause}
|
||||
className={toastProviderClasses.toastsContainer}
|
||||
>
|
||||
<Portal id="toast">
|
||||
{toasts.map((toast) => {
|
||||
const customProps = toastsPropsMap.get(toast.id)
|
||||
const propsMapValue = toastsPropsMap.get(toast.id)
|
||||
|
||||
if (!customProps) {
|
||||
console.error('Could not find toast with id', toast.id)
|
||||
if (!propsMapValue) {
|
||||
console.warn('Could not find toast with id', toast.id)
|
||||
return null
|
||||
}
|
||||
|
||||
const { position, duration, ...customProps } = propsMapValue
|
||||
|
||||
const offset = calculateOffset(toast, {
|
||||
reverseOrder: false,
|
||||
gutter: 8,
|
||||
defaultPosition: position,
|
||||
})
|
||||
|
||||
const ref = (el: HTMLDivElement | null) => {
|
||||
|
@ -45,29 +98,47 @@ const Toasts: React.FC<ToastsProps> = ({ toastsPropsMap }) => {
|
|||
}
|
||||
}
|
||||
|
||||
const { transform: positionTransform, positionClassName } =
|
||||
getPositionStyle(position, offset)
|
||||
|
||||
return (
|
||||
<div
|
||||
key={`container-${toast.id}`}
|
||||
onMouseEnter={startPause}
|
||||
onMouseLeave={endPause}
|
||||
{...containerProps}
|
||||
className={clsx(
|
||||
toastProviderClasses.toastContainer,
|
||||
positionClassName,
|
||||
className,
|
||||
)}
|
||||
style={{
|
||||
transform: positionTransform,
|
||||
...containerProps.style,
|
||||
}}
|
||||
>
|
||||
<Toast
|
||||
key={toast.id}
|
||||
toastRefFunction={ref}
|
||||
style={{
|
||||
transition: 'all 0.5s ease-out',
|
||||
opacity: toast.visible ? 1 : 0,
|
||||
transform: `translateY(${offset}px)`,
|
||||
}}
|
||||
{...toast.ariaProps}
|
||||
className={clsx(customProps.className)}
|
||||
toastRef={ref}
|
||||
{...customProps}
|
||||
style={{
|
||||
opacity: toast.visible ? 1 : 0,
|
||||
...customProps.style,
|
||||
}}
|
||||
onClose={() => {
|
||||
hotToast.dismiss(toast.id)
|
||||
customProps.onClose?.()
|
||||
}}
|
||||
/>
|
||||
</div>
|
||||
)
|
||||
})}
|
||||
</div>
|
||||
</Portal>
|
||||
)
|
||||
}
|
||||
|
||||
export function useLSDToast() {
|
||||
export function useToast() {
|
||||
const context = useContext(ToastContext)
|
||||
if (!context) {
|
||||
throw new Error('useToast must be used within a ToastProvider')
|
||||
|
@ -75,25 +146,39 @@ export function useLSDToast() {
|
|||
return context
|
||||
}
|
||||
|
||||
type ToastProviderProps = {
|
||||
type ToastProviderProps = React.HTMLAttributes<HTMLDivElement> & {
|
||||
providerToastOptions?: ToastOptions
|
||||
children: ReactNode
|
||||
}
|
||||
|
||||
export const ToastProvider: React.FC<ToastProviderProps> = ({ children }) => {
|
||||
export const ToastProvider: React.FC<ToastProviderProps> = ({
|
||||
providerToastOptions,
|
||||
children,
|
||||
...toastsContainerProps
|
||||
}) => {
|
||||
const [toastsPropsMap, setToastsPropsMap] = React.useState<
|
||||
Map<string, ToastProps>
|
||||
Map<string, ToastContantAndOptions>
|
||||
>(new Map())
|
||||
|
||||
const showToast: ShowToastType = (toastProps, options) => {
|
||||
const showToast: ShowToastType = (content, showToastOptions) => {
|
||||
// There are 2 ways to define the toast options:
|
||||
// 1. Globally, in the ToastProvider component's props.
|
||||
// 2. Per-toast, in the showToast function's second argument.
|
||||
// The per-toast options override the global options.
|
||||
const options = {
|
||||
...providerToastOptions,
|
||||
...showToastOptions,
|
||||
}
|
||||
|
||||
// The toast function displays the toast, and returns its ID.
|
||||
// The message is '' because we're not using it - currently
|
||||
// we use the Toast component's 'title' and 'information' props to display info.
|
||||
const toastId = hotToast('', options)
|
||||
const toastId = hotToast('', { duration: options?.duration })
|
||||
|
||||
if (toastProps) {
|
||||
if (content) {
|
||||
setToastsPropsMap((prev) => {
|
||||
const newMap = new Map(prev)
|
||||
newMap.set(toastId, toastProps)
|
||||
newMap.set(toastId, { ...content, ...options })
|
||||
return newMap
|
||||
})
|
||||
}
|
||||
|
@ -102,7 +187,10 @@ export const ToastProvider: React.FC<ToastProviderProps> = ({ children }) => {
|
|||
return (
|
||||
<ToastContext.Provider value={showToast}>
|
||||
{children}
|
||||
<Toasts toastsPropsMap={toastsPropsMap} />
|
||||
<ToastContainer
|
||||
toastsPropsMap={toastsPropsMap}
|
||||
{...toastsContainerProps}
|
||||
/>
|
||||
</ToastContext.Provider>
|
||||
)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue