Skip to content
This repository was archived by the owner on Mar 25, 2025. It is now read-only.
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 24 additions & 22 deletions packages/core/src/Toast/ToastsProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,6 @@ import {
useContext,
useRef,
FC,
Dispatch,
isValidElement,
cloneElement,
ReactNode,
Expand All @@ -18,7 +17,7 @@ import { BaseToast } from './Toast'
import { toastReducer } from './toastReducer'

import { useToastCallbacks, SimpleToastsDurations } from './useToasts'
import { ToastAction, NI, ToastsContext } from './context'
import { ToastsContext } from './context'

export interface ToastsPlacement {
readonly justify: 'center' | 'right'
Expand Down Expand Up @@ -65,12 +64,12 @@ export const ToastsProvider: FC<ToastsProviderProps> = ({
children,
...toastsOptions
}) => {
const __dispatchRef = useRef<Dispatch<ToastAction>>(NI)
const [toasts, dispatch] = useReducer(toastReducer, new Map())

const callbacks = useToastCallbacks(__dispatchRef, toastsOptions)
const callbacks = useToastCallbacks(dispatch, toastsOptions)

return (
<ToastsContext.Provider value={{ ...callbacks, __dispatchRef }}>
<ToastsContext.Provider value={{ ...callbacks, dispatch, toasts }}>
{children}
</ToastsContext.Provider>
)
Expand Down Expand Up @@ -109,25 +108,28 @@ export interface ToastsAnchorProps {
}

export const ToastsAnchor: FC<ToastsAnchorProps> = ({ placement }) => {
const [toasts, dispatch] = useReducer(toastReducer, new Map())
const { hideToast, __dispatchRef } = useContext(ToastsContext)
__dispatchRef.current = dispatch

return (
<ToastsWrapper {...placement}>
<TransitionGroup component={null}>
{[...toasts.entries()].map(([id, props], index) => (
<ToastTransition key={id}>
<BaseToast
key={id}
toastId={id}
zIndex={-index}
dismissToast={hideToast}
{...props}
/>
</ToastTransition>
))}
</TransitionGroup>
<ToastContent />
</ToastsWrapper>
)
}

export const ToastContent = () => {
const { hideToast, toasts } = useContext(ToastsContext)
return (
<TransitionGroup component={null}>
{[...toasts.entries()].map(([id, props], index) => (
<ToastTransition key={id}>
<BaseToast
key={id}
toastId={id}
zIndex={-index}
dismissToast={hideToast}
{...props}
/>
</ToastTransition>
))}
</TransitionGroup>
)
}
10 changes: 7 additions & 3 deletions packages/core/src/Toast/context.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { createContext, ReactNode, MutableRefObject, Dispatch } from 'react'
import { createContext, ReactNode, Dispatch } from 'react'
import { IconType } from '../Icon'
import { ALinkProps, ButtonLinkProps } from '../Link'

Expand All @@ -25,6 +25,8 @@ export interface ProgressToast extends SimpleToast {
}
}

export type ToastsMap = ReadonlyMap<ToastId, BaseToastValue>

export type ShowToastHandler = (toast: BaseToastValue, id?: ToastId) => ToastId
export type HideToastHandler = (id: ToastId) => void
export type SimpleToastCreator = (toast: SimpleToast, id?: ToastId) => ToastId
Expand Down Expand Up @@ -88,7 +90,8 @@ export const NI = () => {
throw new Error(`Not implemented: no ToastContext set`)
}
export interface ToastContextType extends ToastCallbacks {
readonly __dispatchRef: MutableRefObject<Dispatch<ToastAction>>
readonly dispatch: Dispatch<ToastAction>
readonly toasts: ToastsMap
}

export const ToastsContext = createContext<ToastContextType>({
Expand All @@ -102,5 +105,6 @@ export const ToastsContext = createContext<ToastContextType>({
showLoadingToast: NI,
showProgressToast: NI,
showActionToast: NI,
__dispatchRef: { current: NI },
dispatch: NI,
toasts: new Map(),
})
1 change: 1 addition & 0 deletions packages/core/src/Toast/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,4 @@ export {
ToastIconWrapper,
ToastIconType,
} from './toastCreators'
export { ToastContent } from './ToastsProvider'
9 changes: 1 addition & 8 deletions packages/core/src/Toast/toastReducer.ts
Original file line number Diff line number Diff line change
@@ -1,11 +1,4 @@
import {
BaseToastValue,
ToastAction,
ToastActionType,
ToastId,
} from './context'

export type ToastsMap = ReadonlyMap<ToastId, BaseToastValue>
import { ToastAction, ToastActionType, ToastsMap } from './context'

/**
* Given the current state (toast map) and an action,
Expand Down
18 changes: 8 additions & 10 deletions packages/core/src/Toast/useToasts.ts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { MutableRefObject, Dispatch, useContext, useCallback } from 'react'
import { Dispatch, useContext, useCallback } from 'react'

import { createToast, removeToast, removeAllToasts } from './toastActions'
import {
Expand Down Expand Up @@ -30,29 +30,27 @@ export interface SimpleToastsDurations {
}

export const useToastCallbacks = (
dispatchRef: MutableRefObject<Dispatch<ToastAction>>,
dispatch: Dispatch<ToastAction>,
{ success, error, warning, info }: SimpleToastsDurations = {}
): ToastCallbacks => {
const showToast: ShowToastHandler = useCallback(
(toast, id) => {
const toastAction = createToast(toast, id)
dispatchRef.current(toastAction)
dispatch(toastAction)
return toastAction.id
},
[dispatchRef]
[dispatch]
)

const hideToast: HideToastHandler = useCallback(
id => {
const toastAction = removeToast(id)
dispatchRef.current(toastAction)
dispatch(toastAction)
},
[dispatchRef]
[dispatch]
)

const clearToasts = useCallback(() => {
dispatchRef.current(removeAllToasts)
}, [dispatchRef])
const clearToasts = useCallback(() => dispatch(removeAllToasts), [dispatch])

const showSuccessToast: SimpleToastCreator = useCallback(
(toast, id) =>
Expand Down Expand Up @@ -111,7 +109,7 @@ export const useToastCallbacks = (
}

export const useToasts = () => {
const { __dispatchRef, ...callbacks } = useContext(ToastsContext)
const { dispatch, toasts, ...callbacks } = useContext(ToastsContext)

return callbacks
}