diff --git a/src/Operations.tsx b/src/Operations.tsx index 013523f8..64511482 100644 --- a/src/Operations.tsx +++ b/src/Operations.tsx @@ -1,6 +1,7 @@ import Portal from '@rc-component/portal'; import classnames from 'classnames'; import CSSMotion from 'rc-motion'; +import KeyCode from 'rc-util/lib/KeyCode'; import * as React from 'react'; import { useContext } from 'react'; import { PreviewGroupContext } from './context'; @@ -75,6 +76,22 @@ const Operations: React.FC = props => { const { rotateLeft, rotateRight, zoomIn, zoomOut, close, left, right, flipX, flipY } = icons; const toolClassName = `${prefixCls}-operations-operation`; + React.useEffect(() => { + const onKeyDown = (e: KeyboardEvent) => { + if (e.keyCode === KeyCode.ESC) { + onClose(); + } + }; + + if (visible) { + window.addEventListener('keydown', onKeyDown); + } + + return () => { + window.removeEventListener('keydown', onKeyDown); + }; + }, [visible]); + const tools = [ { icon: flipY, diff --git a/tests/preview.test.tsx b/tests/preview.test.tsx index 712a5c64..486c5f3b 100644 --- a/tests/preview.test.tsx +++ b/tests/preview.test.tsx @@ -861,4 +861,34 @@ describe('Preview', () => { expect(document.querySelector('video')).toBeTruthy(); }); + + it('should be closed when press esc after click portal', () => { + const onVisibleChange = jest.fn(); + const { container } = render( + , + ); + + fireEvent.click(container.querySelector('.rc-image')); + act(() => { + jest.runAllTimers(); + }); + + expect(document.querySelector('.rc-image-preview')).toBeTruthy(); + + expect(onVisibleChange).toBeCalledWith(true, false); + + fireEvent.click(document.querySelector('.rc-image-preview-operations')); + + fireEvent.keyDown(window, { key: 'Escape', keyCode: 27 }); + + expect(onVisibleChange).toBeCalledWith(false, true); + expect(onVisibleChange).toBeCalledTimes(2); + + onVisibleChange.mockRestore(); + }); });