import * as React from 'react' ; import * as PropTypes from 'prop-types' ; import { Container } from 'reakit' ; import { ActionMap , EffectMap } from 'constate/dist/ts/src' ; import _uniqueId from 'lodash/uniqueId' ; import { Placement , placementPropType } from '../types' ; import { LocalToastProps } from './Toast' ; type Toast = LocalToastProps & { key ? : string ; message : string | React . ReactElement < any > ; } ; type Actions = { remove : ( { key } : { key : Toast [ 'key' ] ; } ) => void ; } ; type Effects = { add : ( toast : Toast ) => void ; info : ( toast : Toast ) => void ; success : ( toast : Toast ) => void ; danger : ( toast : Toast ) => void ; warning : ( toast : Toast ) => void ; } ; type State = { toasts : Array < Toast > ; props : { } ; } ; export type ToastContainerProps = { children : ( props : Actions & Effects & { toasts : Array < Toast > ; } ) => React . ReactNode ; placement ? : Placement ; } ; const initialState = { autoDismissTimeout : 5000 , toasts : [ ] } ; const add = ( toast ) => ( { setState , state } ) => { const { placement } = state . props ; const key = _uniqueId ( 'toast-' ) ; const autoDismissTimeout = typeof toast . autoDismissTimeout === 'number' ? toast . autoDismissTimeout : state . autoDismissTimeout ; setState ( ( state ) => ( { toasts : [ ... ( placement . includes ( 'bottom' ) ? state . toasts : [ ] ) , { key , autoDismissTimeout , ... toast } , ... ( ! placement . includes ( 'bottom' ) ? state . toasts : [ ] ) ] } ) ) ; if ( autoDismissTimeout > 0 ) { setTimeout ( ( ) => setState ( ( state ) => ( { toasts : state . toasts . filter ( toast => toast . key !== key ) } ) ) , toast . autoDismissTimeout || state . autoDismissTimeout ) ; } } ; const effects = { add , info : ( toast ) => add ( { ... toast , type : 'info' } ) , success : ( toast ) => add ( { ... toast , type : 'success' } ) , danger : ( toast ) => add ( { ... toast , type : 'danger' } ) , warning : ( toast ) => add ( { ... toast , type : 'warning' } ) } ; const actions = { remove : ( { key } ) => state => ( { toasts : state . toasts . filter ( toast => toast . key !== key ) } ) } ; export const ToastContainer = ( { children , ... props } ) => ( < Container context = "toasts" initialState = { { ... initialState , props } } actions = { actions } effects = { effects } > { children } < /Container>); export const toastContainerPropTypes = { children : PropTypes . func . isRequired , placement : placementPropType } ; ToastContainer . propTypes = toastContainerPropTypes ; export const toastContainerDefaultProps = { placement : 'top-end' } ; ToastContainer . defaultProps = toastContainerDefaultProps ; export default ToastContainer ; export const withToasts = ( C ) => ( props ) => ( < ToastContainer > { toast => < C toast = { toast } { ... props } />}</ToastContainer > ) ;