diff --git a/src/core/containerObserver.ts b/src/core/containerObserver.ts index f6e69dbe..f5f387dd 100644 --- a/src/core/containerObserver.ts +++ b/src/core/containerObserver.ts @@ -98,8 +98,11 @@ export function createContainerObserver( notify(); dispatchChanges(toToastItem(toast, isNew ? 'added' : 'updated')); - if (isNew && isFn(onOpen)) - onOpen(isValidElement(children) && children.props); + if (isNew) { + if (isFn(containerProps.onOpen)) + containerProps.onOpen(isValidElement(children) && children.props); + if (isFn(onOpen)) onOpen(isValidElement(children) && children.props); + } }; const buildToast = ( @@ -119,6 +122,9 @@ export function createContainerObserver( const toastProps = { ...props, + // dont propagate the handlers called above for the container to the toast + onOpen: undefined, + onClose: undefined, style: props.toastStyle, key: toastKey++, ...Object.fromEntries( @@ -142,6 +148,8 @@ export function createContainerObserver( deleteToast() { const toastToRemove = toasts.get(toastId)!; const { onClose, children } = toastToRemove.props; + if (isFn(containerProps.onClose)) + containerProps.onClose(isValidElement(children) && children.props); if (isFn(onClose)) onClose(isValidElement(children) && children.props); dispatchChanges(toToastItem(toastToRemove, 'removed')); diff --git a/src/core/toast.cy.tsx b/src/core/toast.cy.tsx index b344d2b1..9caad028 100644 --- a/src/core/toast.cy.tsx +++ b/src/core/toast.cy.tsx @@ -34,6 +34,49 @@ describe('without container', () => { }); }); +describe('with container event handlers', () => { + it('calls container open and close', () => { + const onOpen = cy.stub().as('onContainerOpen'); + const onClose = cy.stub().as('onContainerClose'); + cy.mount( + + ); + toast('msg'); + cy.resolveEntranceAnimation(); + cy.findByText('msg').should('exist').click().should('not.exist'); + cy.get('@onContainerOpen').should('have.been.calledOnce'); + cy.get('@onContainerClose').should('have.been.calledOnce'); + }); + + it('calls container open and close and toast open and close', () => { + const onOpen = cy.stub().as('onContainerOpen'); + const onClose = cy.stub().as('onContainerClose'); + cy.mount( + + ); + toast('msg', { + onOpen: cy.stub().as('onToastOpen'), + onClose: cy.stub().as('onToastClose') + }); + cy.resolveEntranceAnimation(); + cy.findByText('msg').should('exist').click().should('not.exist'); + cy.get('@onContainerOpen').should('have.been.calledOnce'); + cy.get('@onContainerClose').should('have.been.calledOnce'); + cy.get('@onToastOpen').should('have.been.calledOnce'); + cy.get('@onToastClose').should('have.been.calledOnce'); + }); +}); + describe('with container', () => { beforeEach(() => { cy.mount(); diff --git a/src/types.ts b/src/types.ts index c7c4fd78..be78bf57 100644 --- a/src/types.ts +++ b/src/types.ts @@ -183,13 +183,6 @@ interface CommonOptions { * `Default: 'light'` */ theme?: Theme; -} - -export interface ToastOptions extends CommonOptions { - /** - * An optional css class to set. - */ - className?: ToastClassName; /** * Called when toast is mounted. @@ -200,6 +193,13 @@ export interface ToastOptions extends CommonOptions { * Called when toast is unmounted. */ onClose?: (props: T) => void; +} + +export interface ToastOptions extends CommonOptions { + /** + * An optional css class to set. + */ + className?: ToastClassName; /** * An optional inline style to apply.