Skip to content

Commit 579d037

Browse files
author
刘欢
committed
feat: Merge 'AfterClose' to 'Closable'
1 parent 302f4f4 commit 579d037

File tree

5 files changed

+48
-7
lines changed

5 files changed

+48
-7
lines changed

README.md

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -64,13 +64,12 @@ ReactDOM.render(
6464
| maskTransitionName | String | | mask animation css class name | |
6565
| title | String\|React.Element | | Title of the dialog | |
6666
| footer | React.Element | | footer of the dialog | |
67-
| closable | Boolean \| ({ closeIcon?: React.ReactNode; disabled?: boolean } & React.AriaAttributes | true | whether show close button | |
67+
| closable | Boolean \| ({ closeIcon?: React.ReactNode; disabled?: boolean, afterClose:function } & React.AriaAttributes) | true | whether show close button | |
6868
| mask | Boolean | true | whether show mask | |
6969
| maskClosable | Boolean | true | whether click mask to close | |
7070
| keyboard | Boolean | true | whether support press esc to close | |
7171
| mousePosition | {x:number,y:number} | | set pageX and pageY of current mouse(it will cause transform origin to be set). | |
7272
| onClose | function() | | called when click close button or mask | |
73-
| afterClose | function() | | called when close animation end | |
7473
| getContainer | function(): HTMLElement | | to determine where Dialog will be mounted | |
7574
| destroyOnHidden | Boolean | false | to unmount child compenents on onClose | |
7675
| closeIcon | ReactNode | | specific the close icon. | |

src/Dialog/index.tsx

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import KeyCode from '@rc-component/util/lib/KeyCode';
55
import pickAttrs from '@rc-component/util/lib/pickAttrs';
66
import * as React from 'react';
77
import { useEffect, useRef } from 'react';
8-
import type { IDialogPropTypes } from '../IDialogPropTypes';
8+
import type { ClosableType, IDialogPropTypes } from '../IDialogPropTypes';
99
import { getMotionName } from '../util';
1010
import Content, { type ContentRef } from './Content';
1111
import Mask from './Mask';
@@ -95,7 +95,7 @@ const Dialog: React.FC<IDialogPropTypes> = (props) => {
9595

9696
// Trigger afterClose only when change visible from true to false
9797
if (animatedVisible) {
98-
afterClose?.();
98+
((closable as ClosableType)?.afterClose ?? afterClose)?.();
9999
}
100100
}
101101

src/DialogWrap.tsx

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ import Portal from '@rc-component/portal';
22
import * as React from 'react';
33
import { RefContext } from './context';
44
import Dialog from './Dialog';
5-
import type { IDialogPropTypes } from './IDialogPropTypes';
5+
import type { ClosableType, IDialogPropTypes } from './IDialogPropTypes';
66

77
// fix issue #10656
88
/*
@@ -20,6 +20,7 @@ const DialogWrap: React.FC<IDialogPropTypes> = (props) => {
2020
forceRender,
2121
destroyOnHidden = false,
2222
afterClose,
23+
closable,
2324
panelRef,
2425
} = props;
2526
const [animatedVisible, setAnimatedVisible] = React.useState<boolean>(visible);
@@ -49,7 +50,7 @@ const DialogWrap: React.FC<IDialogPropTypes> = (props) => {
4950
{...props}
5051
destroyOnHidden={destroyOnHidden}
5152
afterClose={() => {
52-
afterClose?.();
53+
((closable as ClosableType)?.afterClose ?? afterClose)?.();
5354
setAnimatedVisible(false);
5455
}}
5556
/>

src/IDialogPropTypes.tsx

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,17 +7,24 @@ export type ModalClassNames = Partial<Record<SemanticName, string>>;
77

88
export type ModalStyles = Partial<Record<SemanticName, CSSProperties>>;
99

10+
export type ClosableType = {
11+
closeIcon?: React.ReactNode;
12+
disabled?: boolean;
13+
afterClose?: () => any;
14+
};
15+
1016
export type IDialogPropTypes = {
1117
className?: string;
1218
keyboard?: boolean;
1319
style?: CSSProperties;
1420
rootStyle?: CSSProperties;
1521
mask?: boolean;
1622
children?: React.ReactNode;
23+
/** @description please use `closable.afterClose` instead */
1724
afterClose?: () => any;
1825
afterOpenChange?: (open: boolean) => void;
1926
onClose?: (e: SyntheticEvent) => any;
20-
closable?: boolean | ({ closeIcon?: React.ReactNode; disabled?: boolean } & React.AriaAttributes);
27+
closable?: boolean | (ClosableType & React.AriaAttributes);
2128
maskClosable?: boolean;
2229
visible?: boolean;
2330
destroyOnHidden?: boolean;

tests/index.spec.tsx

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -552,6 +552,40 @@ describe('dialog', () => {
552552

553553
expect(afterClose).toHaveBeenCalledTimes(0);
554554
});
555+
556+
it('should trigger closable.afterClose when using new API', () => {
557+
const afterClose = jest.fn();
558+
559+
const { rerender } = render(<Dialog closable={{ afterClose }} visible />);
560+
act(() => {
561+
jest.runAllTimers();
562+
});
563+
564+
rerender(<Dialog closable={{ afterClose }} visible={false} />);
565+
act(() => {
566+
jest.runAllTimers();
567+
});
568+
expect(afterClose).toHaveBeenCalledTimes(1);
569+
});
570+
571+
it('should prioritize closable.afterClose when both exist', () => {
572+
const afterClose = jest.fn();
573+
const legacyAfterClose = jest.fn();
574+
575+
const { rerender } = render(
576+
<Dialog closable={{ afterClose }} afterClose={legacyAfterClose} visible />,
577+
);
578+
act(() => {
579+
jest.runAllTimers();
580+
});
581+
582+
rerender(<Dialog closable={{ afterClose }} afterClose={legacyAfterClose} visible={false} />);
583+
act(() => {
584+
jest.runAllTimers();
585+
});
586+
expect(afterClose).toHaveBeenCalledTimes(1);
587+
expect(legacyAfterClose).toHaveBeenCalledTimes(0);
588+
});
555589
});
556590

557591
describe('afterOpenChange', () => {

0 commit comments

Comments
 (0)