diff --git a/src/Notification.tsx b/src/Notification.tsx index ad9e529..0f68c54 100644 --- a/src/Notification.tsx +++ b/src/Notification.tsx @@ -65,7 +65,7 @@ export interface NotificationProps { // Function onClick?: React.MouseEventHandler; onMouseEnter?: React.MouseEventHandler; - onMouseLeave?: React.MouseEventHandler; + onMouseLeave?: (event?: React.MouseEvent) => void; /** @deprecated Please use `closable.onClose` instead. */ onClose?: () => void; } @@ -144,7 +144,7 @@ const Notification = React.forwardRef((props, onMouseEnter?.(event); } - function onInternalMouseLeave(event: React.MouseEvent) { + function onInternalMouseLeave(event?: React.MouseEvent) { setHovering(false); if (pauseOnHover && !forcedHovering) { onResume(); @@ -158,6 +158,14 @@ const Notification = React.forwardRef((props, onInternalClose(); } + const destroy = useEvent(() => { + if (hovering) { + onInternalMouseLeave(); + } + }); + + React.useEffect(() => destroy, [destroy]); + // ======================== Position ======================== const offsetRef = React.useRef(offset); if (offset !== undefined) { diff --git a/tests/notification-unmount.test.tsx b/tests/notification-unmount.test.tsx new file mode 100644 index 0000000..47ce3d6 --- /dev/null +++ b/tests/notification-unmount.test.tsx @@ -0,0 +1,31 @@ +import { fireEvent, render } from '@testing-library/react'; +import React from 'react'; +import { Notification } from '../src'; + +describe('Notification unmount', () => { + it.each(['hovered', 'never hovered', 'already left'])( + 'only calls leave when still hovered: %s', + (state) => { + const onMouseLeave = vi.fn(); + const { container, unmount } = render( + , + ); + const notice = container.firstElementChild!; + + if (state !== 'never hovered') { + fireEvent.mouseEnter(notice); + } + if (state === 'already left') { + fireEvent.mouseLeave(notice); + expect(onMouseLeave).toHaveBeenCalledTimes(1); + onMouseLeave.mockClear(); + } + + unmount(); + expect(onMouseLeave).toHaveBeenCalledTimes(state === 'hovered' ? 1 : 0); + if (state === 'hovered') { + expect(onMouseLeave).toHaveBeenCalledWith(undefined); + } + }, + ); +});