Skip to content

Commit 0a961d7

Browse files
authored
fix: optimize ESC key handling in nested portal scenarios (#494)
* add reproduce demo * chore: adjust * fix: optimize ESC key handling in nested portal scenarios * chore: adjust test * update
1 parent d3985c4 commit 0a961d7

File tree

8 files changed

+120
-9
lines changed

8 files changed

+120
-9
lines changed

.gitignore

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -44,4 +44,5 @@ es/
4444
.dumi/tmp
4545
.dumi/tmp-production
4646

47-
bun.lockb
47+
bun.lockb
48+
.vscode

assets/preview.less

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
overflow: hidden;
66
user-select: none;
77
inset: 0;
8+
z-index: 1055;
89

910
&-mask {
1011
position: absolute;

docs/demo/nested.md

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
---
2+
title: nested
3+
nav:
4+
title: Demo
5+
path: /demo
6+
---
7+
8+
<code src="../examples/nested.tsx"></code>

docs/examples/nested.tsx

Lines changed: 71 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,71 @@
1+
import React, { useState } from 'react';
2+
import Dialog from '@rc-component/dialog';
3+
import Image from '@rc-component/image';
4+
import '@rc-component/dialog/assets/index.css';
5+
import '../../assets/index.less';
6+
7+
const App: React.FC = () => {
8+
const [show, setShow] = useState(false);
9+
return (
10+
<>
11+
<button
12+
onClick={() => {
13+
setShow(true);
14+
}}
15+
>
16+
showModal
17+
</button>
18+
<Dialog
19+
visible={show}
20+
afterOpenChange={open => {
21+
setShow(open);
22+
}}
23+
onClose={() => {
24+
setShow(false);
25+
}}
26+
footer={
27+
<>
28+
<button
29+
onClick={() => {
30+
setShow(false);
31+
}}
32+
>
33+
Cancel
34+
</button>
35+
<button
36+
onClick={() => {
37+
setShow(false);
38+
}}
39+
>
40+
OK
41+
</button>
42+
</>
43+
}
44+
>
45+
<Image
46+
width={200}
47+
alt="svg image"
48+
src="https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg"
49+
/>
50+
<Image.PreviewGroup
51+
preview={{
52+
onChange: (current, prev) =>
53+
console.log(`current index: ${current}, prev index: ${prev}`),
54+
}}
55+
>
56+
<Image
57+
width={200}
58+
alt="svg image"
59+
src="https://gw.alipayobjects.com/zos/rmsportal/KDpgvguMpGfqaHPjicRK.svg"
60+
/>
61+
<Image
62+
width={200}
63+
src="https://gw.alipayobjects.com/zos/antfincdn/aPkFc8Sj7n/method-draw-image.svg"
64+
/>
65+
</Image.PreviewGroup>
66+
</Dialog>
67+
</>
68+
);
69+
};
70+
71+
export default App;

package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,14 +41,15 @@
4141
},
4242
"dependencies": {
4343
"@rc-component/motion": "^1.0.0",
44-
"@rc-component/portal": "^2.0.0",
44+
"@rc-component/portal": "^2.1.2",
4545
"@rc-component/util": "^1.3.0",
4646
"clsx": "^2.1.1"
4747
},
4848
"devDependencies": {
4949
"@ant-design/icons": "^5.0.1",
5050
"@rc-component/father-plugin": "^2.0.2",
5151
"@rc-component/np": "^1.0.0",
52+
"@rc-component/dialog": "^1.7.0",
5253
"@testing-library/jest-dom": "^6.4.0",
5354
"@testing-library/react": "^15.0.6",
5455
"@types/jest": "^30.0.0",

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: 21 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,25 @@ describe('Preview', () => {
10521053
expect(afterOpenChange).toHaveBeenCalledTimes(2);
10531054
});
10541055

1056+
it('Esc closes preview then modal', () => {
1057+
const onClose = jest.fn();
1058+
1059+
const { baseElement, getByRole } = render(
1060+
<Dialog visible onClose={onClose}>
1061+
<Image src="https://zos.alipayobjects.com/rmsportal/jkjgkEfvpUPVyRjUImniVslZfWPnJuuZ.png" />
1062+
</Dialog>,
1063+
);
1064+
1065+
fireEvent.click(getByRole('img'));
1066+
expect(baseElement.querySelector('.rc-image-preview')).toBeTruthy();
1067+
1068+
fireEvent.keyDown(window, { key: 'Escape' });
1069+
expect(baseElement.querySelector('.rc-image-preview')).toBeFalsy();
1070+
1071+
fireEvent.keyDown(window, { key: 'Escape' });
1072+
expect(onClose).toHaveBeenCalled();
1073+
});
1074+
10551075
it('not modify preview image size', () => {
10561076
render(
10571077
<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)