Skip to content

Commit d093098

Browse files
committed
fix: optimize ESC key handling in nested portal scenarios
1 parent b4c7b99 commit d093098

4 files changed

Lines changed: 56 additions & 16 deletions

File tree

docs/examples/nested.tsx

Lines changed: 6 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,4 @@
11
import React, { useState } from 'react';
2-
import { Button, Divider } from 'antd';
32
import Dialog from '@rc-component/dialog';
43
import Image from '@rc-component/image';
54
import '@rc-component/dialog/assets/index.css';
@@ -9,13 +8,13 @@ const App: React.FC = () => {
98
const [show, setShow] = useState(false);
109
return (
1110
<>
12-
<Button
11+
<button
1312
onClick={() => {
1413
setShow(true);
1514
}}
1615
>
1716
showModal
18-
</Button>
17+
</button>
1918
<Dialog
2019
visible={show}
2120
afterOpenChange={open => {
@@ -26,21 +25,20 @@ const App: React.FC = () => {
2625
}}
2726
footer={
2827
<>
29-
<Button
28+
<button
3029
onClick={() => {
3130
setShow(false);
3231
}}
3332
>
3433
Cancel
35-
</Button>
36-
<Button
37-
type="primary"
34+
</button>
35+
<button
3836
onClick={() => {
3937
setShow(false);
4038
}}
4139
>
4240
OK
43-
</Button>
41+
</button>
4442
</>
4543
}
4644
>
@@ -49,7 +47,6 @@ const App: React.FC = () => {
4947
alt="svg image"
5048
src="https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg"
5149
/>
52-
<Divider />
5350
<Image.PreviewGroup
5451
preview={{
5552
onChange: (current, prev) =>

src/Preview/index.tsx

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -332,10 +332,6 @@ const Preview: React.FC<PreviewProps> = props => {
332332
if (open) {
333333
const { keyCode } = event;
334334

335-
if (keyCode === KeyCode.ESC) {
336-
onClose?.();
337-
}
338-
339335
if (showLeftOrRightSwitches) {
340336
if (keyCode === KeyCode.LEFT) {
341337
onActive(-1);
@@ -380,6 +376,12 @@ const Preview: React.FC<PreviewProps> = props => {
380376
}
381377
}, [open]);
382378

379+
const onEsc: PortalProps['onEsc'] = ({ top }) => {
380+
if (top) {
381+
onClose?.();
382+
}
383+
};
384+
383385
// ========================== Render ==========================
384386
const bodyStyle: React.CSSProperties = {
385387
...styles.body,
@@ -389,7 +391,13 @@ const Preview: React.FC<PreviewProps> = props => {
389391
}
390392

391393
return (
392-
<Portal open={portalRender} getContainer={getContainer} autoLock={lockScroll}>
394+
<Portal
395+
open={portalRender && open}
396+
autoDestroy={false}
397+
getContainer={getContainer}
398+
autoLock={lockScroll}
399+
onEsc={onEsc}
400+
>
393401
<CSSMotion
394402
motionName={motionName}
395403
visible={portalRender && open}

tests/preview.test.tsx

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,8 @@ import ZoomInOutlined from '@ant-design/icons/ZoomInOutlined';
77
import ZoomOutOutlined from '@ant-design/icons/ZoomOutOutlined';
88
import { spyElementPrototypes } from '@rc-component/util/lib/test/domHook';
99
import { act, createEvent, fireEvent, render } from '@testing-library/react';
10-
import React from 'react';
10+
import React, { useState } from 'react';
11+
import Dialog from '@rc-component/dialog';
1112

1213
jest.mock('../src/Preview', () => {
1314
const MockPreview = (props: any) => {
@@ -1052,6 +1053,39 @@ describe('Preview', () => {
10521053
expect(afterOpenChange).toHaveBeenCalledTimes(2);
10531054
});
10541055

1056+
it('Esc closes preview then modal', () => {
1057+
function NestedTestDemo({ onClose }: { onClose: () => void }) {
1058+
const [visible, setVisible] = useState(false);
1059+
const [open, setOpen] = useState(false);
1060+
return (
1061+
<>
1062+
<button onClick={() => setVisible(true)}>open</button>
1063+
<Dialog visible={visible} onClose={onClose}>
1064+
<Image
1065+
src="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png"
1066+
preview={{ open, onOpenChange: setOpen }}
1067+
/>
1068+
</Dialog>
1069+
</>
1070+
);
1071+
}
1072+
1073+
const onClose = jest.fn();
1074+
const { baseElement, getByRole } = render(<NestedTestDemo onClose={onClose} />);
1075+
1076+
fireEvent.click(getByRole('button'));
1077+
expect(getByRole('dialog')).toBeTruthy();
1078+
1079+
fireEvent.click(getByRole('img'));
1080+
expect(baseElement.querySelector('.rc-image-preview')).toBeTruthy();
1081+
1082+
fireEvent.keyDown(window, { key: 'Escape' });
1083+
expect(baseElement.querySelector('.rc-image-preview')).toBeFalsy();
1084+
1085+
fireEvent.keyDown(window, { key: 'Escape' });
1086+
expect(onClose).toHaveBeenCalled();
1087+
});
1088+
10551089
it('not modify preview image size', () => {
10561090
render(
10571091
<Image

tsconfig.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
"@/*": ["src/*"],
1212
"@@/*": [".dumi/tmp/*"],
1313
"@rc-component/image": ["src/index.ts"]
14-
}
14+
},
15+
"types": ["@testing-library/jest-dom", "jest", "node"]
1516
}
1617
}

0 commit comments

Comments
 (0)